diff options
| author | gingerBill <bill@gingerbill.org> | 2021-08-31 22:21:13 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2021-08-31 22:21:13 +0100 |
| commit | 251da264ed6e0f039931683c7b0d4b97e88c8d99 (patch) | |
| tree | c7a9a088477d2452c2cf850458c62d994a211df6 /core | |
| parent | b176af27427a6c39448a71a8023e4a9877f0a51c (diff) | |
Remove unneeded semicolons from the core library
Diffstat (limited to 'core')
187 files changed, 27512 insertions, 27512 deletions
diff --git a/core/bufio/lookahead_reader.odin b/core/bufio/lookahead_reader.odin index 04ce2fb6b..7d6d7832c 100644 --- a/core/bufio/lookahead_reader.odin +++ b/core/bufio/lookahead_reader.odin @@ -14,14 +14,14 @@ Loadahead_Reader :: struct { } lookahead_reader_init :: proc(lr: ^Loadahead_Reader, r: io.Reader, buf: []byte) -> ^Loadahead_Reader { - lr.r = r; - lr.buf = buf; - lr.n = 0; - return lr; + lr.r = r + lr.buf = buf + lr.n = 0 + return lr } lookahead_reader_buffer :: proc(lr: ^Loadahead_Reader) -> []byte { - return lr.buf[:lr.n]; + return lr.buf[:lr.n] } @@ -31,35 +31,35 @@ lookahead_reader_buffer :: proc(lr: ^Loadahead_Reader) -> []byte { lookahead_reader_peek :: proc(lr: ^Loadahead_Reader, n: int) -> ([]byte, io.Error) { switch { case n < 0: - return nil, .Negative_Read; + return nil, .Negative_Read case n > len(lr.buf): - return nil, .Buffer_Full; + return nil, .Buffer_Full } - n := n; - err: io.Error; - read_count: int; + n := n + err: io.Error + read_count: int if lr.n < n { - read_count, err = io.read_at_least(lr.r, lr.buf[lr.n:], n-lr.n); + read_count, err = io.read_at_least(lr.r, lr.buf[lr.n:], n-lr.n) if err == .Unexpected_EOF { - err = .EOF; + err = .EOF } } - lr.n += read_count; + lr.n += read_count if n > lr.n { - n = lr.n; + n = lr.n } - return lr.buf[:n], err; + return lr.buf[:n], err } // lookahead_reader_peek_all returns a slice of the Lookahead_Reader populating the full buffer // If the Lookahead_Reader cannot hold enough bytes, it will read from the underlying reader to populate the rest. // NOTE: The returned buffer is not a copy of the underlying buffer lookahead_reader_peek_all :: proc(lr: ^Loadahead_Reader) -> ([]byte, io.Error) { - return lookahead_reader_peek(lr, len(lr.buf)); + return lookahead_reader_peek(lr, len(lr.buf)) } @@ -67,17 +67,17 @@ lookahead_reader_peek_all :: proc(lr: ^Loadahead_Reader) -> ([]byte, io.Error) { lookahead_reader_consume :: proc(lr: ^Loadahead_Reader, n: int) -> io.Error { switch { case n == 0: - return nil; + return nil case n < 0: - return .Negative_Read; + return .Negative_Read case lr.n < n: - return .Short_Buffer; + return .Short_Buffer } - copy(lr.buf, lr.buf[n:lr.n]); - lr.n -= n; - return nil; + copy(lr.buf, lr.buf[n:lr.n]) + lr.n -= n + return nil } lookahead_reader_consume_all :: proc(lr: ^Loadahead_Reader) -> io.Error { - return lookahead_reader_consume(lr, lr.n); + return lookahead_reader_consume(lr, lr.n) } diff --git a/core/bufio/read_writer.odin b/core/bufio/read_writer.odin index f60e17d2d..9026abcfd 100644 --- a/core/bufio/read_writer.odin +++ b/core/bufio/read_writer.odin @@ -10,59 +10,59 @@ Read_Writer :: struct { read_writer_init :: proc(rw: ^Read_Writer, r: ^Reader, w: ^Writer) { - rw.r, rw.w = r, w; + rw.r, rw.w = r, w } read_writer_to_stream :: proc(rw: ^Read_Writer) -> (s: io.Stream) { - s.stream_data = rw; - s.stream_vtable = _read_writer_vtable; - return; + s.stream_data = rw + s.stream_vtable = _read_writer_vtable + return } @(private) _read_writer_vtable := &io.Stream_VTable{ impl_read = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) { - b := (^Read_Writer)(s.stream_data).r; - return reader_read(b, p); + b := (^Read_Writer)(s.stream_data).r + return reader_read(b, p) }, impl_read_byte = proc(s: io.Stream) -> (c: byte, err: io.Error) { - b := (^Read_Writer)(s.stream_data).r; - return reader_read_byte(b); + b := (^Read_Writer)(s.stream_data).r + return reader_read_byte(b) }, impl_unread_byte = proc(s: io.Stream) -> io.Error { - b := (^Read_Writer)(s.stream_data).r; - return reader_unread_byte(b); + b := (^Read_Writer)(s.stream_data).r + return reader_unread_byte(b) }, impl_read_rune = proc(s: io.Stream) -> (r: rune, size: int, err: io.Error) { - b := (^Read_Writer)(s.stream_data).r; - return reader_read_rune(b); + b := (^Read_Writer)(s.stream_data).r + return reader_read_rune(b) }, impl_unread_rune = proc(s: io.Stream) -> io.Error { - b := (^Read_Writer)(s.stream_data).r; - return reader_unread_rune(b); + b := (^Read_Writer)(s.stream_data).r + return reader_unread_rune(b) }, impl_write_to = proc(s: io.Stream, w: io.Writer) -> (n: i64, err: io.Error) { - b := (^Read_Writer)(s.stream_data).r; - return reader_write_to(b, w); + b := (^Read_Writer)(s.stream_data).r + return reader_write_to(b, w) }, impl_flush = proc(s: io.Stream) -> io.Error { - b := (^Read_Writer)(s.stream_data).w; - return writer_flush(b); + b := (^Read_Writer)(s.stream_data).w + return writer_flush(b) }, impl_write = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) { - b := (^Read_Writer)(s.stream_data).w; - return writer_write(b, p); + b := (^Read_Writer)(s.stream_data).w + return writer_write(b, p) }, impl_write_byte = proc(s: io.Stream, c: byte) -> io.Error { - b := (^Read_Writer)(s.stream_data).w; - return writer_write_byte(b, c); + b := (^Read_Writer)(s.stream_data).w + return writer_write_byte(b, c) }, impl_write_rune = proc(s: io.Stream, r: rune) -> (int, io.Error) { - b := (^Read_Writer)(s.stream_data).w; - return writer_write_rune(b, r); + b := (^Read_Writer)(s.stream_data).w + return writer_write_rune(b, r) }, impl_read_from = proc(s: io.Stream, r: io.Reader) -> (n: i64, err: io.Error) { - b := (^Read_Writer)(s.stream_data).w; - return writer_read_from(b, r); + b := (^Read_Writer)(s.stream_data).w + return writer_read_from(b, r) }, -}; +} diff --git a/core/bufio/reader.odin b/core/bufio/reader.odin index 27f157630..f17519656 100644 --- a/core/bufio/reader.odin +++ b/core/bufio/reader.odin @@ -22,85 +22,85 @@ Reader :: struct { } -DEFAULT_BUF_SIZE :: 4096; +DEFAULT_BUF_SIZE :: 4096 @(private) -MIN_READ_BUFFER_SIZE :: 16; +MIN_READ_BUFFER_SIZE :: 16 @(private) -DEFAULT_MAX_CONSECUTIVE_EMPTY_READS :: 128; +DEFAULT_MAX_CONSECUTIVE_EMPTY_READS :: 128 reader_init :: proc(b: ^Reader, rd: io.Reader, size: int = DEFAULT_BUF_SIZE, allocator := context.allocator) { - size := size; - size = max(size, MIN_READ_BUFFER_SIZE); - reader_reset(b, rd); - b.buf_allocator = allocator; - b.buf = make([]byte, size, allocator); + size := size + size = max(size, MIN_READ_BUFFER_SIZE) + reader_reset(b, rd) + b.buf_allocator = allocator + b.buf = make([]byte, size, allocator) } reader_init_with_buf :: proc(b: ^Reader, rd: io.Reader, buf: []byte) { - reader_reset(b, rd); - b.buf_allocator = {}; - b.buf = buf; + reader_reset(b, rd) + b.buf_allocator = {} + b.buf = buf } // reader_destroy destroys the underlying buffer with its associated allocator IFF that allocator has been set reader_destroy :: proc(b: ^Reader) { - delete(b.buf, b.buf_allocator); - b^ = {}; + delete(b.buf, b.buf_allocator) + b^ = {} } reader_size :: proc(b: ^Reader) -> int { - return len(b.buf); + return len(b.buf) } reader_reset :: proc(b: ^Reader, r: io.Reader) { - b.rd = r; - b.r, b.w = 0, 0; - b.err = nil; - b.last_byte = -1; - b.last_rune_size = -1; + b.rd = r + b.r, b.w = 0, 0 + b.err = nil + b.last_byte = -1 + b.last_rune_size = -1 } @(private) _reader_read_new_chunk :: proc(b: ^Reader) -> io.Error { if b.r > 0 { - copy(b.buf, b.buf[b.r:b.w]); - b.w -= b.r; - b.r = 0; + copy(b.buf, b.buf[b.r:b.w]) + b.w -= b.r + b.r = 0 } if b.w >= len(b.buf) { - return .Buffer_Full; + return .Buffer_Full } if b.max_consecutive_empty_reads <= 0 { - b.max_consecutive_empty_reads = DEFAULT_MAX_CONSECUTIVE_EMPTY_READS; + b.max_consecutive_empty_reads = DEFAULT_MAX_CONSECUTIVE_EMPTY_READS } // read new data, and try a limited number of times for i := b.max_consecutive_empty_reads; i > 0; i -= 1 { - n, err := io.read(b.rd, b.buf[b.w:]); + n, err := io.read(b.rd, b.buf[b.w:]) if n < 0 { - return .Negative_Read; + return .Negative_Read } - b.w += n; + b.w += n if err != nil { - b.err = err; - return nil; + b.err = err + return nil } if n > 0 { - return nil; + return nil } } - b.err = .No_Progress; - return nil; + b.err = .No_Progress + return nil } @(private) _reader_consume_err :: proc(b: ^Reader) -> io.Error { - err := b.err; - b.err = nil; - return err; + err := b.err + b.err = nil + return err } // reader_peek returns the next n bytes without advancing the reader @@ -109,151 +109,151 @@ _reader_consume_err :: proc(b: ^Reader) -> io.Error { // explaining why the read is short // The error will be .Buffer_Full if n is larger than the internal buffer size reader_peek :: proc(b: ^Reader, n: int) -> (data: []byte, err: io.Error) { - n := n; + n := n if n < 0 { - return nil, .Negative_Count; + return nil, .Negative_Count } - b.last_byte = -1; - b.last_rune_size = -1; + b.last_byte = -1 + b.last_rune_size = -1 for b.w-b.r < n && b.w-b.r < len(b.buf) && b.err == nil { if fill_err := _reader_read_new_chunk(b); fill_err != nil { - return nil, fill_err; + return nil, fill_err } } if n > len(b.buf) { - return b.buf[b.r : b.w], .Buffer_Full; + return b.buf[b.r : b.w], .Buffer_Full } if available := b.w - b.r; available < n { - n = available; - err = _reader_consume_err(b); + n = available + err = _reader_consume_err(b) if err == nil { - err = .Buffer_Full; + err = .Buffer_Full } } - return b.buf[b.r : b.r+n], err; + return b.buf[b.r : b.r+n], err } // reader_buffered returns the number of bytes that can be read from the current buffer reader_buffered :: proc(b: ^Reader) -> int { - return b.w - b.r; + return b.w - b.r } // reader_discard skips the next n bytes, and returns the number of bytes that were discarded reader_discard :: proc(b: ^Reader, n: int) -> (discarded: int, err: io.Error) { if n < 0 { - return 0, .Negative_Count; + return 0, .Negative_Count } if n == 0 { - return; + return } - remaining := n; + remaining := n for { - skip := reader_buffered(b); + skip := reader_buffered(b) if skip == 0 { if fill_err := _reader_read_new_chunk(b); fill_err != nil { - return 0, fill_err; + return 0, fill_err } - skip = reader_buffered(b); + skip = reader_buffered(b) } - skip = min(skip, remaining); - b.r += skip; - remaining -= skip; + skip = min(skip, remaining) + b.r += skip + remaining -= skip if remaining == 0 { - return n, nil; + return n, nil } if b.err != nil { - return n - remaining, _reader_consume_err(b); + return n - remaining, _reader_consume_err(b) } } - return; + return } // reader_read reads data into p // The bytes are taken from at most one read on the underlying Reader, which means n may be less than len(p) reader_read :: proc(b: ^Reader, p: []byte) -> (n: int, err: io.Error) { - n = len(p); + n = len(p) if n == 0 { if reader_buffered(b) > 0 { - return 0, nil; + return 0, nil } - return 0, _reader_consume_err(b); + return 0, _reader_consume_err(b) } if b.r == b.w { if b.err != nil { - return 0, _reader_consume_err(b); + return 0, _reader_consume_err(b) } if len(p) >= len(b.buf) { - n, b.err = io.read(b.rd, p); + n, b.err = io.read(b.rd, p) if n < 0 { - return 0, .Negative_Read; + return 0, .Negative_Read } if n > 0 { - b.last_byte = int(p[n-1]); - b.last_rune_size = -1; + b.last_byte = int(p[n-1]) + b.last_rune_size = -1 } - return n, _reader_consume_err(b); + return n, _reader_consume_err(b) } - b.r, b.w = 0, 0; - n, b.err = io.read(b.rd, b.buf); + b.r, b.w = 0, 0 + n, b.err = io.read(b.rd, b.buf) if n < 0 { - return 0, .Negative_Read; + return 0, .Negative_Read } if n == 0 { - return 0, _reader_consume_err(b); + return 0, _reader_consume_err(b) } - b.w += n; + b.w += n } - n = copy(p, b.buf[b.r:b.w]); - b.r += n; - b.last_byte = int(b.buf[b.r-1]); - b.last_rune_size = -1; - return n, nil; + n = copy(p, b.buf[b.r:b.w]) + b.r += n + b.last_byte = int(b.buf[b.r-1]) + b.last_rune_size = -1 + return n, nil } // reader_read_byte reads and returns a single byte // If no byte is available, it return an error reader_read_byte :: proc(b: ^Reader) -> (byte, io.Error) { - b.last_rune_size = -1; + b.last_rune_size = -1 for b.r == b.w { if b.err != nil { - return 0, _reader_consume_err(b); + return 0, _reader_consume_err(b) } if err := _reader_read_new_chunk(b); err != nil { - return 0, err; + return 0, err } } - c := b.buf[b.r]; - b.r += 1; - b.last_byte = int(c); - return c, nil; + c := b.buf[b.r] + b.r += 1 + b.last_byte = int(c) + return c, nil } // reader_unread_byte unreads the last byte. Only the most recently read byte can be unread reader_unread_byte :: proc(b: ^Reader) -> io.Error { if b.last_byte < 0 || b.r == 0 && b.w > 0 { - return .Invalid_Unread; + return .Invalid_Unread } if b.r > 0 { - b.r -= 1; + b.r -= 1 } else { // b.r == 0 && b.w == 0 - b.w = 1; + b.w = 1 } - b.buf[b.r] = byte(b.last_byte); - b.last_byte = -1; - b.last_rune_size = -1; - return nil; + b.buf[b.r] = byte(b.last_byte) + b.last_byte = -1 + b.last_rune_size = -1 + return nil } // reader_read_rune reads a single UTF-8 encoded unicode character @@ -265,96 +265,96 @@ reader_read_rune :: proc(b: ^Reader) -> (r: rune, size: int, err: io.Error) { b.err == nil && b.w-b.w < len(b.buf) { if err = _reader_read_new_chunk(b); err != nil { - return; + return } } - b.last_rune_size = -1; + b.last_rune_size = -1 if b.r == b.w { - err = _reader_consume_err(b); - return; + err = _reader_consume_err(b) + return } - r, size = rune(b.buf[b.r]), 1; + r, size = rune(b.buf[b.r]), 1 if r >= utf8.RUNE_SELF { - r, size = utf8.decode_rune(b.buf[b.r : b.w]); + r, size = utf8.decode_rune(b.buf[b.r : b.w]) } - b.r += size; - b.last_byte = int(b.buf[b.r-1]); - b.last_rune_size = size; - return; + b.r += size + b.last_byte = int(b.buf[b.r-1]) + b.last_rune_size = size + return } // reader_unread_rune unreads the last rune. Only the most recently read rune can be unread reader_unread_rune :: proc(b: ^Reader) -> io.Error { if b.last_rune_size < 0 || b.r < b.last_rune_size { - return .Invalid_Unread; + return .Invalid_Unread } - b.r -= b.last_rune_size; - b.last_byte = -1; - b.last_rune_size = -1; - return nil; + b.r -= b.last_rune_size + b.last_byte = -1 + b.last_rune_size = -1 + return nil } reader_write_to :: proc(b: ^Reader, w: io.Writer) -> (n: i64, err: io.Error) { write_buf :: proc(b: ^Reader, w: io.Writer) -> (i64, io.Error) { - n, err := io.write(w, b.buf[b.r:b.w]); + n, err := io.write(w, b.buf[b.r:b.w]) if n < 0 { - return 0, .Negative_Write; + return 0, .Negative_Write } - b.r += n; - return i64(n), err; + b.r += n + return i64(n), err } - n, err = write_buf(b, w); + n, err = write_buf(b, w) if err != nil { - return; + return } - m: i64; + m: i64 if nr, ok := io.to_writer_to(b.rd); ok { - m, err = io.write_to(nr, w); - n += m; - return n, err; + m, err = io.write_to(nr, w) + n += m + return n, err } if nw, ok := io.to_reader_from(w); ok { - m, err = io.read_from(nw, b.rd); - n += m; - return n, err; + m, err = io.read_from(nw, b.rd) + n += m + return n, err } if b.w-b.r < len(b.buf) { if err = _reader_read_new_chunk(b); err != nil { - return; + return } } for b.r < b.w { - m, err = write_buf(b, w); - n += m; + m, err = write_buf(b, w) + n += m if err != nil { - return; + return } if err = _reader_read_new_chunk(b); err != nil { - return; + return } } if b.err == .EOF { - b.err = nil; + b.err = nil } - err = _reader_consume_err(b); - return; + err = _reader_consume_err(b) + return } // reader_to_stream converts a Reader into an io.Stream reader_to_stream :: proc(b: ^Reader) -> (s: io.Stream) { - s.stream_data = b; - s.stream_vtable = _reader_vtable; - return; + s.stream_data = b + s.stream_vtable = _reader_vtable + return } @@ -362,35 +362,35 @@ reader_to_stream :: proc(b: ^Reader) -> (s: io.Stream) { @(private) _reader_vtable := &io.Stream_VTable{ impl_destroy = proc(s: io.Stream) -> io.Error { - b := (^Reader)(s.stream_data); - reader_destroy(b); - return nil; + b := (^Reader)(s.stream_data) + reader_destroy(b) + return nil }, impl_read = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) { - b := (^Reader)(s.stream_data); - return reader_read(b, p); + b := (^Reader)(s.stream_data) + return reader_read(b, p) }, impl_read_byte = proc(s: io.Stream) -> (c: byte, err: io.Error) { - b := (^Reader)(s.stream_data); - return reader_read_byte(b); + b := (^Reader)(s.stream_data) + return reader_read_byte(b) }, impl_unread_byte = proc(s: io.Stream) -> io.Error { - b := (^Reader)(s.stream_data); - return reader_unread_byte(b); + b := (^Reader)(s.stream_data) + return reader_unread_byte(b) }, impl_read_rune = proc(s: io.Stream) -> (r: rune, size: int, err: io.Error) { - b := (^Reader)(s.stream_data); - return reader_read_rune(b); + b := (^Reader)(s.stream_data) + return reader_read_rune(b) }, impl_unread_rune = proc(s: io.Stream) -> io.Error { - b := (^Reader)(s.stream_data); - return reader_unread_rune(b); + b := (^Reader)(s.stream_data) + return reader_unread_rune(b) }, impl_write_to = proc(s: io.Stream, w: io.Writer) -> (n: i64, err: io.Error) { - b := (^Reader)(s.stream_data); - return reader_write_to(b, w); + b := (^Reader)(s.stream_data) + return reader_write_to(b, w) }, -}; +} @@ -410,71 +410,71 @@ _reader_vtable := &io.Stream_VTable{ // reader_read_slice returns err != nil if and only if line does not end in delim // reader_read_slice :: proc(b: ^Reader, delim: byte) -> (line: []byte, err: io.Error) { - s := 0; + s := 0 for { if i := bytes.index_byte(b.buf[b.r+s : b.w], delim); i >= 0 { - i += s; - line = b.buf[b.r:][:i+1]; - b.r += i + 1; - break; + i += s + line = b.buf[b.r:][:i+1] + b.r += i + 1 + break } if b.err != nil { - line = b.buf[b.r : b.w]; - b.r = b.w; - err = _reader_consume_err(b); - break; + line = b.buf[b.r : b.w] + b.r = b.w + err = _reader_consume_err(b) + break } if reader_buffered(b) >= len(b.buf) { - b.r = b.w; - line = b.buf; - err = .Buffer_Full; - break; + b.r = b.w + line = b.buf + err = .Buffer_Full + break } - s = b.w - b.r; + s = b.w - b.r if err = _reader_read_new_chunk(b); err != nil { - break; + break } } if i := len(line)-1; i >= 0 { - b.last_byte = int(line[i]); - b.last_rune_size = -1; + b.last_byte = int(line[i]) + b.last_rune_size = -1 } - return; + return } // reader_read_bytes reads until the first occurrence of delim from the Reader // It returns an allocated slice containing the data up to and including the delimiter reader_read_bytes :: proc(b: ^Reader, delim: byte, allocator := context.allocator) -> (buf: []byte, err: io.Error) { - full: [dynamic]byte; - full.allocator = allocator; + full: [dynamic]byte + full.allocator = allocator - frag: []byte; + frag: []byte for { - e: io.Error; - frag, e = reader_read_slice(b, delim); + e: io.Error + frag, e = reader_read_slice(b, delim) if e == nil { - break; + break } if e != .Buffer_Full { - err = e; - break; + err = e + break } - append(&full, ..frag); + append(&full, ..frag) } - append(&full, ..frag); - return full[:], err; + append(&full, ..frag) + return full[:], err } // reader_read_string reads until the first occurrence of delim from the Reader // It returns an allocated string containing the data up to and including the delimiter reader_read_string :: proc(b: ^Reader, delim: byte, allocator := context.allocator) -> (string, io.Error) { - buf, err := reader_read_bytes(b, delim, allocator); - return string(buf), err; + buf, err := reader_read_bytes(b, delim, allocator) + return string(buf), err } diff --git a/core/bufio/scanner.odin b/core/bufio/scanner.odin index 2918764b0..cc3b4533a 100644 --- a/core/bufio/scanner.odin +++ b/core/bufio/scanner.odin @@ -21,7 +21,7 @@ Scanner_Error :: union { } // Split_Proc is the signature of the split procedure used to tokenize the input. -Split_Proc :: proc(data: []byte, at_eof: bool) -> (advance: int, token: []byte, err: Scanner_Error, final_token: bool); +Split_Proc :: proc(data: []byte, at_eof: bool) -> (advance: int, token: []byte, err: Scanner_Error, final_token: bool) Scanner :: struct { r: io.Reader, @@ -40,28 +40,28 @@ Scanner :: struct { done: bool, } -DEFAULT_MAX_SCAN_TOKEN_SIZE :: 1<<16; +DEFAULT_MAX_SCAN_TOKEN_SIZE :: 1<<16 @(private) -_INIT_BUF_SIZE :: 4096; +_INIT_BUF_SIZE :: 4096 scanner_init :: proc(s: ^Scanner, r: io.Reader, buf_allocator := context.allocator) -> ^Scanner { - s.r = r; - s.split = scan_lines; - s.max_token_size = DEFAULT_MAX_SCAN_TOKEN_SIZE; - s.buf.allocator = buf_allocator; - return s; + s.r = r + s.split = scan_lines + s.max_token_size = DEFAULT_MAX_SCAN_TOKEN_SIZE + s.buf.allocator = buf_allocator + return s } scanner_init_with_buffer :: proc(s: ^Scanner, r: io.Reader, buf: []byte) -> ^Scanner { - s.r = r; - s.split = scan_lines; - s.max_token_size = DEFAULT_MAX_SCAN_TOKEN_SIZE; - s.buf = mem.buffer_from_slice(buf); - resize(&s.buf, cap(s.buf)); - return s; + s.r = r + s.split = scan_lines + s.max_token_size = DEFAULT_MAX_SCAN_TOKEN_SIZE + s.buf = mem.buffer_from_slice(buf) + resize(&s.buf, cap(s.buf)) + return s } scanner_destroy :: proc(s: ^Scanner) { - delete(s.buf); + delete(s.buf) } @@ -69,9 +69,9 @@ scanner_destroy :: proc(s: ^Scanner) { scanner_error :: proc(s: ^Scanner) -> Scanner_Error { switch s._err { case .EOF, .None: - return nil; + return nil } - return s._err; + return s._err } // Returns the most recent token created by scanner_scan. @@ -79,7 +79,7 @@ scanner_error :: proc(s: ^Scanner) -> Scanner_Error { // by another call to scanner_scan. // Treat the returned value as if it is immutable. scanner_bytes :: proc(s: ^Scanner) -> []byte { - return s.token; + return s.token } // Returns the most recent token created by scanner_scan. @@ -87,146 +87,146 @@ scanner_bytes :: proc(s: ^Scanner) -> []byte { // by another call to scanner_scan. // Treat the returned value as if it is immutable. scanner_text :: proc(s: ^Scanner) -> string { - return string(s.token); + return string(s.token) } // scanner_scan advances the scanner scanner_scan :: proc(s: ^Scanner) -> bool { set_err :: proc(s: ^Scanner, err: Scanner_Error) { - err := err; + err := err if err == .None { - err = nil; + err = nil } switch s._err { case nil, .EOF: - s._err = err; + s._err = err } } if s.done { - return false; + return false } - s.scan_called = true; + s.scan_called = true for { // Check if a token is possible with what is available // Allow the split procedure to recover if it fails if s.start < s.end || s._err != nil { - advance, token, err, final_token := s.split(s.buf[s.start:s.end], s._err != nil); + advance, token, err, final_token := s.split(s.buf[s.start:s.end], s._err != nil) if final_token { - s.token = token; - s.done = true; - return true; + s.token = token + s.done = true + return true } if err != nil { - set_err(s, err); - return false; + set_err(s, err) + return false } // Do advance if advance < 0 { - set_err(s, .Negative_Advance); - return false; + set_err(s, .Negative_Advance) + return false } if advance > s.end-s.start { - set_err(s, .Advanced_Too_Far); - return false; + set_err(s, .Advanced_Too_Far) + return false } - s.start += advance; + s.start += advance - s.token = token; + s.token = token if s.token != nil { if s._err == nil || advance > 0 { - s.successive_empty_token_count = 0; + s.successive_empty_token_count = 0 } else { - s.successive_empty_token_count += 1; + s.successive_empty_token_count += 1 if s.max_consecutive_empty_reads <= 0 { - s.max_consecutive_empty_reads = DEFAULT_MAX_CONSECUTIVE_EMPTY_READS; + s.max_consecutive_empty_reads = DEFAULT_MAX_CONSECUTIVE_EMPTY_READS } if s.successive_empty_token_count > s.max_consecutive_empty_reads { - set_err(s, .No_Progress); - return false; + set_err(s, .No_Progress) + return false } } - return true; + return true } } // If an error is hit, no token can be created if s._err != nil { - s.start = 0; - s.end = 0; - return false; + s.start = 0 + s.end = 0 + return false } // More data must be required to be read if s.start > 0 && (s.end == len(s.buf) || s.start > len(s.buf)/2) { - copy(s.buf[:], s.buf[s.start:s.end]); - s.end -= s.start; - s.start = 0; + copy(s.buf[:], s.buf[s.start:s.end]) + s.end -= s.start + s.start = 0 } - could_be_too_short := false; + could_be_too_short := false // Resize the buffer if full if s.end == len(s.buf) { if s.max_token_size <= 0 { - s.max_token_size = DEFAULT_MAX_SCAN_TOKEN_SIZE; + s.max_token_size = DEFAULT_MAX_SCAN_TOKEN_SIZE } if len(s.buf) >= s.max_token_size { - set_err(s, .Too_Long); - return false; + set_err(s, .Too_Long) + return false } // overflow check - new_size := _INIT_BUF_SIZE; + new_size := _INIT_BUF_SIZE if len(s.buf) > 0 { - overflowed: bool; + overflowed: bool if new_size, overflowed = intrinsics.overflow_mul(len(s.buf), 2); overflowed { - set_err(s, .Too_Long); - return false; + set_err(s, .Too_Long) + return false } } - old_size := len(s.buf); - new_size = min(new_size, s.max_token_size); - resize(&s.buf, new_size); - s.end -= s.start; - s.start = 0; + old_size := len(s.buf) + new_size = min(new_size, s.max_token_size) + resize(&s.buf, new_size) + s.end -= s.start + s.start = 0 - could_be_too_short = old_size >= len(s.buf); + could_be_too_short = old_size >= len(s.buf) } // Read data into the buffer - loop := 0; + loop := 0 for { - n, err := io.read(s.r, s.buf[s.end:len(s.buf)]); + n, err := io.read(s.r, s.buf[s.end:len(s.buf)]) if n < 0 || len(s.buf)-s.end < n { - set_err(s, .Bad_Read_Count); - break; + set_err(s, .Bad_Read_Count) + break } - s.end += n; + s.end += n if err != nil { - set_err(s, err); - break; + set_err(s, err) + break } if n > 0 { - s.successive_empty_token_count = 0; - break; + s.successive_empty_token_count = 0 + break } - loop += 1; + loop += 1 if s.max_consecutive_empty_reads <= 0 { - s.max_consecutive_empty_reads = DEFAULT_MAX_CONSECUTIVE_EMPTY_READS; + s.max_consecutive_empty_reads = DEFAULT_MAX_CONSECUTIVE_EMPTY_READS } if loop > s.max_consecutive_empty_reads { if could_be_too_short { - set_err(s, .Too_Short); + set_err(s, .Too_Short) } else { - set_err(s, .No_Progress); + set_err(s, .No_Progress) } - break; + break } } } @@ -234,38 +234,38 @@ scanner_scan :: proc(s: ^Scanner) -> bool { scan_bytes :: proc(data: []byte, at_eof: bool) -> (advance: int, token: []byte, err: Scanner_Error, final_token: bool) { if at_eof && len(data) == 0 { - return; + return } - return 1, data[0:1], nil, false; + return 1, data[0:1], nil, false } scan_runes :: proc(data: []byte, at_eof: bool) -> (advance: int, token: []byte, err: Scanner_Error, final_token: bool) { if at_eof && len(data) == 0 { - return; + return } if data[0] < utf8.RUNE_SELF { - advance = 1; - token = data[0:1]; - return; + advance = 1 + token = data[0:1] + return } - _, width := utf8.decode_rune(data); + _, width := utf8.decode_rune(data) if width > 1 { - advance = width; - token = data[0:width]; - return; + advance = width + token = data[0:width] + return } if !at_eof && !utf8.full_rune(data) { - return; + return } - @thread_local ERROR_RUNE := []byte{0xef, 0xbf, 0xbd}; + @thread_local ERROR_RUNE := []byte{0xef, 0xbf, 0xbd} - advance = 1; - token = ERROR_RUNE; - return; + advance = 1 + token = ERROR_RUNE + return } scan_words :: proc(data: []byte, at_eof: bool) -> (advance: int, token: []byte, err: Scanner_Error, final_token: bool) { @@ -273,68 +273,68 @@ scan_words :: proc(data: []byte, at_eof: bool) -> (advance: int, token: []byte, switch r { // lower ones case ' ', '\t', '\n', '\v', '\f', '\r': - return true; + return true case '\u0085', '\u00a0': - return true; + return true // higher ones case '\u2000' ..= '\u200a': - return true; + return true case '\u1680', '\u2028', '\u2029', '\u202f', '\u205f', '\u3000': - return true; + return true } - return false; + return false } // skip spaces at the beginning - start := 0; + start := 0 for width := 0; start < len(data); start += width { - r: rune; - r, width = utf8.decode_rune(data[start:]); + r: rune + r, width = utf8.decode_rune(data[start:]) if !is_space(r) { - break; + break } } for width, i := 0, start; i < len(data); i += width { - r: rune; - r, width = utf8.decode_rune(data[i:]); + r: rune + r, width = utf8.decode_rune(data[i:]) if is_space(r) { - advance = i+width; - token = data[start:i]; - return; + advance = i+width + token = data[start:i] + return } } if at_eof && len(data) > start { - advance = len(data); - token = data[start:]; - return; + advance = len(data) + token = data[start:] + return } - advance = start; - return; + advance = start + return } scan_lines :: proc(data: []byte, at_eof: bool) -> (advance: int, token: []byte, err: Scanner_Error, final_token: bool) { trim_carriage_return :: proc "contextless" (data: []byte) -> []byte { if len(data) > 0 && data[len(data)-1] == '\r' { - return data[0:len(data)-1]; + return data[0:len(data)-1] } - return data; + return data } if at_eof && len(data) == 0 { - return; + return } if i := bytes.index_byte(data, '\n'); i >= 0 { - advance = i+1; - token = trim_carriage_return(data[0:i]); - return; + advance = i+1 + token = trim_carriage_return(data[0:i]) + return } if at_eof { - advance = len(data); - token = trim_carriage_return(data); + advance = len(data) + token = trim_carriage_return(data) } - return; + return } diff --git a/core/bufio/writer.odin b/core/bufio/writer.odin index f2b33d591..861358526 100644 --- a/core/bufio/writer.odin +++ b/core/bufio/writer.odin @@ -20,150 +20,150 @@ Writer :: struct { } writer_init :: proc(b: ^Writer, wr: io.Writer, size: int = DEFAULT_BUF_SIZE, allocator := context.allocator) { - size := size; - size = max(size, MIN_READ_BUFFER_SIZE); - writer_reset(b, wr); - b.buf_allocator = allocator; - b.buf = make([]byte, size, allocator); + size := size + size = max(size, MIN_READ_BUFFER_SIZE) + writer_reset(b, wr) + b.buf_allocator = allocator + b.buf = make([]byte, size, allocator) } writer_init_with_buf :: proc(b: ^Writer, wr: io.Writer, buf: []byte) { - writer_reset(b, wr); - b.buf_allocator = {}; - b.buf = buf; + writer_reset(b, wr) + b.buf_allocator = {} + b.buf = buf } // writer_destroy destroys the underlying buffer with its associated allocator IFF that allocator has been set writer_destroy :: proc(b: ^Writer) { - delete(b.buf, b.buf_allocator); - b^ = {}; + delete(b.buf, b.buf_allocator) + b^ = {} } // writer_size returns the size of underlying buffer in bytes writer_size :: proc(b: ^Writer) -> int { - return len(b.buf); + return len(b.buf) } writer_reset :: proc(b: ^Writer, w: io.Writer) { - b.wr = w; - b.n = 0; - b.err = nil; + b.wr = w + b.n = 0 + b.err = nil } // writer_flush writes any buffered data into the underlying io.Writer writer_flush :: proc(b: ^Writer) -> io.Error { if b.err != nil { - return b.err; + return b.err } if b.n == 0 { - return nil; + return nil } - n, err := io.write(b.wr, b.buf[0:b.n]); + n, err := io.write(b.wr, b.buf[0:b.n]) if n < b.n && err == nil { - err = .Short_Write; + err = .Short_Write } if err != nil { if n > 0 && n < b.n { - copy(b.buf[:b.n-n], b.buf[n : b.n]); + copy(b.buf[:b.n-n], b.buf[n : b.n]) } - b.n -= n; - b.err = err; - return err; + b.n -= n + b.err = err + return err } - b.n = 0; - return nil; + b.n = 0 + return nil } // writer_available returns how many bytes are unused in the buffer writer_available :: proc(b: ^Writer) -> int { - return len(b.buf) - b.n; + return len(b.buf) - b.n } // writer_buffered returns the number of bytes that have been writted into the current buffer writer_buffered :: proc(b: ^Writer) -> int { - return b.n; + return b.n } // writer_write writes the contents of p into the buffer // It returns the number of bytes written // If n < len(p), it will return an error explaining why the write is short writer_write :: proc(b: ^Writer, p: []byte) -> (n: int, err: io.Error) { - p := p; + p := p for len(p) > writer_available(b) && b.err == nil { - m: int; + m: int if writer_buffered(b) == 0 { - m, b.err = io.write(b.wr, p); + m, b.err = io.write(b.wr, p) } else { - m = copy(b.buf[b.n:], p); - b.n += m; - writer_flush(b); + m = copy(b.buf[b.n:], p) + b.n += m + writer_flush(b) } - n += m; - p = p[m:]; + n += m + p = p[m:] } if b.err != nil { - return n, b.err; + return n, b.err } - m := copy(b.buf[b.n:], p); - b.n += m; - m += n; - return m, nil; + m := copy(b.buf[b.n:], p) + b.n += m + m += n + return m, nil } // writer_write_byte writes a single byte writer_write_byte :: proc(b: ^Writer, c: byte) -> io.Error { if b.err != nil { - return b.err; + return b.err } if writer_available(b) <= 0 && writer_flush(b) != nil { - return b.err; + return b.err } - b.buf[b.n] = c; - b.n += 1; - return nil; + b.buf[b.n] = c + b.n += 1 + return nil } // writer_write_rune writes a single unicode code point, and returns the number of bytes written with any error writer_write_rune :: proc(b: ^Writer, r: rune) -> (size: int, err: io.Error) { if r < utf8.RUNE_SELF { - err = writer_write_byte(b, byte(r)); - size = 0 if err != nil else 1; - return; + err = writer_write_byte(b, byte(r)) + size = 0 if err != nil else 1 + return } if b.err != nil { - return 0, b.err; + return 0, b.err } - buf: [4]u8; + buf: [4]u8 - n := writer_available(b); + n := writer_available(b) if n < utf8.UTF_MAX { - writer_flush(b); + writer_flush(b) if b.err != nil { - return 0, b.err; + return 0, b.err } - n = writer_available(b); + n = writer_available(b) if n < utf8.UTF_MAX { // this only happens if the buffer is very small - w: int; - buf, w = utf8.encode_rune(r); - return writer_write(b, buf[:w]); + w: int + buf, w = utf8.encode_rune(r) + return writer_write(b, buf[:w]) } } - buf, size = utf8.encode_rune(r); - copy(b.buf[b.n:], buf[:size]); - b.n += size; - return; + buf, size = utf8.encode_rune(r) + copy(b.buf[b.n:], buf[:size]) + b.n += size + return } // writer_write writes a string into the buffer // It returns the number of bytes written // If n < len(p), it will return an error explaining why the write is short writer_write_string :: proc(b: ^Writer, s: string) -> (int, io.Error) { - return writer_write(b, transmute([]byte)s); + return writer_write(b, transmute([]byte)s) } // writer_read_from is to support io.Reader_From types @@ -171,60 +171,60 @@ writer_write_string :: proc(b: ^Writer, s: string) -> (int, io.Error) { // this procedure calls the underlying read_from implementation without buffering writer_read_from :: proc(b: ^Writer, r: io.Reader) -> (n: i64, err: io.Error) { if b.err != nil { - return 0, b.err; + return 0, b.err } if writer_buffered(b) == 0 { if w, ok := io.to_reader_from(b.wr); !ok { - n, err = io.read_from(w, r); - b.err = err; - return; + n, err = io.read_from(w, r) + b.err = err + return } } for { if writer_available(b) == 0 { - writer_flush(b) or_return; + writer_flush(b) or_return } if b.max_consecutive_empty_writes <= 0 { - b.max_consecutive_empty_writes = DEFAULT_MAX_CONSECUTIVE_EMPTY_READS; + b.max_consecutive_empty_writes = DEFAULT_MAX_CONSECUTIVE_EMPTY_READS } - m: int; - nr := 0; + m: int + nr := 0 for nr < b.max_consecutive_empty_writes { - m, err = io.read(r, b.buf[b.n:]); + m, err = io.read(r, b.buf[b.n:]) if m != 0 || err != nil { - break; + break } - nr += 1; + nr += 1 } if nr == b.max_consecutive_empty_writes { - return n, .No_Progress; + return n, .No_Progress } - b.n += m; - n += i64(m); + b.n += m + n += i64(m) if err != nil { - break; + break } } if err == .EOF { if writer_available(b) == 0 { - err = writer_flush(b); + err = writer_flush(b) } else { - err = nil; + err = nil } } - return; + return } // writer_to_stream converts a Writer into an io.Stream writer_to_stream :: proc(b: ^Writer) -> (s: io.Stream) { - s.stream_data = b; - s.stream_vtable = _writer_vtable; - return; + s.stream_data = b + s.stream_vtable = _writer_vtable + return } @@ -232,28 +232,28 @@ writer_to_stream :: proc(b: ^Writer) -> (s: io.Stream) { @(private) _writer_vtable := &io.Stream_VTable{ impl_destroy = proc(s: io.Stream) -> io.Error { - b := (^Writer)(s.stream_data); - writer_destroy(b); - return nil; + b := (^Writer)(s.stream_data) + writer_destroy(b) + return nil }, impl_flush = proc(s: io.Stream) -> io.Error { - b := (^Writer)(s.stream_data); - return writer_flush(b); + b := (^Writer)(s.stream_data) + return writer_flush(b) }, impl_write = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) { - b := (^Writer)(s.stream_data); - return writer_write(b, p); + b := (^Writer)(s.stream_data) + return writer_write(b, p) }, impl_write_byte = proc(s: io.Stream, c: byte) -> io.Error { - b := (^Writer)(s.stream_data); - return writer_write_byte(b, c); + b := (^Writer)(s.stream_data) + return writer_write_byte(b, c) }, impl_write_rune = proc(s: io.Stream, r: rune) -> (int, io.Error) { - b := (^Writer)(s.stream_data); - return writer_write_rune(b, r); + b := (^Writer)(s.stream_data) + return writer_write_rune(b, r) }, impl_read_from = proc(s: io.Stream, r: io.Reader) -> (n: i64, err: io.Error) { - b := (^Writer)(s.stream_data); - return writer_read_from(b, r); + b := (^Writer)(s.stream_data) + return writer_read_from(b, r) }, -}; +} diff --git a/core/bytes/buffer.odin b/core/bytes/buffer.odin index 21468e6e8..7d8ae596d 100644 --- a/core/bytes/buffer.odin +++ b/core/bytes/buffer.odin @@ -3,10 +3,10 @@ package bytes import "core:io" import "core:unicode/utf8" -MIN_READ :: 512; +MIN_READ :: 512 @(private) -SMALL_BUFFER_SIZE :: 64; +SMALL_BUFFER_SIZE :: 64 // A Buffer is a variable-sized buffer of bytes with a io.Stream interface // The zero value for Buffer is an empty buffer ready to use. @@ -28,406 +28,406 @@ Read_Op :: enum i8 { buffer_init :: proc(b: ^Buffer, buf: []byte) { - resize(&b.buf, len(buf)); - copy(b.buf[:], buf); + resize(&b.buf, len(buf)) + copy(b.buf[:], buf) } buffer_init_string :: proc(b: ^Buffer, s: string) { - resize(&b.buf, len(s)); - copy(b.buf[:], s); + resize(&b.buf, len(s)) + copy(b.buf[:], s) } buffer_init_allocator :: proc(b: ^Buffer, len, cap: int, allocator := context.allocator) { - b.buf.allocator = allocator; - reserve(&b.buf, cap); - resize(&b.buf, len); + b.buf.allocator = allocator + reserve(&b.buf, cap) + resize(&b.buf, len) } buffer_destroy :: proc(b: ^Buffer) { - delete(b.buf); - buffer_reset(b); + delete(b.buf) + buffer_reset(b) } buffer_to_bytes :: proc(b: ^Buffer) -> []byte { - return b.buf[b.off:]; + return b.buf[b.off:] } buffer_to_string :: proc(b: ^Buffer) -> string { if b == nil { - return "<nil>"; + return "<nil>" } - return string(b.buf[b.off:]); + return string(b.buf[b.off:]) } buffer_is_empty :: proc(b: ^Buffer) -> bool { - return len(b.buf) <= b.off; + return len(b.buf) <= b.off } buffer_length :: proc(b: ^Buffer) -> int { - return len(b.buf) - b.off; + return len(b.buf) - b.off } buffer_capacity :: proc(b: ^Buffer) -> int { - return cap(b.buf); + return cap(b.buf) } buffer_reset :: proc(b: ^Buffer) { - clear(&b.buf); - b.off = 0; - b.last_read = .Invalid; + clear(&b.buf) + b.off = 0 + b.last_read = .Invalid } buffer_truncate :: proc(b: ^Buffer, n: int) { if n == 0 { - buffer_reset(b); - return; + buffer_reset(b) + return } - b.last_read = .Invalid; + b.last_read = .Invalid if n < 0 || n > buffer_length(b) { - panic("bytes.truncate: truncation out of range"); + panic("bytes.truncate: truncation out of range") } - resize(&b.buf, b.off+n); + resize(&b.buf, b.off+n) } @(private) _buffer_try_grow :: proc(b: ^Buffer, n: int) -> (int, bool) { if l := len(b.buf); n <= cap(b.buf)-l { - resize(&b.buf, l+n); - return l, true; + resize(&b.buf, l+n) + return l, true } - return 0, false; + return 0, false } @(private) _buffer_grow :: proc(b: ^Buffer, n: int) -> int { - m := buffer_length(b); + m := buffer_length(b) if m == 0 && b.off != 0 { - buffer_reset(b); + buffer_reset(b) } if i, ok := _buffer_try_grow(b, n); ok { - return i; + return i } if b.buf == nil && n <= SMALL_BUFFER_SIZE { - b.buf = make([dynamic]byte, n, SMALL_BUFFER_SIZE); - return 0; + b.buf = make([dynamic]byte, n, SMALL_BUFFER_SIZE) + return 0 } - c := cap(b.buf); + c := cap(b.buf) if n <= c/2 - m { - copy(b.buf[:], b.buf[b.off:]); + copy(b.buf[:], b.buf[b.off:]) } else if c > max(int) - c - n { - panic("bytes.Buffer: too large"); + panic("bytes.Buffer: too large") } else { - resize(&b.buf, 2*c + n); - copy(b.buf[:], b.buf[b.off:]); + resize(&b.buf, 2*c + n) + copy(b.buf[:], b.buf[b.off:]) } - b.off = 0; - resize(&b.buf, m+n); - return m; + b.off = 0 + resize(&b.buf, m+n) + return m } buffer_grow :: proc(b: ^Buffer, n: int) { if n < 0 { - panic("bytes.buffer_grow: negative count"); + panic("bytes.buffer_grow: negative count") } - m := _buffer_grow(b, n); - resize(&b.buf, m); + m := _buffer_grow(b, n) + resize(&b.buf, m) } buffer_write_at :: proc(b: ^Buffer, p: []byte, offset: int) -> (n: int, err: io.Error) { - b.last_read = .Invalid; + b.last_read = .Invalid if offset < 0 { - err = .Invalid_Offset; - return; + err = .Invalid_Offset + return } - _, ok := _buffer_try_grow(b, offset+len(p)); + _, ok := _buffer_try_grow(b, offset+len(p)) if !ok { - _ = _buffer_grow(b, offset+len(p)); + _ = _buffer_grow(b, offset+len(p)) } if len(b.buf) <= offset { - return 0, .Short_Write; + return 0, .Short_Write } - return copy(b.buf[offset:], p), nil; + return copy(b.buf[offset:], p), nil } buffer_write :: proc(b: ^Buffer, p: []byte) -> (n: int, err: io.Error) { - b.last_read = .Invalid; - m, ok := _buffer_try_grow(b, len(p)); + b.last_read = .Invalid + m, ok := _buffer_try_grow(b, len(p)) if !ok { - m = _buffer_grow(b, len(p)); + m = _buffer_grow(b, len(p)) } - return copy(b.buf[m:], p), nil; + return copy(b.buf[m:], p), nil } buffer_write_string :: proc(b: ^Buffer, s: string) -> (n: int, err: io.Error) { - b.last_read = .Invalid; - m, ok := _buffer_try_grow(b, len(s)); + b.last_read = .Invalid + m, ok := _buffer_try_grow(b, len(s)) if !ok { - m = _buffer_grow(b, len(s)); + m = _buffer_grow(b, len(s)) } - return copy(b.buf[m:], s), nil; + return copy(b.buf[m:], s), nil } buffer_write_byte :: proc(b: ^Buffer, c: byte) -> io.Error { - b.last_read = .Invalid; - m, ok := _buffer_try_grow(b, 1); + b.last_read = .Invalid + m, ok := _buffer_try_grow(b, 1) if !ok { - m = _buffer_grow(b, 1); + m = _buffer_grow(b, 1) } - b.buf[m] = c; - return nil; + b.buf[m] = c + return nil } buffer_write_rune :: proc(b: ^Buffer, r: rune) -> (n: int, err: io.Error) { if r < utf8.RUNE_SELF { - buffer_write_byte(b, byte(r)); - return 1, nil; + buffer_write_byte(b, byte(r)) + return 1, nil } - b.last_read = .Invalid; - m, ok := _buffer_try_grow(b, utf8.UTF_MAX); + b.last_read = .Invalid + m, ok := _buffer_try_grow(b, utf8.UTF_MAX) if !ok { - m = _buffer_grow(b, utf8.UTF_MAX); + m = _buffer_grow(b, utf8.UTF_MAX) } - res: [4]byte; - res, n = utf8.encode_rune(r); - copy(b.buf[m:][:utf8.UTF_MAX], res[:n]); - resize(&b.buf, m+n); - return; + res: [4]byte + res, n = utf8.encode_rune(r) + copy(b.buf[m:][:utf8.UTF_MAX], res[:n]) + resize(&b.buf, m+n) + return } buffer_next :: proc(b: ^Buffer, n: int) -> []byte { - n := n; - b.last_read = .Invalid; - m := buffer_length(b); + n := n + b.last_read = .Invalid + m := buffer_length(b) if n > m { - n = m; + n = m } - data := b.buf[b.off : b.off + n]; - b.off += n; + data := b.buf[b.off : b.off + n] + b.off += n if n > 0 { - b.last_read = .Read; + b.last_read = .Read } - return data; + return data } buffer_read :: proc(b: ^Buffer, p: []byte) -> (n: int, err: io.Error) { - b.last_read = .Invalid; + b.last_read = .Invalid if buffer_is_empty(b) { - buffer_reset(b); + buffer_reset(b) if len(p) == 0 { - return 0, nil; + return 0, nil } - return 0, .EOF; + return 0, .EOF } - n = copy(p, b.buf[b.off:]); - b.off += n; + n = copy(p, b.buf[b.off:]) + b.off += n if n > 0 { - b.last_read = .Read; + b.last_read = .Read } - return; + return } buffer_read_at :: proc(b: ^Buffer, p: []byte, offset: int) -> (n: int, err: io.Error) { - b.last_read = .Invalid; + b.last_read = .Invalid if offset < 0 || offset >= len(b.buf) { - err = .Invalid_Offset; - return; + err = .Invalid_Offset + return } if 0 <= offset && offset < len(b.buf) { - n = copy(p, b.buf[offset:]); + n = copy(p, b.buf[offset:]) } if n > 0 { - b.last_read = .Read; + b.last_read = .Read } - return; + return } buffer_read_byte :: proc(b: ^Buffer) -> (byte, io.Error) { if buffer_is_empty(b) { - buffer_reset(b); - return 0, .EOF; + buffer_reset(b) + return 0, .EOF } - c := b.buf[b.off]; - b.off += 1; - b.last_read = .Read; - return c, nil; + c := b.buf[b.off] + b.off += 1 + b.last_read = .Read + return c, nil } buffer_read_rune :: proc(b: ^Buffer) -> (r: rune, size: int, err: io.Error) { if buffer_is_empty(b) { - buffer_reset(b); - return 0, 0, .EOF; + buffer_reset(b) + return 0, 0, .EOF } - c := b.buf[b.off]; + c := b.buf[b.off] if c < utf8.RUNE_SELF { - b.off += 1; - b.last_read = .Read_Rune1; - return rune(c), 1, nil; + b.off += 1 + b.last_read = .Read_Rune1 + return rune(c), 1, nil } - r, size = utf8.decode_rune(b.buf[b.off:]); - b.off += size; - b.last_read = Read_Op(i8(size)); - return; + r, size = utf8.decode_rune(b.buf[b.off:]) + b.off += size + b.last_read = Read_Op(i8(size)) + return } buffer_unread_byte :: proc(b: ^Buffer) -> io.Error { if b.last_read == .Invalid { - return .Invalid_Unread; + return .Invalid_Unread } - b.last_read = .Invalid; + b.last_read = .Invalid if b.off > 0 { - b.off -= 1; + b.off -= 1 } - return nil; + return nil } buffer_unread_rune :: proc(b: ^Buffer) -> io.Error { if b.last_read <= .Invalid { - return .Invalid_Unread; + return .Invalid_Unread } if b.off >= int(b.last_read) { - b.off -= int(i8(b.last_read)); + b.off -= int(i8(b.last_read)) } - b.last_read = .Invalid; - return nil; + b.last_read = .Invalid + return nil } buffer_read_bytes :: proc(b: ^Buffer, delim: byte) -> (line: []byte, err: io.Error) { - i := index_byte(b.buf[b.off:], delim); - end := b.off + i + 1; + i := index_byte(b.buf[b.off:], delim) + end := b.off + i + 1 if i < 0 { - end = len(b.buf); - err = .EOF; + end = len(b.buf) + err = .EOF } - line = b.buf[b.off:end]; - b.off = end; - b.last_read = .Read; - return; + line = b.buf[b.off:end] + b.off = end + b.last_read = .Read + return } buffer_read_string :: proc(b: ^Buffer, delim: byte) -> (line: string, err: io.Error) { - slice: []byte; - slice, err = buffer_read_bytes(b, delim); - return string(slice), err; + slice: []byte + slice, err = buffer_read_bytes(b, delim) + return string(slice), err } buffer_write_to :: proc(b: ^Buffer, w: io.Writer) -> (n: i64, err: io.Error) { - b.last_read = .Invalid; + b.last_read = .Invalid if byte_count := buffer_length(b); byte_count > 0 { - m, e := io.write(w, b.buf[b.off:]); + m, e := io.write(w, b.buf[b.off:]) if m > byte_count { - panic("bytes.buffer_write_to: invalid io.write count"); + panic("bytes.buffer_write_to: invalid io.write count") } - b.off += m; - n = i64(m); + b.off += m + n = i64(m) if e != nil { - err = e; - return; + err = e + return } if m != byte_count { - err = .Short_Write; - return; + err = .Short_Write + return } } - buffer_reset(b); - return; + buffer_reset(b) + return } buffer_read_from :: proc(b: ^Buffer, r: io.Reader) -> (n: i64, err: io.Error) #no_bounds_check { - b.last_read = .Invalid; + b.last_read = .Invalid for { - i := _buffer_grow(b, MIN_READ); - resize(&b.buf, i); - m, e := io.read(r, b.buf[i:cap(b.buf)]); + i := _buffer_grow(b, MIN_READ) + resize(&b.buf, i) + m, e := io.read(r, b.buf[i:cap(b.buf)]) if m < 0 { - err = .Negative_Read; - return; + err = .Negative_Read + return } - resize(&b.buf, i+m); - n += i64(m); + resize(&b.buf, i+m) + n += i64(m) if e == .EOF { - return; + return } if e != nil { - err = e; - return; + err = e + return } } - return; + return } buffer_to_stream :: proc(b: ^Buffer) -> (s: io.Stream) { - s.stream_data = b; - s.stream_vtable = _buffer_vtable; - return; + s.stream_data = b + s.stream_vtable = _buffer_vtable + return } @(private) _buffer_vtable := &io.Stream_VTable{ impl_size = proc(s: io.Stream) -> i64 { - b := (^Buffer)(s.stream_data); - return i64(buffer_capacity(b)); + b := (^Buffer)(s.stream_data) + return i64(buffer_capacity(b)) }, impl_read = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) { - b := (^Buffer)(s.stream_data); - return buffer_read(b, p); + b := (^Buffer)(s.stream_data) + return buffer_read(b, p) }, impl_read_at = proc(s: io.Stream, p: []byte, offset: i64) -> (n: int, err: io.Error) { - b := (^Buffer)(s.stream_data); - return buffer_read_at(b, p, int(offset)); + b := (^Buffer)(s.stream_data) + return buffer_read_at(b, p, int(offset)) }, impl_read_byte = proc(s: io.Stream) -> (byte, io.Error) { - b := (^Buffer)(s.stream_data); - return buffer_read_byte(b); + b := (^Buffer)(s.stream_data) + return buffer_read_byte(b) }, impl_read_rune = proc(s: io.Stream) -> (r: rune, size: int, err: io.Error) { - b := (^Buffer)(s.stream_data); - return buffer_read_rune(b); + b := (^Buffer)(s.stream_data) + return buffer_read_rune(b) }, impl_write = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) { - b := (^Buffer)(s.stream_data); - return buffer_write(b, p); + b := (^Buffer)(s.stream_data) + return buffer_write(b, p) }, impl_write_at = proc(s: io.Stream, p: []byte, offset: i64) -> (n: int, err: io.Error) { - b := (^Buffer)(s.stream_data); - return buffer_write_at(b, p, int(offset)); + b := (^Buffer)(s.stream_data) + return buffer_write_at(b, p, int(offset)) }, impl_write_byte = proc(s: io.Stream, c: byte) -> io.Error { - b := (^Buffer)(s.stream_data); - return buffer_write_byte(b, c); + b := (^Buffer)(s.stream_data) + return buffer_write_byte(b, c) }, impl_write_rune = proc(s: io.Stream, r: rune) -> (int, io.Error) { - b := (^Buffer)(s.stream_data); - return buffer_write_rune(b, r); + b := (^Buffer)(s.stream_data) + return buffer_write_rune(b, r) }, impl_unread_byte = proc(s: io.Stream) -> io.Error { - b := (^Buffer)(s.stream_data); - return buffer_unread_byte(b); + b := (^Buffer)(s.stream_data) + return buffer_unread_byte(b) }, impl_unread_rune = proc(s: io.Stream) -> io.Error { - b := (^Buffer)(s.stream_data); - return buffer_unread_rune(b); + b := (^Buffer)(s.stream_data) + return buffer_unread_rune(b) }, impl_destroy = proc(s: io.Stream) -> io.Error { - b := (^Buffer)(s.stream_data); - buffer_destroy(b); - return nil; + b := (^Buffer)(s.stream_data) + buffer_destroy(b) + return nil }, impl_write_to = proc(s: io.Stream, w: io.Writer) -> (n: i64, err: io.Error) { - b := (^Buffer)(s.stream_data); - return buffer_write_to(b, w); + b := (^Buffer)(s.stream_data) + return buffer_write_to(b, w) }, impl_read_from = proc(s: io.Stream, r: io.Reader) -> (n: i64, err: io.Error) { - b := (^Buffer)(s.stream_data); - return buffer_read_from(b, r); + b := (^Buffer)(s.stream_data) + return buffer_read_from(b, r) }, -}; +} diff --git a/core/bytes/bytes.odin b/core/bytes/bytes.odin index a7cf23d1b..cbc1e2506 100644 --- a/core/bytes/bytes.odin +++ b/core/bytes/bytes.odin @@ -5,272 +5,272 @@ import "core:unicode" import "core:unicode/utf8" clone :: proc(s: []byte, allocator := context.allocator, loc := #caller_location) -> []byte { - c := make([]byte, len(s)+1, allocator, loc); - copy(c, s); - c[len(s)] = 0; - return c[:len(s)]; + c := make([]byte, len(s)+1, allocator, loc) + copy(c, s) + c[len(s)] = 0 + return c[:len(s)] } ptr_from_slice :: proc(str: []byte) -> ^byte { - d := transmute(mem.Raw_String)str; - return d.data; + d := transmute(mem.Raw_String)str + return d.data } truncate_to_byte :: proc(str: []byte, b: byte) -> []byte { - n := index_byte(str, b); + n := index_byte(str, b) if n < 0 { - n = len(str); + n = len(str) } - return str[:n]; + return str[:n] } truncate_to_rune :: proc(str: []byte, r: rune) -> []byte { - n := index_rune(str, r); + n := index_rune(str, r) if n < 0 { - n = len(str); + n = len(str) } - return str[:n]; + return str[:n] } // Compares two strings, returning a value representing which one comes first lexiographically. // -1 for `a`; 1 for `b`, or 0 if they are equal. compare :: proc(lhs, rhs: []byte) -> int { - return mem.compare(lhs, rhs); + return mem.compare(lhs, rhs) } contains_rune :: proc(s: []byte, r: rune) -> int { for c, offset in string(s) { if c == r { - return offset; + return offset } } - return -1; + return -1 } contains :: proc(s, substr: []byte) -> bool { - return index(s, substr) >= 0; + return index(s, substr) >= 0 } contains_any :: proc(s, chars: []byte) -> bool { - return index_any(s, chars) >= 0; + return index_any(s, chars) >= 0 } rune_count :: proc(s: []byte) -> int { - return utf8.rune_count(s); + return utf8.rune_count(s) } equal :: proc(a, b: []byte) -> bool { - return string(a) == string(b); + return string(a) == string(b) } equal_fold :: proc(u, v: []byte) -> bool { - s, t := string(u), string(v); + s, t := string(u), string(v) loop: for s != "" && t != "" { - sr, tr: rune; + sr, tr: rune if s[0] < utf8.RUNE_SELF { - sr, s = rune(s[0]), s[1:]; + sr, s = rune(s[0]), s[1:] } else { - r, size := utf8.decode_rune_in_string(s); - sr, s = r, s[size:]; + r, size := utf8.decode_rune_in_string(s) + sr, s = r, s[size:] } if t[0] < utf8.RUNE_SELF { - tr, t = rune(t[0]), t[1:]; + tr, t = rune(t[0]), t[1:] } else { - r, size := utf8.decode_rune_in_string(t); - tr, t = r, t[size:]; + r, size := utf8.decode_rune_in_string(t) + tr, t = r, t[size:] } if tr == sr { // easy case - continue loop; + continue loop } if tr < sr { - tr, sr = sr, tr; + tr, sr = sr, tr } if tr < utf8.RUNE_SELF { switch sr { case 'A'..='Z': if tr == (sr+'a')-'A' { - continue loop; + continue loop } } - return false; + return false } // TODO(bill): Unicode folding - return false; + return false } - return s == t; + return s == t } has_prefix :: proc(s, prefix: []byte) -> bool { - return len(s) >= len(prefix) && string(s[0:len(prefix)]) == string(prefix); + return len(s) >= len(prefix) && string(s[0:len(prefix)]) == string(prefix) } has_suffix :: proc(s, suffix: []byte) -> bool { - return len(s) >= len(suffix) && string(s[len(s)-len(suffix):]) == string(suffix); + return len(s) >= len(suffix) && string(s[len(s)-len(suffix):]) == string(suffix) } join :: proc(a: [][]byte, sep: []byte, allocator := context.allocator) -> []byte { if len(a) == 0 { - return nil; + return nil } - n := len(sep) * (len(a) - 1); + n := len(sep) * (len(a) - 1) for s in a { - n += len(s); + n += len(s) } - b := make([]byte, n, allocator); - i := copy(b, a[0]); + b := make([]byte, n, allocator) + i := copy(b, a[0]) for s in a[1:] { - i += copy(b[i:], sep); - i += copy(b[i:], s); + i += copy(b[i:], sep) + i += copy(b[i:], s) } - return b; + return b } concatenate :: proc(a: [][]byte, allocator := context.allocator) -> []byte { if len(a) == 0 { - return nil; + return nil } - n := 0; + n := 0 for s in a { - n += len(s); + n += len(s) } - b := make([]byte, n, allocator); - i := 0; + b := make([]byte, n, allocator) + i := 0 for s in a { - i += copy(b[i:], s); + i += copy(b[i:], s) } - return b; + return b } @private _split :: proc(s, sep: []byte, sep_save, n: int, allocator := context.allocator) -> [][]byte { - s, n := s, n; + s, n := s, n if n == 0 { - return nil; + return nil } if sep == nil { - l := utf8.rune_count(s); + l := utf8.rune_count(s) if n < 0 || n > l { - n = l; + n = l } - res := make([dynamic][]byte, n, allocator); + res := make([dynamic][]byte, n, allocator) for i := 0; i < n-1; i += 1 { - _, w := utf8.decode_rune(s); - res[i] = s[:w]; - s = s[w:]; + _, w := utf8.decode_rune(s) + res[i] = s[:w] + s = s[w:] } if n > 0 { - res[n-1] = s; + res[n-1] = s } - return res[:]; + return res[:] } if n < 0 { - n = count(s, sep) + 1; + n = count(s, sep) + 1 } - res := make([dynamic][]byte, n, allocator); + res := make([dynamic][]byte, n, allocator) - n -= 1; + n -= 1 - i := 0; + i := 0 for ; i < n; i += 1 { - m := index(s, sep); + m := index(s, sep) if m < 0 { - break; + break } - res[i] = s[:m+sep_save]; - s = s[m+len(sep):]; + res[i] = s[:m+sep_save] + s = s[m+len(sep):] } - res[i] = s; + res[i] = s - return res[:i+1]; + return res[:i+1] } split :: proc(s, sep: []byte, allocator := context.allocator) -> [][]byte { - return _split(s, sep, 0, -1, allocator); + return _split(s, sep, 0, -1, allocator) } split_n :: proc(s, sep: []byte, n: int, allocator := context.allocator) -> [][]byte { - return _split(s, sep, 0, n, allocator); + return _split(s, sep, 0, n, allocator) } split_after :: proc(s, sep: []byte, allocator := context.allocator) -> [][]byte { - return _split(s, sep, len(sep), -1, allocator); + return _split(s, sep, len(sep), -1, allocator) } split_after_n :: proc(s, sep: []byte, n: int, allocator := context.allocator) -> [][]byte { - return _split(s, sep, len(sep), n, allocator); + return _split(s, sep, len(sep), n, allocator) } @private _split_iterator :: proc(s: ^[]byte, sep: []byte, sep_save, n: int) -> (res: []byte, ok: bool) { - s, n := s, n; + s, n := s, n if n == 0 { - return; + return } if sep == nil { - res = s[:]; - ok = true; - s^ = s[len(s):]; - return; + res = s[:] + ok = true + s^ = s[len(s):] + return } if n < 0 { - n = count(s^, sep) + 1; + n = count(s^, sep) + 1 } - n -= 1; + n -= 1 - i := 0; + i := 0 for ; i < n; i += 1 { - m := index(s^, sep); + m := index(s^, sep) if m < 0 { - break; + break } - res = s[:m+sep_save]; - ok = true; - s^ = s[m+len(sep):]; - return; + res = s[:m+sep_save] + ok = true + s^ = s[m+len(sep):] + return } - res = s[:]; - ok = res != nil; - s^ = s[len(s):]; - return; + res = s[:] + ok = res != nil + s^ = s[len(s):] + return } split_iterator :: proc(s: ^[]byte, sep: []byte) -> ([]byte, bool) { - return _split_iterator(s, sep, 0, -1); + return _split_iterator(s, sep, 0, -1) } split_n_iterator :: proc(s: ^[]byte, sep: []byte, n: int) -> ([]byte, bool) { - return _split_iterator(s, sep, 0, n); + return _split_iterator(s, sep, 0, n) } split_after_iterator :: proc(s: ^[]byte, sep: []byte) -> ([]byte, bool) { - return _split_iterator(s, sep, len(sep), -1); + return _split_iterator(s, sep, len(sep), -1) } split_after_n_iterator :: proc(s: ^[]byte, sep: []byte, n: int) -> ([]byte, bool) { - return _split_iterator(s, sep, len(sep), n); + return _split_iterator(s, sep, len(sep), n) } @@ -278,599 +278,599 @@ split_after_n_iterator :: proc(s: ^[]byte, sep: []byte, n: int) -> ([]byte, bool index_byte :: proc(s: []byte, c: byte) -> int { for i := 0; i < len(s); i += 1 { if s[i] == c { - return i; + return i } } - return -1; + return -1 } // Returns -1 if c is not present last_index_byte :: proc(s: []byte, c: byte) -> int { for i := len(s)-1; i >= 0; i -= 1 { if s[i] == c { - return i; + return i } } - return -1; + return -1 } -@private PRIME_RABIN_KARP :: 16777619; +@private PRIME_RABIN_KARP :: 16777619 index :: proc(s, substr: []byte) -> int { hash_str_rabin_karp :: proc(s: []byte) -> (hash: u32 = 0, pow: u32 = 1) { for i := 0; i < len(s); i += 1 { - hash = hash*PRIME_RABIN_KARP + u32(s[i]); + hash = hash*PRIME_RABIN_KARP + u32(s[i]) } - sq := u32(PRIME_RABIN_KARP); + sq := u32(PRIME_RABIN_KARP) for i := len(s); i > 0; i >>= 1 { if (i & 1) != 0 { - pow *= sq; + pow *= sq } - sq *= sq; + sq *= sq } - return; + return } - n := len(substr); + n := len(substr) switch { case n == 0: - return 0; + return 0 case n == 1: - return index_byte(s, substr[0]); + return index_byte(s, substr[0]) case n == len(s): if string(s) == string(substr) { - return 0; + return 0 } - return -1; + return -1 case n > len(s): - return -1; + return -1 } - hash, pow := hash_str_rabin_karp(substr); - h: u32; + hash, pow := hash_str_rabin_karp(substr) + h: u32 for i := 0; i < n; i += 1 { - h = h*PRIME_RABIN_KARP + u32(s[i]); + h = h*PRIME_RABIN_KARP + u32(s[i]) } if h == hash && string(s[:n]) == string(substr) { - return 0; + return 0 } for i := n; i < len(s); /**/ { - h *= PRIME_RABIN_KARP; - h += u32(s[i]); - h -= pow * u32(s[i-n]); - i += 1; + h *= PRIME_RABIN_KARP + h += u32(s[i]) + h -= pow * u32(s[i-n]) + i += 1 if h == hash && string(s[i-n:i]) == string(substr) { - return i - n; + return i - n } } - return -1; + return -1 } last_index :: proc(s, substr: []byte) -> int { hash_str_rabin_karp_reverse :: proc(s: []byte) -> (hash: u32 = 0, pow: u32 = 1) { for i := len(s) - 1; i >= 0; i -= 1 { - hash = hash*PRIME_RABIN_KARP + u32(s[i]); + hash = hash*PRIME_RABIN_KARP + u32(s[i]) } - sq := u32(PRIME_RABIN_KARP); + sq := u32(PRIME_RABIN_KARP) for i := len(s); i > 0; i >>= 1 { if (i & 1) != 0 { - pow *= sq; + pow *= sq } - sq *= sq; + sq *= sq } - return; + return } - n := len(substr); + n := len(substr) switch { case n == 0: - return len(s); + return len(s) case n == 1: - return last_index_byte(s, substr[0]); + return last_index_byte(s, substr[0]) case n == len(s): - return 0 if string(substr) == string(s) else -1; + return 0 if string(substr) == string(s) else -1 case n > len(s): - return -1; + return -1 } - hash, pow := hash_str_rabin_karp_reverse(substr); - last := len(s) - n; - h: u32; + hash, pow := hash_str_rabin_karp_reverse(substr) + last := len(s) - n + h: u32 for i := len(s)-1; i >= last; i -= 1 { - h = h*PRIME_RABIN_KARP + u32(s[i]); + h = h*PRIME_RABIN_KARP + u32(s[i]) } if h == hash && string(s[last:]) == string(substr) { - return last; + return last } for i := last-1; i >= 0; i -= 1 { - h *= PRIME_RABIN_KARP; - h += u32(s[i]); - h -= pow * u32(s[i+n]); + h *= PRIME_RABIN_KARP + h += u32(s[i]) + h -= pow * u32(s[i+n]) if h == hash && string(s[i:i+n]) == string(substr) { - return i; + return i } } - return -1; + return -1 } index_any :: proc(s, chars: []byte) -> int { if chars == nil { - return -1; + return -1 } // TODO(bill): Optimize for r, i in s { for c in chars { if r == c { - return i; + return i } } } - return -1; + return -1 } last_index_any :: proc(s, chars: []byte) -> int { if chars == nil { - return -1; + return -1 } for i := len(s); i > 0; { - r, w := utf8.decode_last_rune(s[:i]); - i -= w; + r, w := utf8.decode_last_rune(s[:i]) + i -= w for c in string(chars) { if r == c { - return i; + return i } } } - return -1; + return -1 } count :: proc(s, substr: []byte) -> int { if len(substr) == 0 { // special case - return rune_count(s) + 1; + return rune_count(s) + 1 } if len(substr) == 1 { - c := substr[0]; + c := substr[0] switch len(s) { case 0: - return 0; + return 0 case 1: - return int(s[0] == c); + return int(s[0] == c) } - n := 0; + n := 0 for i := 0; i < len(s); i += 1 { if s[i] == c { - n += 1; + n += 1 } } - return n; + return n } // TODO(bill): Use a non-brute for approach - n := 0; - str := s; + n := 0 + str := s for { - i := index(str, substr); + i := index(str, substr) if i == -1 { - return n; + return n } - n += 1; - str = str[i+len(substr):]; + n += 1 + str = str[i+len(substr):] } - return n; + return n } repeat :: proc(s: []byte, count: int, allocator := context.allocator) -> []byte { if count < 0 { - panic("bytes: negative repeat count"); + panic("bytes: negative repeat count") } else if count > 0 && (len(s)*count)/count != len(s) { - panic("bytes: repeat count will cause an overflow"); + panic("bytes: repeat count will cause an overflow") } - b := make([]byte, len(s)*count, allocator); - i := copy(b, s); + b := make([]byte, len(s)*count, allocator) + i := copy(b, s) for i < len(b) { // 2^N trick to reduce the need to copy - copy(b[i:], b[:i]); - i *= 2; + copy(b[i:], b[:i]) + i *= 2 } - return b; + return b } replace_all :: proc(s, old, new: []byte, allocator := context.allocator) -> (output: []byte, was_allocation: bool) { - return replace(s, old, new, -1, allocator); + return replace(s, old, new, -1, allocator) } // if n < 0, no limit on the number of replacements replace :: proc(s, old, new: []byte, n: int, allocator := context.allocator) -> (output: []byte, was_allocation: bool) { if string(old) == string(new) || n == 0 { - was_allocation = false; - output = s; - return; + was_allocation = false + output = s + return } - byte_count := n; + byte_count := n if m := count(s, old); m == 0 { - was_allocation = false; - output = s; - return; + was_allocation = false + output = s + return } else if n < 0 || m < n { - byte_count = m; + byte_count = m } - t := make([]byte, len(s) + byte_count*(len(new) - len(old)), allocator); - was_allocation = true; + t := make([]byte, len(s) + byte_count*(len(new) - len(old)), allocator) + was_allocation = true - w := 0; - start := 0; + w := 0 + start := 0 for i := 0; i < byte_count; i += 1 { - j := start; + j := start if len(old) == 0 { if i > 0 { - _, width := utf8.decode_rune(s[start:]); - j += width; + _, width := utf8.decode_rune(s[start:]) + j += width } } else { - j += index(s[start:], old); + j += index(s[start:], old) } - w += copy(t[w:], s[start:j]); - w += copy(t[w:], new); - start = j + len(old); + w += copy(t[w:], s[start:j]) + w += copy(t[w:], new) + start = j + len(old) } - w += copy(t[w:], s[start:]); - output = t[0:w]; - return; + w += copy(t[w:], s[start:]) + output = t[0:w] + return } remove :: proc(s, key: []byte, n: int, allocator := context.allocator) -> (output: []byte, was_allocation: bool) { - return replace(s, key, {}, n, allocator); + return replace(s, key, {}, n, allocator) } remove_all :: proc(s, key: []byte, allocator := context.allocator) -> (output: []byte, was_allocation: bool) { - return remove(s, key, -1, allocator); + return remove(s, key, -1, allocator) } -@(private) _ascii_space := [256]u8{'\t' = 1, '\n' = 1, '\v' = 1, '\f' = 1, '\r' = 1, ' ' = 1}; +@(private) _ascii_space := [256]u8{'\t' = 1, '\n' = 1, '\v' = 1, '\f' = 1, '\r' = 1, ' ' = 1} is_ascii_space :: proc(r: rune) -> bool { if r < utf8.RUNE_SELF { - return _ascii_space[u8(r)] != 0; + return _ascii_space[u8(r)] != 0 } - return false; + return false } is_space :: proc(r: rune) -> bool { if r < 0x2000 { switch r { case '\t', '\n', '\v', '\f', '\r', ' ', 0x85, 0xa0, 0x1680: - return true; + return true } } else { if r <= 0x200a { - return true; + return true } switch r { case 0x2028, 0x2029, 0x202f, 0x205f, 0x3000: - return true; + return true } } - return false; + return false } is_null :: proc(r: rune) -> bool { - return r == 0x0000; + return r == 0x0000 } index_proc :: proc(s: []byte, p: proc(rune) -> bool, truth := true) -> int { for r, i in string(s) { if p(r) == truth { - return i; + return i } } - return -1; + return -1 } index_proc_with_state :: proc(s: []byte, p: proc(rawptr, rune) -> bool, state: rawptr, truth := true) -> int { for r, i in string(s) { if p(state, r) == truth { - return i; + return i } } - return -1; + return -1 } last_index_proc :: proc(s: []byte, p: proc(rune) -> bool, truth := true) -> int { // TODO(bill): Probably use Rabin-Karp Search for i := len(s); i > 0; { - r, size := utf8.decode_last_rune(s[:i]); - i -= size; + r, size := utf8.decode_last_rune(s[:i]) + i -= size if p(r) == truth { - return i; + return i } } - return -1; + return -1 } last_index_proc_with_state :: proc(s: []byte, p: proc(rawptr, rune) -> bool, state: rawptr, truth := true) -> int { // TODO(bill): Probably use Rabin-Karp Search for i := len(s); i > 0; { - r, size := utf8.decode_last_rune(s[:i]); - i -= size; + r, size := utf8.decode_last_rune(s[:i]) + i -= size if p(state, r) == truth { - return i; + return i } } - return -1; + return -1 } trim_left_proc :: proc(s: []byte, p: proc(rune) -> bool) -> []byte { - i := index_proc(s, p, false); + i := index_proc(s, p, false) if i == -1 { - return nil; + return nil } - return s[i:]; + return s[i:] } index_rune :: proc(s: []byte, r: rune) -> int { switch { case 0 <= r && r < utf8.RUNE_SELF: - return index_byte(s, byte(r)); + return index_byte(s, byte(r)) case r == utf8.RUNE_ERROR: for c, i in string(s) { if c == utf8.RUNE_ERROR { - return i; + return i } } - return -1; + return -1 case !utf8.valid_rune(r): - return -1; + return -1 } - b, w := utf8.encode_rune(r); - return index(s, b[:w]); + b, w := utf8.encode_rune(r) + return index(s, b[:w]) } trim_left_proc_with_state :: proc(s: []byte, p: proc(rawptr, rune) -> bool, state: rawptr) -> []byte { - i := index_proc_with_state(s, p, state, false); + i := index_proc_with_state(s, p, state, false) if i == -1 { - return nil; + return nil } - return s[i:]; + return s[i:] } trim_right_proc :: proc(s: []byte, p: proc(rune) -> bool) -> []byte { - i := last_index_proc(s, p, false); + i := last_index_proc(s, p, false) if i >= 0 && s[i] >= utf8.RUNE_SELF { - _, w := utf8.decode_rune(s[i:]); - i += w; + _, w := utf8.decode_rune(s[i:]) + i += w } else { - i += 1; + i += 1 } - return s[0:i]; + return s[0:i] } trim_right_proc_with_state :: proc(s: []byte, p: proc(rawptr, rune) -> bool, state: rawptr) -> []byte { - i := last_index_proc_with_state(s, p, state, false); + i := last_index_proc_with_state(s, p, state, false) if i >= 0 && s[i] >= utf8.RUNE_SELF { - _, w := utf8.decode_rune(s[i:]); - i += w; + _, w := utf8.decode_rune(s[i:]) + i += w } else { - i += 1; + i += 1 } - return s[0:i]; + return s[0:i] } is_in_cutset :: proc(state: rawptr, r: rune) -> bool { if state == nil { - return false; + return false } - cutset := (^string)(state)^; + cutset := (^string)(state)^ for c in cutset { if r == c { - return true; + return true } } - return false; + return false } trim_left :: proc(s: []byte, cutset: []byte) -> []byte { if s == nil || cutset == nil { - return s; + return s } - state := cutset; - return trim_left_proc_with_state(s, is_in_cutset, &state); + state := cutset + return trim_left_proc_with_state(s, is_in_cutset, &state) } trim_right :: proc(s: []byte, cutset: []byte) -> []byte { if s == nil || cutset == nil { - return s; + return s } - state := cutset; - return trim_right_proc_with_state(s, is_in_cutset, &state); + state := cutset + return trim_right_proc_with_state(s, is_in_cutset, &state) } trim :: proc(s: []byte, cutset: []byte) -> []byte { - return trim_right(trim_left(s, cutset), cutset); + return trim_right(trim_left(s, cutset), cutset) } trim_left_space :: proc(s: []byte) -> []byte { - return trim_left_proc(s, is_space); + return trim_left_proc(s, is_space) } trim_right_space :: proc(s: []byte) -> []byte { - return trim_right_proc(s, is_space); + return trim_right_proc(s, is_space) } trim_space :: proc(s: []byte) -> []byte { - return trim_right_space(trim_left_space(s)); + return trim_right_space(trim_left_space(s)) } trim_left_null :: proc(s: []byte) -> []byte { - return trim_left_proc(s, is_null); + return trim_left_proc(s, is_null) } trim_right_null :: proc(s: []byte) -> []byte { - return trim_right_proc(s, is_null); + return trim_right_proc(s, is_null) } trim_null :: proc(s: []byte) -> []byte { - return trim_right_null(trim_left_null(s)); + return trim_right_null(trim_left_null(s)) } trim_prefix :: proc(s, prefix: []byte) -> []byte { if has_prefix(s, prefix) { - return s[len(prefix):]; + return s[len(prefix):] } - return s; + return s } trim_suffix :: proc(s, suffix: []byte) -> []byte { if has_suffix(s, suffix) { - return s[:len(s)-len(suffix)]; + return s[:len(s)-len(suffix)] } - return s; + return s } split_multi :: proc(s: []byte, substrs: [][]byte, skip_empty := false, allocator := context.allocator) -> [][]byte #no_bounds_check { if s == nil || len(substrs) <= 0 { - return nil; + return nil } - sublen := len(substrs[0]); + sublen := len(substrs[0]) for substr in substrs[1:] { - sublen = min(sublen, len(substr)); + sublen = min(sublen, len(substr)) } - shared := len(s) - sublen; + shared := len(s) - sublen if shared <= 0 { - return nil; + return nil } // number, index, last - n, i, l := 0, 0, 0; + n, i, l := 0, 0, 0 // count results first_pass: for i <= shared { for substr in substrs { if string(s[i:i+sublen]) == string(substr) { if !skip_empty || i - l > 0 { - n += 1; + n += 1 } - i += sublen; - l = i; + i += sublen + l = i - continue first_pass; + continue first_pass } } - _, skip := utf8.decode_rune(s[i:]); - i += skip; + _, skip := utf8.decode_rune(s[i:]) + i += skip } if !skip_empty || len(s) - l > 0 { - n += 1; + n += 1 } if n < 1 { // no results - return nil; + return nil } - buf := make([][]byte, n, allocator); + buf := make([][]byte, n, allocator) - n, i, l = 0, 0, 0; + n, i, l = 0, 0, 0 // slice results second_pass: for i <= shared { for substr in substrs { if string(s[i:i+sublen]) == string(substr) { if !skip_empty || i - l > 0 { - buf[n] = s[l:i]; - n += 1; + buf[n] = s[l:i] + n += 1 } - i += sublen; - l = i; + i += sublen + l = i - continue second_pass; + continue second_pass } } - _, skip := utf8.decode_rune(s[i:]); - i += skip; + _, skip := utf8.decode_rune(s[i:]) + i += skip } if !skip_empty || len(s) - l > 0 { - buf[n] = s[l:]; + buf[n] = s[l:] } - return buf; + return buf } split_multi_iterator :: proc(s: ^[]byte, substrs: [][]byte, skip_empty := false) -> ([]byte, bool) #no_bounds_check { if s == nil || s^ == nil || len(substrs) <= 0 { - return nil, false; + return nil, false } - sublen := len(substrs[0]); + sublen := len(substrs[0]) for substr in substrs[1:] { - sublen = min(sublen, len(substr)); + sublen = min(sublen, len(substr)) } - shared := len(s) - sublen; + shared := len(s) - sublen if shared <= 0 { - return nil, false; + return nil, false } // index, last - i, l := 0, 0; + i, l := 0, 0 loop: for i <= shared { for substr in substrs { if string(s[i:i+sublen]) == string(substr) { if !skip_empty || i - l > 0 { - res := s[l:i]; - s^ = s[i:]; - return res, true; + res := s[l:i] + s^ = s[i:] + return res, true } - i += sublen; - l = i; + i += sublen + l = i - continue loop; + continue loop } } - _, skip := utf8.decode_rune(s[i:]); - i += skip; + _, skip := utf8.decode_rune(s[i:]) + i += skip } if !skip_empty || len(s) - l > 0 { - res := s[l:]; - s^ = s[len(s):]; - return res, true; + res := s[l:] + s^ = s[len(s):] + return res, true } - return nil, false; + return nil, false } @@ -879,167 +879,167 @@ split_multi_iterator :: proc(s: ^[]byte, substrs: [][]byte, skip_empty := false) // scrub scruvs invalid utf-8 characters and replaces them with the replacement string // Adjacent invalid bytes are only replaced once scrub :: proc(s: []byte, replacement: []byte, allocator := context.allocator) -> []byte { - str := s; - b: Buffer; - buffer_init_allocator(&b, 0, len(s), allocator); + str := s + b: Buffer + buffer_init_allocator(&b, 0, len(s), allocator) - has_error := false; - cursor := 0; - origin := str; + has_error := false + cursor := 0 + origin := str for len(str) > 0 { - r, w := utf8.decode_rune(str); + r, w := utf8.decode_rune(str) if r == utf8.RUNE_ERROR { if !has_error { - has_error = true; - buffer_write(&b, origin[:cursor]); + has_error = true + buffer_write(&b, origin[:cursor]) } } else if has_error { - has_error = false; - buffer_write(&b, replacement); + has_error = false + buffer_write(&b, replacement) - origin = origin[cursor:]; - cursor = 0; + origin = origin[cursor:] + cursor = 0 } - cursor += w; - str = str[w:]; + cursor += w + str = str[w:] } - return buffer_to_bytes(&b); + return buffer_to_bytes(&b) } reverse :: proc(s: []byte, allocator := context.allocator) -> []byte { - str := s; - n := len(str); - buf := make([]byte, n); - i := n; + str := s + n := len(str) + buf := make([]byte, n) + i := n for len(str) > 0 { - _, w := utf8.decode_rune(str); - i -= w; - copy(buf[i:], str[:w]); - str = str[w:]; + _, w := utf8.decode_rune(str) + i -= w + copy(buf[i:], str[:w]) + str = str[w:] } - return buf; + return buf } expand_tabs :: proc(s: []byte, tab_size: int, allocator := context.allocator) -> []byte { if tab_size <= 0 { - panic("tab size must be positive"); + panic("tab size must be positive") } if s == nil { - return nil; + return nil } - b: Buffer; - buffer_init_allocator(&b, 0, len(s), allocator); + b: Buffer + buffer_init_allocator(&b, 0, len(s), allocator) - str := s; - column: int; + str := s + column: int for len(str) > 0 { - r, w := utf8.decode_rune(str); + r, w := utf8.decode_rune(str) if r == '\t' { - expand := tab_size - column%tab_size; + expand := tab_size - column%tab_size for i := 0; i < expand; i += 1 { - buffer_write_byte(&b, ' '); + buffer_write_byte(&b, ' ') } - column += expand; + column += expand } else { if r == '\n' { - column = 0; + column = 0 } else { - column += w; + column += w } - buffer_write_rune(&b, r); + buffer_write_rune(&b, r) } - str = str[w:]; + str = str[w:] } - return buffer_to_bytes(&b); + return buffer_to_bytes(&b) } partition :: proc(str, sep: []byte) -> (head, match, tail: []byte) { - i := index(str, sep); + i := index(str, sep) if i == -1 { - head = str; - return; + head = str + return } - head = str[:i]; - match = str[i:i+len(sep)]; - tail = str[i+len(sep):]; - return; + head = str[:i] + match = str[i:i+len(sep)] + tail = str[i+len(sep):] + return } -center_justify :: centre_justify; // NOTE(bill): Because Americans exist +center_justify :: centre_justify // NOTE(bill): Because Americans exist // centre_justify returns a byte slice with a pad byte slice at boths sides if the str's rune length is smaller than length centre_justify :: proc(str: []byte, length: int, pad: []byte, allocator := context.allocator) -> []byte { - n := rune_count(str); + n := rune_count(str) if n >= length || pad == nil { - return clone(str, allocator); + return clone(str, allocator) } - remains := length-1; - pad_len := rune_count(pad); + remains := length-1 + pad_len := rune_count(pad) - b: Buffer; - buffer_init_allocator(&b, 0, len(str) + (remains/pad_len + 1)*len(pad), allocator); + b: Buffer + buffer_init_allocator(&b, 0, len(str) + (remains/pad_len + 1)*len(pad), allocator) - write_pad_string(&b, pad, pad_len, remains/2); - buffer_write(&b, str); - write_pad_string(&b, pad, pad_len, (remains+1)/2); + write_pad_string(&b, pad, pad_len, remains/2) + buffer_write(&b, str) + write_pad_string(&b, pad, pad_len, (remains+1)/2) - return buffer_to_bytes(&b); + return buffer_to_bytes(&b) } // left_justify returns a byte slice with a pad byte slice at left side if the str's rune length is smaller than length left_justify :: proc(str: []byte, length: int, pad: []byte, allocator := context.allocator) -> []byte { - n := rune_count(str); + n := rune_count(str) if n >= length || pad == nil { - return clone(str, allocator); + return clone(str, allocator) } - remains := length-1; - pad_len := rune_count(pad); + remains := length-1 + pad_len := rune_count(pad) - b: Buffer; - buffer_init_allocator(&b, 0, len(str) + (remains/pad_len + 1)*len(pad), allocator); + b: Buffer + buffer_init_allocator(&b, 0, len(str) + (remains/pad_len + 1)*len(pad), allocator) - buffer_write(&b, str); - write_pad_string(&b, pad, pad_len, remains); + buffer_write(&b, str) + write_pad_string(&b, pad, pad_len, remains) - return buffer_to_bytes(&b); + return buffer_to_bytes(&b) } // right_justify returns a byte slice with a pad byte slice at right side if the str's rune length is smaller than length right_justify :: proc(str: []byte, length: int, pad: []byte, allocator := context.allocator) -> []byte { - n := rune_count(str); + n := rune_count(str) if n >= length || pad == nil { - return clone(str, allocator); + return clone(str, allocator) } - remains := length-1; - pad_len := rune_count(pad); + remains := length-1 + pad_len := rune_count(pad) - b: Buffer; - buffer_init_allocator(&b, 0, len(str) + (remains/pad_len + 1)*len(pad), allocator); + b: Buffer + buffer_init_allocator(&b, 0, len(str) + (remains/pad_len + 1)*len(pad), allocator) - write_pad_string(&b, pad, pad_len, remains); - buffer_write(&b, str); + write_pad_string(&b, pad, pad_len, remains) + buffer_write(&b, str) - return buffer_to_bytes(&b); + return buffer_to_bytes(&b) } @@ -1047,19 +1047,19 @@ right_justify :: proc(str: []byte, length: int, pad: []byte, allocator := contex @private write_pad_string :: proc(b: ^Buffer, pad: []byte, pad_len, remains: int) { - repeats := remains / pad_len; + repeats := remains / pad_len for i := 0; i < repeats; i += 1 { - buffer_write(b, pad); + buffer_write(b, pad) } - n := remains % pad_len; - p := pad; + n := remains % pad_len + p := pad for i := 0; i < n; i += 1 { - r, width := utf8.decode_rune(p); - buffer_write_rune(b, r); - p = p[width:]; + r, width := utf8.decode_rune(p) + buffer_write_rune(b, r) + p = p[width:] } } @@ -1067,52 +1067,52 @@ write_pad_string :: proc(b: ^Buffer, pad: []byte, pad_len, remains: int) { // fields splits the byte slice s around each instance of one or more consecutive white space character, defined by unicode.is_space // returning a slice of subslices of s or an empty slice if s only contains white space fields :: proc(s: []byte, allocator := context.allocator) -> [][]byte #no_bounds_check { - n := 0; - was_space := 1; - set_bits := u8(0); + n := 0 + was_space := 1 + set_bits := u8(0) // check to see for i in 0..<len(s) { - r := s[i]; - set_bits |= r; - is_space := int(_ascii_space[r]); - n += was_space & ~is_space; - was_space = is_space; + r := s[i] + set_bits |= r + is_space := int(_ascii_space[r]) + n += was_space & ~is_space + was_space = is_space } if set_bits >= utf8.RUNE_SELF { - return fields_proc(s, unicode.is_space, allocator); + return fields_proc(s, unicode.is_space, allocator) } if n == 0 { - return nil; + return nil } - a := make([][]byte, n, allocator); - na := 0; - field_start := 0; - i := 0; + a := make([][]byte, n, allocator) + na := 0 + field_start := 0 + i := 0 for i < len(s) && _ascii_space[s[i]] != 0 { - i += 1; + i += 1 } - field_start = i; + field_start = i for i < len(s) { if _ascii_space[s[i]] == 0 { - i += 1; - continue; + i += 1 + continue } - a[na] = s[field_start : i]; - na += 1; - i += 1; + a[na] = s[field_start : i] + na += 1 + i += 1 for i < len(s) && _ascii_space[s[i]] != 0 { - i += 1; + i += 1 } - field_start = i; + field_start = i } if field_start < len(s) { - a[na] = s[field_start:]; + a[na] = s[field_start:] } - return a; + return a } @@ -1123,28 +1123,28 @@ fields :: proc(s: []byte, allocator := context.allocator) -> [][]byte #no_bounds // fields_proc makes no guarantee about the order in which it calls f(ch) // it assumes that `f` always returns the same value for a given ch fields_proc :: proc(s: []byte, f: proc(rune) -> bool, allocator := context.allocator) -> [][]byte #no_bounds_check { - subslices := make([dynamic][]byte, 0, 32, allocator); + subslices := make([dynamic][]byte, 0, 32, allocator) - start, end := -1, -1; + start, end := -1, -1 for r, offset in string(s) { - end = offset; + end = offset if f(r) { if start >= 0 { - append(&subslices, s[start : end]); + append(&subslices, s[start : end]) // -1 could be used, but just speed it up through bitwise not // gotta love 2's complement - start = ~start; + start = ~start } } else { if start < 0 { - start = end; + start = end } } } if start >= 0 { - append(&subslices, s[start : end]); + append(&subslices, s[start : end]) } - return subslices[:]; + return subslices[:] } diff --git a/core/bytes/reader.odin b/core/bytes/reader.odin index 2032616d0..b10fd009c 100644 --- a/core/bytes/reader.odin +++ b/core/bytes/reader.odin @@ -10,168 +10,168 @@ Reader :: struct { } reader_init :: proc(r: ^Reader, s: []byte) { - r.s = s; - r.i = 0; - r.prev_rune = -1; + r.s = s + r.i = 0 + r.prev_rune = -1 } reader_to_stream :: proc(r: ^Reader) -> (s: io.Stream) { - s.stream_data = r; - s.stream_vtable = _reader_vtable; - return; + s.stream_data = r + s.stream_vtable = _reader_vtable + return } reader_length :: proc(r: ^Reader) -> int { if r.i >= i64(len(r.s)) { - return 0; + return 0 } - return int(i64(len(r.s)) - r.i); + return int(i64(len(r.s)) - r.i) } reader_size :: proc(r: ^Reader) -> i64 { - return i64(len(r.s)); + return i64(len(r.s)) } reader_read :: proc(r: ^Reader, p: []byte) -> (n: int, err: io.Error) { if r.i >= i64(len(r.s)) { - return 0, .EOF; + return 0, .EOF } - r.prev_rune = -1; - n = copy(p, r.s[r.i:]); - r.i += i64(n); - return; + r.prev_rune = -1 + n = copy(p, r.s[r.i:]) + r.i += i64(n) + return } reader_read_at :: proc(r: ^Reader, p: []byte, off: i64) -> (n: int, err: io.Error) { if off < 0 { - return 0, .Invalid_Offset; + return 0, .Invalid_Offset } if off >= i64(len(r.s)) { - return 0, .EOF; + return 0, .EOF } - n = copy(p, r.s[off:]); + n = copy(p, r.s[off:]) if n < len(p) { - err = .EOF; + err = .EOF } - return; + return } reader_read_byte :: proc(r: ^Reader) -> (byte, io.Error) { - r.prev_rune = -1; + r.prev_rune = -1 if r.i >= i64(len(r.s)) { - return 0, .EOF; + return 0, .EOF } - b := r.s[r.i]; - r.i += 1; - return b, nil; + b := r.s[r.i] + r.i += 1 + return b, nil } reader_unread_byte :: proc(r: ^Reader) -> io.Error { if r.i <= 0 { - return .Invalid_Unread; + return .Invalid_Unread } - r.prev_rune = -1; - r.i -= 1; - return nil; + r.prev_rune = -1 + r.i -= 1 + return nil } reader_read_rune :: proc(r: ^Reader) -> (ch: rune, size: int, err: io.Error) { if r.i >= i64(len(r.s)) { - r.prev_rune = -1; - return 0, 0, .EOF; + r.prev_rune = -1 + return 0, 0, .EOF } - r.prev_rune = int(r.i); + r.prev_rune = int(r.i) if c := r.s[r.i]; c < utf8.RUNE_SELF { - r.i += 1; - return rune(c), 1, nil; + r.i += 1 + return rune(c), 1, nil } - ch, size = utf8.decode_rune(r.s[r.i:]); - r.i += i64(size); - return; + ch, size = utf8.decode_rune(r.s[r.i:]) + r.i += i64(size) + return } reader_unread_rune :: proc(r: ^Reader) -> io.Error { if r.i <= 0 { - return .Invalid_Unread; + return .Invalid_Unread } if r.prev_rune < 0 { - return .Invalid_Unread; + return .Invalid_Unread } - r.i = i64(r.prev_rune); - r.prev_rune = -1; - return nil; + r.i = i64(r.prev_rune) + r.prev_rune = -1 + return nil } reader_seek :: proc(r: ^Reader, offset: i64, whence: io.Seek_From) -> (i64, io.Error) { - r.prev_rune = -1; - abs: i64; + r.prev_rune = -1 + abs: i64 switch whence { case .Start: - abs = offset; + abs = offset case .Current: - abs = r.i + offset; + abs = r.i + offset case .End: - abs = i64(len(r.s)) + offset; + abs = i64(len(r.s)) + offset case: - return 0, .Invalid_Whence; + return 0, .Invalid_Whence } if abs < 0 { - return 0, .Invalid_Offset; + return 0, .Invalid_Offset } - r.i = abs; - return abs, nil; + r.i = abs + return abs, nil } reader_write_to :: proc(r: ^Reader, w: io.Writer) -> (n: i64, err: io.Error) { - r.prev_rune = -1; + r.prev_rune = -1 if r.i >= i64(len(r.s)) { - return 0, nil; + return 0, nil } - s := r.s[r.i:]; - m: int; - m, err = io.write(w, s); + s := r.s[r.i:] + m: int + m, err = io.write(w, s) if m > len(s) { - panic("bytes.Reader.write_to: invalid io.write_string count"); + panic("bytes.Reader.write_to: invalid io.write_string count") } - r.i += i64(m); - n = i64(m); + r.i += i64(m) + n = i64(m) if m != len(s) && err == nil { - err = .Short_Write; + err = .Short_Write } - return; + return } @(private) _reader_vtable := &io.Stream_VTable{ impl_size = proc(s: io.Stream) -> i64 { - r := (^Reader)(s.stream_data); - return reader_size(r); + r := (^Reader)(s.stream_data) + return reader_size(r) }, impl_read = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) { - r := (^Reader)(s.stream_data); - return reader_read(r, p); + r := (^Reader)(s.stream_data) + return reader_read(r, p) }, impl_read_at = proc(s: io.Stream, p: []byte, off: i64) -> (n: int, err: io.Error) { - r := (^Reader)(s.stream_data); - return reader_read_at(r, p, off); + r := (^Reader)(s.stream_data) + return reader_read_at(r, p, off) }, impl_read_byte = proc(s: io.Stream) -> (byte, io.Error) { - r := (^Reader)(s.stream_data); - return reader_read_byte(r); + r := (^Reader)(s.stream_data) + return reader_read_byte(r) }, impl_unread_byte = proc(s: io.Stream) -> io.Error { - r := (^Reader)(s.stream_data); - return reader_unread_byte(r); + r := (^Reader)(s.stream_data) + return reader_unread_byte(r) }, impl_read_rune = proc(s: io.Stream) -> (ch: rune, size: int, err: io.Error) { - r := (^Reader)(s.stream_data); - return reader_read_rune(r); + r := (^Reader)(s.stream_data) + return reader_read_rune(r) }, impl_unread_rune = proc(s: io.Stream) -> io.Error { - r := (^Reader)(s.stream_data); - return reader_unread_rune(r); + r := (^Reader)(s.stream_data) + return reader_unread_rune(r) }, impl_seek = proc(s: io.Stream, offset: i64, whence: io.Seek_From) -> (i64, io.Error) { - r := (^Reader)(s.stream_data); - return reader_seek(r, offset, whence); + r := (^Reader)(s.stream_data) + return reader_seek(r, offset, whence) }, impl_write_to = proc(s: io.Stream, w: io.Writer) -> (n: i64, err: io.Error) { - r := (^Reader)(s.stream_data); - return reader_write_to(r, w); + r := (^Reader)(s.stream_data) + return reader_write_to(r, w) }, -}; +} diff --git a/core/c/c.odin b/core/c/c.odin index 757abcac9..40c273927 100644 --- a/core/c/c.odin +++ b/core/c/c.odin @@ -2,34 +2,34 @@ package c import b "core:builtin" -CHAR_BIT :: 8; - -bool :: b.bool; -char :: b.u8; -byte :: b.byte; -schar :: b.i8; -uchar :: b.u8; -short :: b.i16; -ushort :: b.u16; -int :: b.i32; -uint :: b.u32; - -long :: b.i32 when (ODIN_OS == "windows" || size_of(b.rawptr) == 4) else b.i64; -ulong :: b.u32 when (ODIN_OS == "windows" || size_of(b.rawptr) == 4) else b.u64; - -longlong :: b.i64; -ulonglong :: b.u64; -float :: b.f32; -double :: b.f64; -complex_float :: b.complex64; -complex_double :: b.complex128; +CHAR_BIT :: 8 + +bool :: b.bool +char :: b.u8 +byte :: b.byte +schar :: b.i8 +uchar :: b.u8 +short :: b.i16 +ushort :: b.u16 +int :: b.i32 +uint :: b.u32 + +long :: b.i32 when (ODIN_OS == "windows" || size_of(b.rawptr) == 4) else b.i64 +ulong :: b.u32 when (ODIN_OS == "windows" || size_of(b.rawptr) == 4) else b.u64 + +longlong :: b.i64 +ulonglong :: b.u64 +float :: b.f32 +double :: b.f64 +complex_float :: b.complex64 +complex_double :: b.complex128 #assert(size_of(b.uintptr) == size_of(b.int)); -size_t :: b.uint; -ssize_t :: b.int; -ptrdiff_t :: b.int; -uintptr_t :: b.uintptr; -intptr_t :: b.int; +size_t :: b.uint +ssize_t :: b.int +ptrdiff_t :: b.int +uintptr_t :: b.uintptr +intptr_t :: b.int -wchar_t :: b.u16 when (ODIN_OS == "windows") else b.u32; +wchar_t :: b.u16 when (ODIN_OS == "windows") else b.u32 diff --git a/core/c/frontend/preprocessor/const_expr.odin b/core/c/frontend/preprocessor/const_expr.odin index 5f52fff9c..ff13f6432 100644 --- a/core/c/frontend/preprocessor/const_expr.odin +++ b/core/c/frontend/preprocessor/const_expr.odin @@ -6,20 +6,20 @@ const_expr :: proc(rest: ^^Token, tok: ^Token) -> i64 { // TODO(bill): Handle const_expr correctly // This is effectively a mini-parser - assert(rest != nil); - assert(tok != nil); - rest^ = tokenizer.new_eof(tok); + assert(rest != nil) + assert(tok != nil) + rest^ = tokenizer.new_eof(tok) switch v in tok.val { case i64: - return v; + return v case f64: - return i64(v); + return i64(v) case string: - return 0; + return 0 case []u16: // TODO case []u32: // TODO } - return 0; + return 0 } diff --git a/core/c/frontend/preprocessor/preprocess.odin b/core/c/frontend/preprocessor/preprocess.odin index 2136c19ba..21ff2b4eb 100644 --- a/core/c/frontend/preprocessor/preprocess.odin +++ b/core/c/frontend/preprocessor/preprocess.odin @@ -10,11 +10,11 @@ import "core:unicode/utf16" import "core:os" @(private) -Tokenizer :: tokenizer.Tokenizer; +Tokenizer :: tokenizer.Tokenizer @(private) -Token :: tokenizer.Token; +Token :: tokenizer.Token -Error_Handler :: tokenizer.Error_Handler; +Error_Handler :: tokenizer.Error_Handler Macro_Param :: struct { next: ^Macro_Param, @@ -33,7 +33,7 @@ Macro_Kind :: enum u8 { Value_Like, } -Macro_Handler :: #type proc(^Preprocessor, ^Token) -> ^Token; +Macro_Handler :: #type proc(^Preprocessor, ^Token) -> ^Token Macro :: struct { name: string, @@ -57,7 +57,7 @@ Cond_Incl :: struct { included: bool, } -Pragma_Handler :: #type proc(^Preprocessor, ^Token); +Pragma_Handler :: #type proc(^Preprocessor, ^Token) Preprocessor :: struct { // Lookup tables @@ -87,230 +87,230 @@ Preprocessor :: struct { warning_count: int, } -MAX_INCLUDE_LEVEL :: 1024; +MAX_INCLUDE_LEVEL :: 1024 error :: proc(cpp: ^Preprocessor, tok: ^Token, msg: string, args: ..any) { if cpp.err != nil { - cpp.err(tok.pos, msg, ..args); + cpp.err(tok.pos, msg, ..args) } - cpp.error_count += 1; + cpp.error_count += 1 } warn :: proc(cpp: ^Preprocessor, tok: ^Token, msg: string, args: ..any) { if cpp.warn != nil { - cpp.warn(tok.pos, msg, ..args); + cpp.warn(tok.pos, msg, ..args) } - cpp.warning_count += 1; + cpp.warning_count += 1 } is_hash :: proc(tok: ^Token) -> bool { - return tok.at_bol && tok.lit == "#"; + return tok.at_bol && tok.lit == "#" } skip_line :: proc(cpp: ^Preprocessor, tok: ^Token) -> ^Token { - tok := tok; + tok := tok if tok.at_bol { - return tok; + return tok } - warn(cpp, tok, "extra token"); + warn(cpp, tok, "extra token") for tok.at_bol { - tok = tok.next; + tok = tok.next } - return tok; + return tok } append_token :: proc(a, b: ^Token) -> ^Token { if a.kind == .EOF { - return b; + return b } - head: Token; - curr := &head; + head: Token + curr := &head for tok := a; tok.kind != .EOF; tok = tok.next { - curr.next = tokenizer.copy_token(tok); - curr = curr.next; + curr.next = tokenizer.copy_token(tok) + curr = curr.next } - curr.next = b; - return head.next; + curr.next = b + return head.next } is_hex_digit :: proc(x: byte) -> bool { switch x { case '0'..='9', 'a'..='f', 'A'..='F': - return true; + return true } - return false; + return false } from_hex :: proc(x: byte) -> i32 { switch x { case '0'..='9': - return i32(x) - '0'; + return i32(x) - '0' case 'a'..='f': - return i32(x) - 'a' + 10; + return i32(x) - 'a' + 10 case 'A'..='F': - return i32(x) - 'A' + 10; + return i32(x) - 'A' + 10 } - return 16; + return 16 } convert_pp_number :: proc(tok: ^Token) { convert_pp_int :: proc(tok: ^Token) -> bool { - p := tok.lit; - base := 10; + p := tok.lit + base := 10 if len(p) > 2 { if strings.equal_fold(p[:2], "0x") && is_hex_digit(p[2]) { - p = p[2:]; - base = 16; + p = p[2:] + base = 16 } else if strings.equal_fold(p[:2], "0b") && p[2] == '0' || p[2] == '1' { - p = p[2:]; - base = 2; + p = p[2:] + base = 2 } } if base == 10 && p[0] == '0' { - base = 8; + base = 8 } - tok.val, _ = strconv.parse_i64_of_base(p, base); + tok.val, _ = strconv.parse_i64_of_base(p, base) - l, u: int; + l, u: int - suf: [3]byte; - suf_n := 0; - i := len(p)-1; + suf: [3]byte + suf_n := 0 + i := len(p)-1 for /**/; i >= 0 && suf_n < len(suf); i -= 1 { switch p[i] { case 'l', 'L': - suf[suf_n] = 'l'; - l += 1; - suf_n += 1; + suf[suf_n] = 'l' + l += 1 + suf_n += 1 case 'u', 'U': - suf[suf_n] = 'u'; - u += 1; - suf_n += 1; + suf[suf_n] = 'u' + u += 1 + suf_n += 1 } } if i < len(p) { if !is_hex_digit(p[i]) && p[i] != '.' { - return false; + return false } } if u > 1 { - return false; + return false } if l > 2 { - return false; + return false } if u == 1 { switch l { - case 0: tok.type_hint = .Unsigned_Int; - case 1: tok.type_hint = .Unsigned_Long; - case 2: tok.type_hint = .Unsigned_Long_Long; + case 0: tok.type_hint = .Unsigned_Int + case 1: tok.type_hint = .Unsigned_Long + case 2: tok.type_hint = .Unsigned_Long_Long } } else { switch l { - case 0: tok.type_hint = .Int; - case 1: tok.type_hint = .Long; - case 2: tok.type_hint = .Long_Long; + case 0: tok.type_hint = .Int + case 1: tok.type_hint = .Long + case 2: tok.type_hint = .Long_Long } } - return true; + return true } if convert_pp_int(tok) { - return; + return } - fval, _ := strconv.parse_f64(tok.lit); - tok.val = fval; + fval, _ := strconv.parse_f64(tok.lit) + tok.val = fval - end := tok.lit[len(tok.lit)-1]; + end := tok.lit[len(tok.lit)-1] switch end { case 'f', 'F': - tok.type_hint = .Float; + tok.type_hint = .Float case 'l', 'L': - tok.type_hint = .Long_Double; + tok.type_hint = .Long_Double case: - tok.type_hint = .Double; + tok.type_hint = .Double } } convert_pp_char :: proc(tok: ^Token) { - assert(len(tok.lit) >= 2); - r, _, _, _ := unquote_char(tok.lit, tok.lit[0]); - tok.val = i64(r); + assert(len(tok.lit) >= 2) + r, _, _, _ := unquote_char(tok.lit, tok.lit[0]) + tok.val = i64(r) - tok.type_hint = .Int; + tok.type_hint = .Int switch tok.prefix { - case "u": tok.type_hint = .UTF_16; - case "U": tok.type_hint = .UTF_32; - case "L": tok.type_hint = .UTF_Wide; + case "u": tok.type_hint = .UTF_16 + case "U": tok.type_hint = .UTF_32 + case "L": tok.type_hint = .UTF_Wide } } wide_char_size :: proc(cpp: ^Preprocessor) -> int { - char_size := 4; + char_size := 4 if cpp.wide_char_size > 0 { - char_size = clamp(cpp.wide_char_size, 1, 4); - assert(char_size & (char_size-1) == 0); + char_size = clamp(cpp.wide_char_size, 1, 4) + assert(char_size & (char_size-1) == 0) } - return char_size; + return char_size } convert_pp_string :: proc(cpp: ^Preprocessor, tok: ^Token) { - assert(len(tok.lit) >= 2); - str, _, _ := unquote_string(tok.lit); - tok.val = str; + assert(len(tok.lit) >= 2) + str, _, _ := unquote_string(tok.lit) + tok.val = str - char_size := 1; + char_size := 1 switch tok.prefix { case "u8": - tok.type_hint = .UTF_8; - char_size = 1; + tok.type_hint = .UTF_8 + char_size = 1 case "u": - tok.type_hint = .UTF_16; - char_size = 2; + tok.type_hint = .UTF_16 + char_size = 2 case "U": - tok.type_hint = .UTF_32; - char_size = 4; + tok.type_hint = .UTF_32 + char_size = 4 case "L": - tok.type_hint = .UTF_Wide; - char_size = wide_char_size(cpp); + tok.type_hint = .UTF_Wide + char_size = wide_char_size(cpp) } switch char_size { case 2: - n: int; - buf := make([]u16, len(str)); + n: int + buf := make([]u16, len(str)) for c in str { - ch := c; + ch := c if ch < 0x10000 { - buf[n] = u16(ch); - n += 1; + buf[n] = u16(ch) + n += 1 } else { - ch -= 0x10000; - buf[n+0] = 0xd800 + u16((ch >> 10) & 0x3ff); - buf[n+1] = 0xdc00 + u16(ch & 0x3ff); - n += 2; + ch -= 0x10000 + buf[n+0] = 0xd800 + u16((ch >> 10) & 0x3ff) + buf[n+1] = 0xdc00 + u16(ch & 0x3ff) + n += 2 } } - tok.val = buf[:n]; + tok.val = buf[:n] case 4: - n: int; - buf := make([]u32, len(str)); + n: int + buf := make([]u32, len(str)) for ch in str { - buf[n] = u32(ch); - n += 1; + buf[n] = u32(ch) + n += 1 } - tok.val = buf[:n]; + tok.val = buf[:n] } } @@ -318,1193 +318,1193 @@ convert_pp_string :: proc(cpp: ^Preprocessor, tok: ^Token) { convert_pp_token :: proc(cpp: ^Preprocessor, t: ^Token, is_keyword: tokenizer.Is_Keyword_Proc) { switch { case t.kind == .Char: - convert_pp_char(t); + convert_pp_char(t) case t.kind == .String: - convert_pp_string(cpp, t); + convert_pp_string(cpp, t) case is_keyword != nil && is_keyword(t): - t.kind = .Keyword; + t.kind = .Keyword case t.kind == .PP_Number: - convert_pp_number(t); + convert_pp_number(t) } } convert_pp_tokens :: proc(cpp: ^Preprocessor, tok: ^Token, is_keyword: tokenizer.Is_Keyword_Proc) { for t := tok; t != nil && t.kind != .EOF; t = t.next { - convert_pp_token(cpp, tok, is_keyword); + convert_pp_token(cpp, tok, is_keyword) } } join_adjacent_string_literals :: proc(cpp: ^Preprocessor, initial_tok: ^Token) { for tok1 := initial_tok; tok1.kind != .EOF; /**/ { if tok1.kind != .String || tok1.next.kind != .String { - tok1 = tok1.next; - continue; + tok1 = tok1.next + continue } - type_hint := tokenizer.Token_Type_Hint.None; - char_size := 1; + type_hint := tokenizer.Token_Type_Hint.None + char_size := 1 - start := tok1; + start := tok1 for t := tok1; t != nil && t.kind == .String; t = t.next { if t.val == nil { - convert_pp_string(cpp, t); + convert_pp_string(cpp, t) } - tok1 = t.next; + tok1 = t.next if type_hint != t.type_hint { if t.type_hint != .None && type_hint != .None { - error(cpp, t, "unsupported non-standard concatenation of string literals of different types"); + error(cpp, t, "unsupported non-standard concatenation of string literals of different types") } - prev_char_size := char_size; + prev_char_size := char_size #partial switch type_hint { - case .UTF_8: char_size = max(char_size, 1); - case .UTF_16: char_size = max(char_size, 2); - case .UTF_32: char_size = max(char_size, 4); - case .UTF_Wide: char_size = max(char_size, wide_char_size(cpp)); + case .UTF_8: char_size = max(char_size, 1) + case .UTF_16: char_size = max(char_size, 2) + case .UTF_32: char_size = max(char_size, 4) + case .UTF_Wide: char_size = max(char_size, wide_char_size(cpp)) } if type_hint == .None || prev_char_size < char_size { - type_hint = t.type_hint; + type_hint = t.type_hint } } } // NOTE(bill): Verbose logic in order to correctly concantenate strings, even if they different in type - max_len := 0; + max_len := 0 switch char_size { case 1: for t := start; t != nil && t.kind == .String; t = t.next { #partial switch v in t.val { - case string: max_len += len(v); - case []u16: max_len += 2*len(v); - case []u32: max_len += 4*len(v); + case string: max_len += len(v) + case []u16: max_len += 2*len(v) + case []u32: max_len += 4*len(v) } } - n := 0; - buf := make([]byte, max_len); + n := 0 + buf := make([]byte, max_len) for t := start; t != nil && t.kind == .String; t = t.next { #partial switch v in t.val { case string: - n += copy(buf[n:], v); + n += copy(buf[n:], v) case []u16: for i := 0; i < len(v); /**/ { - c1 := v[i]; - r: rune; + c1 := v[i] + r: rune if !utf16.is_surrogate(rune(c1)) { - r = rune(c1); - i += 1; + r = rune(c1) + i += 1 } else if i+1 == len(v) { - r = utf16.REPLACEMENT_CHAR; - i += 1; + r = utf16.REPLACEMENT_CHAR + i += 1 } else { - c2 := v[i+1]; - i += 2; - r = utf16.decode_surrogate_pair(rune(c1), rune(c2)); + c2 := v[i+1] + i += 2 + r = utf16.decode_surrogate_pair(rune(c1), rune(c2)) } - b, w := utf8.encode_rune(r); - n += copy(buf[n:], b[:w]); + b, w := utf8.encode_rune(r) + n += copy(buf[n:], b[:w]) } case []u32: for r in v { - b, w := utf8.encode_rune(rune(r)); - n += copy(buf[n:], b[:w]); + b, w := utf8.encode_rune(rune(r)) + n += copy(buf[n:], b[:w]) } } } - new_tok := tokenizer.copy_token(start); - new_tok.lit = ""; - new_tok.val = string(buf[:n]); - new_tok.next = tok1; - new_tok.type_hint = type_hint; - start^ = new_tok^; + new_tok := tokenizer.copy_token(start) + new_tok.lit = "" + new_tok.val = string(buf[:n]) + new_tok.next = tok1 + new_tok.type_hint = type_hint + start^ = new_tok^ case 2: for t := start; t != nil && t.kind == .String; t = t.next { #partial switch v in t.val { - case string: max_len += len(v); - case []u16: max_len += len(v); - case []u32: max_len += 2*len(v); + case string: max_len += len(v) + case []u16: max_len += len(v) + case []u32: max_len += 2*len(v) } } - n := 0; - buf := make([]u16, max_len); + n := 0 + buf := make([]u16, max_len) for t := start; t != nil && t.kind == .String; t = t.next { #partial switch v in t.val { case string: for r in v { if r >= 0x10000 { - c1, c2 := utf16.encode_surrogate_pair(r); - buf[n+0] = u16(c1); - buf[n+1] = u16(c2); - n += 2; + c1, c2 := utf16.encode_surrogate_pair(r) + buf[n+0] = u16(c1) + buf[n+1] = u16(c2) + n += 2 } else { - buf[n] = u16(r); - n += 1; + buf[n] = u16(r) + n += 1 } } case []u16: - n += copy(buf[n:], v); + n += copy(buf[n:], v) case []u32: for r in v { if r >= 0x10000 { - c1, c2 := utf16.encode_surrogate_pair(rune(r)); - buf[n+0] = u16(c1); - buf[n+1] = u16(c2); - n += 2; + c1, c2 := utf16.encode_surrogate_pair(rune(r)) + buf[n+0] = u16(c1) + buf[n+1] = u16(c2) + n += 2 } else { - buf[n] = u16(r); - n += 1; + buf[n] = u16(r) + n += 1 } } } } - new_tok := tokenizer.copy_token(start); - new_tok.lit = ""; - new_tok.val = buf[:n]; - new_tok.next = tok1; - new_tok.type_hint = type_hint; - start^ = new_tok^; + new_tok := tokenizer.copy_token(start) + new_tok.lit = "" + new_tok.val = buf[:n] + new_tok.next = tok1 + new_tok.type_hint = type_hint + start^ = new_tok^ case 4: for t := start; t != nil && t.kind == .String; t = t.next { #partial switch v in t.val { - case string: max_len += len(v); - case []u16: max_len += len(v); - case []u32: max_len += len(v); + case string: max_len += len(v) + case []u16: max_len += len(v) + case []u32: max_len += len(v) } } - n := 0; - buf := make([]u32, max_len); + n := 0 + buf := make([]u32, max_len) for t := start; t != nil && t.kind == .String; t = t.next { #partial switch v in t.val { case string: for r in v { - buf[n] = u32(r); - n += 1; + buf[n] = u32(r) + n += 1 } case []u16: for i := 0; i < len(v); /**/ { - c1 := v[i]; + c1 := v[i] if !utf16.is_surrogate(rune(c1)) { - buf[n] = u32(c1); - n += 1; - i += 1; + buf[n] = u32(c1) + n += 1 + i += 1 } else if i+1 == len(v) { - buf[n] = utf16.REPLACEMENT_CHAR; - n += 1; - i += 1; + buf[n] = utf16.REPLACEMENT_CHAR + n += 1 + i += 1 } else { - c2 := v[i+1]; - i += 2; - r := utf16.decode_surrogate_pair(rune(c1), rune(c2)); - buf[n] = u32(r); - n += 1; + c2 := v[i+1] + i += 2 + r := utf16.decode_surrogate_pair(rune(c1), rune(c2)) + buf[n] = u32(r) + n += 1 } } case []u32: - n += copy(buf[n:], v); + n += copy(buf[n:], v) } } - new_tok := tokenizer.copy_token(start); - new_tok.lit = ""; - new_tok.val = buf[:n]; - new_tok.next = tok1; - new_tok.type_hint = type_hint; - start^ = new_tok^; + new_tok := tokenizer.copy_token(start) + new_tok.lit = "" + new_tok.val = buf[:n] + new_tok.next = tok1 + new_tok.type_hint = type_hint + start^ = new_tok^ } } } quote_string :: proc(s: string) -> []byte { - b := &strings.Builder{}; - strings.init_builder(b, 0, len(s)+2); - strings.write_quoted_string(b, s, '"'); - return b.buf[:]; + b := &strings.Builder{} + strings.init_builder(b, 0, len(s)+2) + strings.write_quoted_string(b, s, '"') + return b.buf[:] } _init_tokenizer_from_preprocessor :: proc(t: ^Tokenizer, cpp: ^Preprocessor) -> ^Tokenizer { - t.warn = cpp.warn; - t.err = cpp.err; - return t; + t.warn = cpp.warn + t.err = cpp.err + return t } new_string_token :: proc(cpp: ^Preprocessor, str: string, tok: ^Token) -> ^Token { - assert(tok != nil); - assert(str != ""); - t := _init_tokenizer_from_preprocessor(&Tokenizer{}, cpp); - src := quote_string(str); - return tokenizer.inline_tokenize(t, tok, src); + assert(tok != nil) + assert(str != "") + t := _init_tokenizer_from_preprocessor(&Tokenizer{}, cpp) + src := quote_string(str) + return tokenizer.inline_tokenize(t, tok, src) } stringize :: proc(cpp: ^Preprocessor, hash, arg: ^Token) -> ^Token { - s := join_tokens(arg, nil); - return new_string_token(cpp, s, hash); + s := join_tokens(arg, nil) + return new_string_token(cpp, s, hash) } new_number_token :: proc(cpp: ^Preprocessor, i: i64, tok: ^Token) -> ^Token { - t := _init_tokenizer_from_preprocessor(&Tokenizer{}, cpp); - buf: [32]byte; - n := len(strconv.append_int(buf[:], i, 10)); - src := make([]byte, n); - copy(src, buf[:n]); - return tokenizer.inline_tokenize(t, tok, src); + t := _init_tokenizer_from_preprocessor(&Tokenizer{}, cpp) + buf: [32]byte + n := len(strconv.append_int(buf[:], i, 10)) + src := make([]byte, n) + copy(src, buf[:n]) + return tokenizer.inline_tokenize(t, tok, src) } find_macro :: proc(cpp: ^Preprocessor, tok: ^Token) -> ^Macro { if tok.kind != .Ident { - return nil; + return nil } - return cpp.macros[tok.lit]; + return cpp.macros[tok.lit] } add_macro :: proc(cpp: ^Preprocessor, name: string, kind: Macro_Kind, body: ^Token) -> ^Macro { - m := new(Macro); - m.name = name; - m.kind = kind; - m.body = body; - cpp.macros[name] = m; - return m; + m := new(Macro) + m.name = name + m.kind = kind + m.body = body + cpp.macros[name] = m + return m } undef_macro :: proc(cpp: ^Preprocessor, name: string) { - delete_key(&cpp.macros, name); + delete_key(&cpp.macros, name) } add_builtin :: proc(cpp: ^Preprocessor, name: string, handler: Macro_Handler) -> ^Macro { - m := add_macro(cpp, name, .Value_Like, nil); - m.handler = handler; - return m; + m := add_macro(cpp, name, .Value_Like, nil) + m.handler = handler + return m } skip :: proc(cpp: ^Preprocessor, tok: ^Token, op: string) -> ^Token { if tok.lit != op { - error(cpp, tok, "expected '%q'", op); + error(cpp, tok, "expected '%q'", op) } - return tok.next; + return tok.next } consume :: proc(rest: ^^Token, tok: ^Token, lit: string) -> bool { if tok.lit == lit { - rest^ = tok.next; - return true; + rest^ = tok.next + return true } - rest^ = tok; - return false; + rest^ = tok + return false } read_macro_params :: proc(cpp: ^Preprocessor, rest: ^^Token, tok: ^Token) -> (param: ^Macro_Param, va_args_name: string) { - head: Macro_Param; - curr := &head; + head: Macro_Param + curr := &head - tok := tok; + tok := tok for tok.lit != ")" && tok.kind != .EOF { if curr != &head { - tok = skip(cpp, tok, ","); + tok = skip(cpp, tok, ",") } if tok.lit == "..." { - va_args_name = "__VA_ARGS__"; - rest^ = skip(cpp, tok.next, ")"); - param = head.next; - return; + va_args_name = "__VA_ARGS__" + rest^ = skip(cpp, tok.next, ")") + param = head.next + return } if tok.kind != .Ident { - error(cpp, tok, "expected an identifier"); + error(cpp, tok, "expected an identifier") } if tok.next.lit == "..." { - va_args_name = tok.lit; - rest^ = skip(cpp, tok.next.next, ")"); - param = head.next; - return; + va_args_name = tok.lit + rest^ = skip(cpp, tok.next.next, ")") + param = head.next + return } - m := new(Macro_Param); - m.name = tok.lit; - curr.next = m; - curr = curr.next; - tok = tok.next; + m := new(Macro_Param) + m.name = tok.lit + curr.next = m + curr = curr.next + tok = tok.next } - rest^ = tok.next; - param = head.next; - return; + rest^ = tok.next + param = head.next + return } copy_line :: proc(rest: ^^Token, tok: ^Token) -> ^Token { - head: Token; - curr := &head; + head: Token + curr := &head - tok := tok; + tok := tok for ; !tok.at_bol; tok = tok.next { - curr.next = tokenizer.copy_token(tok); - curr = curr.next; + curr.next = tokenizer.copy_token(tok) + curr = curr.next } - curr.next = tokenizer.new_eof(tok); - rest^ = tok; - return head.next; + curr.next = tokenizer.new_eof(tok) + rest^ = tok + return head.next } read_macro_definition :: proc(cpp: ^Preprocessor, rest: ^^Token, tok: ^Token) { - tok := tok; + tok := tok if tok.kind != .Ident { - error(cpp, tok, "macro name must be an identifier"); + error(cpp, tok, "macro name must be an identifier") } - name := tok.lit; - tok = tok.next; + name := tok.lit + tok = tok.next if !tok.has_space && tok.lit == "(" { - params, va_args_name := read_macro_params(cpp, &tok, tok.next); + params, va_args_name := read_macro_params(cpp, &tok, tok.next) - m := add_macro(cpp, name, .Function_Like, copy_line(rest, tok)); - m.params = params; - m.va_args_name = va_args_name; + m := add_macro(cpp, name, .Function_Like, copy_line(rest, tok)) + m.params = params + m.va_args_name = va_args_name } else { - add_macro(cpp, name, .Value_Like, copy_line(rest, tok)); + add_macro(cpp, name, .Value_Like, copy_line(rest, tok)) } } join_tokens :: proc(tok, end: ^Token) -> string { - n := 1; + n := 1 for t := tok; t != end && t.kind != .EOF; t = t.next { if t != tok && t.has_space { - n += 1; + n += 1 } - n += len(t.lit); + n += len(t.lit) } - buf := make([]byte, n); + buf := make([]byte, n) - pos := 0; + pos := 0 for t := tok; t != end && t.kind != .EOF; t = t.next { if t != tok && t.has_space { - buf[pos] = ' '; - pos += 1; + buf[pos] = ' ' + pos += 1 } - copy(buf[pos:], t.lit); - pos += len(t.lit); + copy(buf[pos:], t.lit) + pos += len(t.lit) } - return string(buf[:pos]); + return string(buf[:pos]) } read_include_filename :: proc(cpp: ^Preprocessor, rest: ^^Token, tok: ^Token) -> (filename: string, is_quote: bool) { - tok := tok; + tok := tok if tok.kind == .String { - rest^ = skip_line(cpp, tok.next); - filename = tok.lit[1:len(tok.lit)-1]; - is_quote = true; - return; + rest^ = skip_line(cpp, tok.next) + filename = tok.lit[1:len(tok.lit)-1] + is_quote = true + return } if tok.lit == "<" { - start := tok; + start := tok for ; tok.kind != .EOF; tok = tok.next { if tok.at_bol || tok.kind == .EOF { - error(cpp, tok, "expected '>'"); + error(cpp, tok, "expected '>'") } - is_quote = false; + is_quote = false if tok.lit == ">" { - break; + break } } - rest^ = skip_line(cpp, tok.next); - filename = join_tokens(start.next, tok); - return; + rest^ = skip_line(cpp, tok.next) + filename = join_tokens(start.next, tok) + return } if tok.kind == .Ident { - tok2 := preprocess_internal(cpp, copy_line(rest, tok)); - return read_include_filename(cpp, &tok2, tok2); + tok2 := preprocess_internal(cpp, copy_line(rest, tok)) + return read_include_filename(cpp, &tok2, tok2) } - error(cpp, tok, "expected a filename"); - return; + error(cpp, tok, "expected a filename") + return } skip_cond_incl :: proc(tok: ^Token) -> ^Token { next_skip :: proc(tok: ^Token) -> ^Token { - tok := tok; + tok := tok for tok.kind != .EOF { if is_hash(tok) { switch tok.next.lit { case "if", "ifdef", "ifndef": - tok = next_skip(tok.next.next); - continue; + tok = next_skip(tok.next.next) + continue case "endif": - return tok.next.next; + return tok.next.next } } - tok = tok.next; + tok = tok.next } - return tok; + return tok } - tok := tok; + tok := tok loop: for tok.kind != .EOF { if is_hash(tok) { switch tok.next.lit { case "if", "ifdef", "ifndef": - tok = next_skip(tok.next.next); - continue loop; + tok = next_skip(tok.next.next) + continue loop case "elif", "else", "endif": - break loop; + break loop } } - tok = tok.next; + tok = tok.next } - return tok; + return tok } check_for_include_guard :: proc(tok: ^Token) -> (guard: string, ok: bool) { if !is_hash(tok) || tok.next.lit != "ifndef" { - return; + return } - tok := tok; - tok = tok.next.next; + tok := tok + tok = tok.next.next if tok.kind != .Ident { - return; + return } - m := tok.lit; - tok = tok.next; + m := tok.lit + tok = tok.next if !is_hash(tok) || tok.next.lit != "define" || tok.next.lit != "macro" { - return; + return } for tok.kind != .EOF { if !is_hash(tok) { - tok = tok.next; - continue; + tok = tok.next + continue } if tok.next.lit == "endif" && tok.next.next.kind == .EOF { - return m, true; + return m, true } switch tok.lit { case "if", "ifdef", "ifndef": - tok = skip_cond_incl(tok.next); + tok = skip_cond_incl(tok.next) case: - tok = tok.next; + tok = tok.next } } - return; + return } include_file :: proc(cpp: ^Preprocessor, tok: ^Token, path: string, filename_tok: ^Token) -> ^Token { if cpp.pragma_once[path] { - return tok; + return tok } - guard_name, guard_name_found := cpp.include_guards[path]; + guard_name, guard_name_found := cpp.include_guards[path] if guard_name_found && cpp.macros[guard_name] != nil { - return tok; + return tok } if !os.exists(path) { - error(cpp, filename_tok, "%s: cannot open file", path); - return tok; + error(cpp, filename_tok, "%s: cannot open file", path) + return tok } - cpp.include_level += 1; + cpp.include_level += 1 if cpp.include_level > MAX_INCLUDE_LEVEL { - error(cpp, tok, "exceeded maximum nest amount: %d", MAX_INCLUDE_LEVEL); - return tok; + error(cpp, tok, "exceeded maximum nest amount: %d", MAX_INCLUDE_LEVEL) + return tok } - t := _init_tokenizer_from_preprocessor(&Tokenizer{}, cpp); - tok2 := tokenizer.tokenize_file(t, path, /*file.id*/1); + t := _init_tokenizer_from_preprocessor(&Tokenizer{}, cpp) + tok2 := tokenizer.tokenize_file(t, path, /*file.id*/1) if tok2 == nil { - error(cpp, filename_tok, "%s: cannot open file", path); + error(cpp, filename_tok, "%s: cannot open file", path) } - cpp.include_level -= 1; + cpp.include_level -= 1 - guard_name, guard_name_found = check_for_include_guard(tok2); + guard_name, guard_name_found = check_for_include_guard(tok2) if guard_name_found { - cpp.include_guards[path] = guard_name; + cpp.include_guards[path] = guard_name } - return append_token(tok2, tok); + return append_token(tok2, tok) } find_arg :: proc(args: ^Macro_Arg, tok: ^Token) -> ^Macro_Arg { for ap := args; ap != nil; ap = ap.next { if tok.lit == ap.name { - return ap; + return ap } } - return nil; + return nil } paste :: proc(cpp: ^Preprocessor, lhs, rhs: ^Token) -> ^Token { - buf := strings.concatenate({lhs.lit, rhs.lit}); - t := _init_tokenizer_from_preprocessor(&Tokenizer{}, cpp); - tok := tokenizer.inline_tokenize(t, lhs, transmute([]byte)buf); + buf := strings.concatenate({lhs.lit, rhs.lit}) + t := _init_tokenizer_from_preprocessor(&Tokenizer{}, cpp) + tok := tokenizer.inline_tokenize(t, lhs, transmute([]byte)buf) if tok.next.kind != .EOF { - error(cpp, lhs, "pasting forms '%s', an invalid token", buf); + error(cpp, lhs, "pasting forms '%s', an invalid token", buf) } - return tok; + return tok } has_varargs :: proc(args: ^Macro_Arg) -> bool { for ap := args; ap != nil; ap = ap.next { if ap.name == "__VA_ARGS__" { - return ap.tok.kind != .EOF; + return ap.tok.kind != .EOF } } - return false; + return false } substitute_token :: proc(cpp: ^Preprocessor, tok: ^Token, args: ^Macro_Arg) -> ^Token { - head: Token; - curr := &head; - tok := tok; + head: Token + curr := &head + tok := tok for tok.kind != .EOF { if tok.lit == "#" { - arg := find_arg(args, tok.next); + arg := find_arg(args, tok.next) if arg == nil { - error(cpp, tok.next, "'#' is not followed by a macro parameter"); + error(cpp, tok.next, "'#' is not followed by a macro parameter") } - arg_tok := arg.tok if arg != nil else tok.next; - curr.next = stringize(cpp, tok, arg_tok); - curr = curr.next; - tok = tok.next.next; - continue; + arg_tok := arg.tok if arg != nil else tok.next + curr.next = stringize(cpp, tok, arg_tok) + curr = curr.next + tok = tok.next.next + continue } if tok.lit == "," && tok.next.lit == "##" { if arg := find_arg(args, tok.next.next); arg != nil && arg.is_va_args { if arg.tok.kind == .EOF { - tok = tok.next.next.next; + tok = tok.next.next.next } else { - curr.next = tokenizer.copy_token(tok); - curr = curr.next; - tok = tok.next.next; + curr.next = tokenizer.copy_token(tok) + curr = curr.next + tok = tok.next.next } - continue; + continue } } if tok.lit == "##" { if curr == &head { - error(cpp, tok, "'##' cannot appear at start of macro expansion"); + error(cpp, tok, "'##' cannot appear at start of macro expansion") } if tok.next.kind == .EOF { - error(cpp, tok, "'##' cannot appear at end of macro expansion"); + error(cpp, tok, "'##' cannot appear at end of macro expansion") } if arg := find_arg(args, tok.next); arg != nil { if arg.tok.kind != .EOF { - curr^ = paste(cpp, curr, arg.tok)^; + curr^ = paste(cpp, curr, arg.tok)^ for t := arg.tok.next; t.kind != .EOF; t = t.next { - curr.next = tokenizer.copy_token(t); - curr = curr.next; + curr.next = tokenizer.copy_token(t) + curr = curr.next } } - tok = tok.next.next; - continue; + tok = tok.next.next + continue } - curr^ = paste(cpp, curr, tok.next)^; - tok = tok.next.next; - continue; + curr^ = paste(cpp, curr, tok.next)^ + tok = tok.next.next + continue } - arg := find_arg(args, tok); + arg := find_arg(args, tok) if arg != nil && tok.next.lit == "##" { - rhs := tok.next.next; + rhs := tok.next.next if arg.tok.kind == .EOF { - args2 := find_arg(args, rhs); + args2 := find_arg(args, rhs) if args2 != nil { for t := args.tok; t.kind != .EOF; t = t.next { - curr.next = tokenizer.copy_token(t); - curr = curr.next; + curr.next = tokenizer.copy_token(t) + curr = curr.next } } else { - curr.next = tokenizer.copy_token(rhs); - curr = curr.next; + curr.next = tokenizer.copy_token(rhs) + curr = curr.next } - tok = rhs.next; - continue; + tok = rhs.next + continue } for t := arg.tok; t.kind != .EOF; t = t.next { - curr.next = tokenizer.copy_token(t); - curr = curr.next; + curr.next = tokenizer.copy_token(t) + curr = curr.next } - tok = tok.next; - continue; + tok = tok.next + continue } if tok.lit == "__VA__OPT__" && tok.next.lit == "(" { - opt_arg := read_macro_arg_one(cpp, &tok, tok.next.next, true); + opt_arg := read_macro_arg_one(cpp, &tok, tok.next.next, true) if has_varargs(args) { for t := opt_arg.tok; t.kind != .EOF; t = t.next { - curr.next = t; - curr = curr.next; + curr.next = t + curr = curr.next } } - tok = skip(cpp, tok, ")"); - continue; + tok = skip(cpp, tok, ")") + continue } if arg != nil { - t := preprocess_internal(cpp, arg.tok); - t.at_bol = tok.at_bol; - t.has_space = tok.has_space; + t := preprocess_internal(cpp, arg.tok) + t.at_bol = tok.at_bol + t.has_space = tok.has_space for ; t.kind != .EOF; t = t.next { - curr.next = tokenizer.copy_token(t); - curr = curr.next; + curr.next = tokenizer.copy_token(t) + curr = curr.next } - tok = tok.next; - continue; + tok = tok.next + continue } - curr.next = tokenizer.copy_token(tok); - curr = curr.next; - tok = tok.next; - continue; + curr.next = tokenizer.copy_token(tok) + curr = curr.next + tok = tok.next + continue } - curr.next = tok; - return head.next; + curr.next = tok + return head.next } read_macro_arg_one :: proc(cpp: ^Preprocessor, rest: ^^Token, tok: ^Token, read_rest: bool) -> ^Macro_Arg { - tok := tok; - head: Token; - curr := &head; - level := 0; + tok := tok + head: Token + curr := &head + level := 0 for { if level == 0 && tok.lit == ")" { - break; + break } if level == 0 && !read_rest && tok.lit == "," { - break; + break } if tok.kind == .EOF { - error(cpp, tok, "premature end of input"); + error(cpp, tok, "premature end of input") } switch tok.lit { - case "(": level += 1; - case ")": level -= 1; + case "(": level += 1 + case ")": level -= 1 } - curr.next = tokenizer.copy_token(tok); - curr = curr.next; - tok = tok.next; + curr.next = tokenizer.copy_token(tok) + curr = curr.next + tok = tok.next } - curr.next = tokenizer.new_eof(tok); + curr.next = tokenizer.new_eof(tok) - arg := new(Macro_Arg); - arg.tok = head.next; - rest^ = tok; - return arg; + arg := new(Macro_Arg) + arg.tok = head.next + rest^ = tok + return arg } read_macro_args :: proc(cpp: ^Preprocessor, rest: ^^Token, tok: ^Token, params: ^Macro_Param, va_args_name: string) -> ^Macro_Arg { - tok := tok; - start := tok; - tok = tok.next.next; + tok := tok + start := tok + tok = tok.next.next - head: Macro_Arg; - curr := &head; + head: Macro_Arg + curr := &head - pp := params; + pp := params for ; pp != nil; pp = pp.next { if curr != &head { - tok = skip(cpp, tok, ","); + tok = skip(cpp, tok, ",") } - curr.next = read_macro_arg_one(cpp, &tok, tok, false); - curr = curr.next; - curr.name = pp.name; + curr.next = read_macro_arg_one(cpp, &tok, tok, false) + curr = curr.next + curr.name = pp.name } if va_args_name != "" { - arg: ^Macro_Arg; + arg: ^Macro_Arg if tok.lit == ")" { - arg = new(Macro_Arg); - arg.tok = tokenizer.new_eof(tok); + arg = new(Macro_Arg) + arg.tok = tokenizer.new_eof(tok) } else { if pp != params { - tok = skip(cpp, tok, ","); + tok = skip(cpp, tok, ",") } - arg = read_macro_arg_one(cpp, &tok, tok, true); + arg = read_macro_arg_one(cpp, &tok, tok, true) } - arg.name = va_args_name; - arg.is_va_args = true; - curr.next = arg; - curr = curr.next; + arg.name = va_args_name + arg.is_va_args = true + curr.next = arg + curr = curr.next } else if pp != nil { - error(cpp, start, "too many arguments"); + error(cpp, start, "too many arguments") } - skip(cpp, tok, ")"); - rest^ = tok; - return head.next; + skip(cpp, tok, ")") + rest^ = tok + return head.next } expand_macro :: proc(cpp: ^Preprocessor, rest: ^^Token, tok: ^Token) -> bool { if tokenizer.hide_set_contains(tok.hide_set, tok.lit) { - return false; + return false } - tok := tok; - m := find_macro(cpp, tok); + tok := tok + m := find_macro(cpp, tok) if m == nil { - return false; + return false } if m.handler != nil { - rest^ = m.handler(cpp, tok); - rest^.next = tok.next; - return true; + rest^ = m.handler(cpp, tok) + rest^.next = tok.next + return true } if m.kind == .Value_Like { - hs := tokenizer.hide_set_union(tok.hide_set, tokenizer.new_hide_set(m.name)); - body := tokenizer.add_hide_set(m.body, hs); + hs := tokenizer.hide_set_union(tok.hide_set, tokenizer.new_hide_set(m.name)) + body := tokenizer.add_hide_set(m.body, hs) for t := body; t.kind != .EOF; t = t.next { - t.origin = tok; + t.origin = tok } - rest^ = append_token(body, tok.next); - rest^.at_bol = tok.at_bol; - rest^.has_space = tok.has_space; - return true; + rest^ = append_token(body, tok.next) + rest^.at_bol = tok.at_bol + rest^.has_space = tok.has_space + return true } if tok.next.lit != "(" { - return false; + return false } - macro_token := tok; - args := read_macro_args(cpp, &tok, tok, m.params, m.va_args_name); - close_paren := tok; + macro_token := tok + args := read_macro_args(cpp, &tok, tok, m.params, m.va_args_name) + close_paren := tok - hs := tokenizer.hide_set_intersection(macro_token.hide_set, close_paren.hide_set); - hs = tokenizer.hide_set_union(hs, tokenizer.new_hide_set(m.name)); + hs := tokenizer.hide_set_intersection(macro_token.hide_set, close_paren.hide_set) + hs = tokenizer.hide_set_union(hs, tokenizer.new_hide_set(m.name)) - body := substitute_token(cpp, m.body, args); - body = tokenizer.add_hide_set(body, hs); + body := substitute_token(cpp, m.body, args) + body = tokenizer.add_hide_set(body, hs) for t := body; t.kind != .EOF; t = t.next { - t.origin = macro_token; + t.origin = macro_token } - rest^ = append_token(body, tok.next); - rest^.at_bol = macro_token.at_bol; - rest^.has_space = macro_token.has_space; - return true; + rest^ = append_token(body, tok.next) + rest^.at_bol = macro_token.at_bol + rest^.has_space = macro_token.has_space + return true } search_include_next :: proc(cpp: ^Preprocessor, filename: string) -> (path: string, ok: bool) { for ; cpp.include_next_index < len(cpp.include_paths); cpp.include_next_index += 1 { - tpath := filepath.join(elems={cpp.include_paths[cpp.include_next_index], filename}, allocator=context.temp_allocator); + tpath := filepath.join(elems={cpp.include_paths[cpp.include_next_index], filename}, allocator=context.temp_allocator) if os.exists(tpath) { - return strings.clone(tpath), true; + return strings.clone(tpath), true } } - return; + return } search_include_paths :: proc(cpp: ^Preprocessor, filename: string) -> (path: string, ok: bool) { if filepath.is_abs(filename) { - return filename, true; + return filename, true } if path, ok = cpp.filepath_cache[filename]; ok { - return; + return } for include_path in cpp.include_paths { - tpath := filepath.join(elems={include_path, filename}, allocator=context.temp_allocator); + tpath := filepath.join(elems={include_path, filename}, allocator=context.temp_allocator) if os.exists(tpath) { - path, ok = strings.clone(tpath), true; - cpp.filepath_cache[filename] = path; - return; + path, ok = strings.clone(tpath), true + cpp.filepath_cache[filename] = path + return } } - return; + return } read_const_expr :: proc(cpp: ^Preprocessor, rest: ^^Token, tok: ^Token) -> ^Token { - tok := tok; - tok = copy_line(rest, tok); - head: Token; - curr := &head; + tok := tok + tok = copy_line(rest, tok) + head: Token + curr := &head for tok.kind != .EOF { if tok.lit == "defined" { - start := tok; - has_paren := consume(&tok, tok.next, "("); + start := tok + has_paren := consume(&tok, tok.next, "(") if tok.kind != .Ident { - error(cpp, start, "macro name must be an identifier"); + error(cpp, start, "macro name must be an identifier") } - m := find_macro(cpp, tok); - tok = tok.next; + m := find_macro(cpp, tok) + tok = tok.next if has_paren { - tok = skip(cpp, tok, ")"); + tok = skip(cpp, tok, ")") } - curr.next = new_number_token(cpp, 1 if m != nil else 0, start); - curr = curr.next; - continue; + curr.next = new_number_token(cpp, 1 if m != nil else 0, start) + curr = curr.next + continue } - curr.next = tok; - curr = curr.next; - tok = tok.next; + curr.next = tok + curr = curr.next + tok = tok.next } - curr.next = tok; - return head.next; + curr.next = tok + return head.next } eval_const_expr :: proc(cpp: ^Preprocessor, rest: ^^Token, tok: ^Token) -> (val: i64) { - tok := tok; - start := tok; - expr := read_const_expr(cpp, rest, tok.next); - expr = preprocess_internal(cpp, expr); + tok := tok + start := tok + expr := read_const_expr(cpp, rest, tok.next) + expr = preprocess_internal(cpp, expr) if expr.kind == .EOF { - error(cpp, start, "no expression"); + error(cpp, start, "no expression") } for t := expr; t.kind != .EOF; t = t.next { if t.kind == .Ident { - next := t.next; - t^ = new_number_token(cpp, 0, t)^; - t.next = next; + next := t.next + t^ = new_number_token(cpp, 0, t)^ + t.next = next } } - val = 1; - convert_pp_tokens(cpp, expr, tokenizer.default_is_keyword); + val = 1 + convert_pp_tokens(cpp, expr, tokenizer.default_is_keyword) - rest2: ^Token; - val = const_expr(&rest2, expr); + rest2: ^Token + val = const_expr(&rest2, expr) if rest2 != nil && rest2.kind != .EOF { - error(cpp, rest2, "extra token"); + error(cpp, rest2, "extra token") } - return; + return } push_cond_incl :: proc(cpp: ^Preprocessor, tok: ^Token, included: bool) -> ^Cond_Incl { - ci := new(Cond_Incl); - ci.next = cpp.cond_incl; - ci.state = .In_Then; - ci.tok = tok; - ci.included = included; - cpp.cond_incl = ci; - return ci; + ci := new(Cond_Incl) + ci.next = cpp.cond_incl + ci.state = .In_Then + ci.tok = tok + ci.included = included + cpp.cond_incl = ci + return ci } read_line_marker:: proc(cpp: ^Preprocessor, rest: ^^Token, tok: ^Token) { - tok := tok; - start := tok; - tok = preprocess(cpp, copy_line(rest, tok)); + tok := tok + start := tok + tok = preprocess(cpp, copy_line(rest, tok)) if tok.kind != .Number { - error(cpp, tok, "invalid line marker"); + error(cpp, tok, "invalid line marker") } - ival, _ := tok.val.(i64); - start.file.line_delta = int(ival - i64(start.pos.line)); - tok = tok.next; + ival, _ := tok.val.(i64) + start.file.line_delta = int(ival - i64(start.pos.line)) + tok = tok.next if tok.kind == .EOF { - return; + return } if tok.kind != .String { - error(cpp, tok, "filename expected"); + error(cpp, tok, "filename expected") } - start.file.display_name = tok.lit; + start.file.display_name = tok.lit } preprocess_internal :: proc(cpp: ^Preprocessor, tok: ^Token) -> ^Token { - head: Token; - curr := &head; + head: Token + curr := &head - tok := tok; + tok := tok for tok != nil && tok.kind != .EOF { if expand_macro(cpp, &tok, tok) { - continue; + continue } if !is_hash(tok) { if tok.file != nil { - tok.line_delta = tok.file.line_delta; + tok.line_delta = tok.file.line_delta } - curr.next = tok; - curr = curr.next; - tok = tok.next; - continue; + curr.next = tok + curr = curr.next + tok = tok.next + continue } - start := tok; - tok = tok.next; + start := tok + tok = tok.next switch tok.lit { case "include": - filename, is_quote := read_include_filename(cpp, &tok, tok.next); - is_absolute := filepath.is_abs(filename); + filename, is_quote := read_include_filename(cpp, &tok, tok.next) + is_absolute := filepath.is_abs(filename) if is_absolute { - tok = include_file(cpp, tok, filename, start.next.next); - continue; + tok = include_file(cpp, tok, filename, start.next.next) + continue } if is_quote { - dir := ""; + dir := "" if start.file != nil { - dir = filepath.dir(start.file.name); + dir = filepath.dir(start.file.name) } - path := filepath.join(dir, filename); + path := filepath.join(dir, filename) if os.exists(path) { - tok = include_file(cpp, tok, path, start.next.next); - continue; + tok = include_file(cpp, tok, path, start.next.next) + continue } } - path, ok := search_include_paths(cpp, filename); + path, ok := search_include_paths(cpp, filename) if !ok { - path = filename; + path = filename } - tok = include_file(cpp, tok, path, start.next.next); - continue; + tok = include_file(cpp, tok, path, start.next.next) + continue case "include_next": - filename, _ := read_include_filename(cpp, &tok, tok.next); - path, ok := search_include_next(cpp, filename); + filename, _ := read_include_filename(cpp, &tok, tok.next) + path, ok := search_include_next(cpp, filename) if !ok { - path = filename; + path = filename } - tok = include_file(cpp, tok, path, start.next.next); - continue; + tok = include_file(cpp, tok, path, start.next.next) + continue case "define": - read_macro_definition(cpp, &tok, tok.next); - continue; + read_macro_definition(cpp, &tok, tok.next) + continue case "undef": - tok = tok.next; + tok = tok.next if tok.kind != .Ident { - error(cpp, tok, "macro name must be an identifier"); + error(cpp, tok, "macro name must be an identifier") } - undef_macro(cpp, tok.lit); - tok = skip_line(cpp, tok.next); - continue; + undef_macro(cpp, tok.lit) + tok = skip_line(cpp, tok.next) + continue case "if": - val := eval_const_expr(cpp, &tok, tok); - push_cond_incl(cpp, start, val != 0); + val := eval_const_expr(cpp, &tok, tok) + push_cond_incl(cpp, start, val != 0) if val == 0 { - tok = skip_cond_incl(tok); + tok = skip_cond_incl(tok) } - continue; + continue case "ifdef": - defined := find_macro(cpp, tok.next); - push_cond_incl(cpp, tok, defined != nil); - tok = skip_line(cpp, tok.next.next); + defined := find_macro(cpp, tok.next) + push_cond_incl(cpp, tok, defined != nil) + tok = skip_line(cpp, tok.next.next) if defined == nil { - tok = skip_cond_incl(tok); + tok = skip_cond_incl(tok) } - continue; + continue case "ifndef": - defined := find_macro(cpp, tok.next); - push_cond_incl(cpp, tok, defined != nil); - tok = skip_line(cpp, tok.next.next); + defined := find_macro(cpp, tok.next) + push_cond_incl(cpp, tok, defined != nil) + tok = skip_line(cpp, tok.next.next) if !(defined == nil) { - tok = skip_cond_incl(tok); + tok = skip_cond_incl(tok) } - continue; + continue case "elif": if cpp.cond_incl == nil || cpp.cond_incl.state == .In_Else { - error(cpp, start, "stray #elif"); + error(cpp, start, "stray #elif") } if cpp.cond_incl != nil { - cpp.cond_incl.state = .In_Elif; + cpp.cond_incl.state = .In_Elif } if (cpp.cond_incl != nil && !cpp.cond_incl.included) && eval_const_expr(cpp, &tok, tok) != 0 { - cpp.cond_incl.included = true; + cpp.cond_incl.included = true } else { - tok = skip_cond_incl(tok); + tok = skip_cond_incl(tok) } - continue; + continue case "else": if cpp.cond_incl == nil || cpp.cond_incl.state == .In_Else { - error(cpp, start, "stray #else"); + error(cpp, start, "stray #else") } if cpp.cond_incl != nil { - cpp.cond_incl.state = .In_Else; + cpp.cond_incl.state = .In_Else } - tok = skip_line(cpp, tok.next); + tok = skip_line(cpp, tok.next) if cpp.cond_incl != nil { - tok = skip_cond_incl(tok); + tok = skip_cond_incl(tok) } - continue; + continue case "endif": if cpp.cond_incl == nil { - error(cpp, start, "stray #endif"); + error(cpp, start, "stray #endif") } else { - cpp.cond_incl = cpp.cond_incl.next; + cpp.cond_incl = cpp.cond_incl.next } - tok = skip_line(cpp, tok.next); - continue; + tok = skip_line(cpp, tok.next) + continue case "line": - read_line_marker(cpp, &tok, tok.next); - continue; + read_line_marker(cpp, &tok, tok.next) + continue case "pragma": if tok.next.lit == "once" { - cpp.pragma_once[tok.pos.file] = true; - tok = skip_line(cpp, tok.next.next); - continue; + cpp.pragma_once[tok.pos.file] = true + tok = skip_line(cpp, tok.next.next) + continue } - pragma_tok, pragma_end := tok, tok; + pragma_tok, pragma_end := tok, tok for tok != nil && tok.kind != .EOF { - pragma_end = tok; - tok = tok.next; + pragma_end = tok + tok = tok.next if tok.at_bol { - break; + break } } - pragma_end.next = tokenizer.new_eof(tok); + pragma_end.next = tokenizer.new_eof(tok) if cpp.pragma_handler != nil { - cpp.pragma_handler(cpp, pragma_tok.next); - continue; + cpp.pragma_handler(cpp, pragma_tok.next) + continue } - continue; + continue case "error": - error(cpp, tok, "error"); + error(cpp, tok, "error") } if tok.kind == .PP_Number { - read_line_marker(cpp, &tok, tok); - continue; + read_line_marker(cpp, &tok, tok) + continue } if !tok.at_bol { - error(cpp, tok, "invalid preprocessor directive"); + error(cpp, tok, "invalid preprocessor directive") } } - curr.next = tok; - return head.next; + curr.next = tok + return head.next } preprocess :: proc(cpp: ^Preprocessor, tok: ^Token) -> ^Token { - tok := tok; - tok = preprocess_internal(cpp, tok); + tok := tok + tok = preprocess_internal(cpp, tok) if cpp.cond_incl != nil { - error(cpp, tok, "unterminated conditional directive"); + error(cpp, tok, "unterminated conditional directive") } - convert_pp_tokens(cpp, tok, tokenizer.default_is_keyword); - join_adjacent_string_literals(cpp, tok); + convert_pp_tokens(cpp, tok, tokenizer.default_is_keyword) + join_adjacent_string_literals(cpp, tok) for t := tok; t != nil; t = t.next { - t.pos.line += t.line_delta; + t.pos.line += t.line_delta } - return tok; + return tok } define_macro :: proc(cpp: ^Preprocessor, name, def: string) { - src := transmute([]byte)def; + src := transmute([]byte)def - file := new(tokenizer.File); - file.id = -1; - file.src = src; - file.name = "<built-in>"; - file.display_name = file.name; + file := new(tokenizer.File) + file.id = -1 + file.src = src + file.name = "<built-in>" + file.display_name = file.name - t := _init_tokenizer_from_preprocessor(&Tokenizer{}, cpp); - tok := tokenizer.tokenize(t, file); - add_macro(cpp, name, .Value_Like, tok); + t := _init_tokenizer_from_preprocessor(&Tokenizer{}, cpp) + tok := tokenizer.tokenize(t, file) + add_macro(cpp, name, .Value_Like, tok) } file_macro :: proc(cpp: ^Preprocessor, tok: ^Token) -> ^Token { - tok := tok; + tok := tok for tok.origin != nil { - tok = tok.origin; + tok = tok.origin } - i := i64(tok.pos.line + tok.file.line_delta); - return new_number_token(cpp, i, tok); + i := i64(tok.pos.line + tok.file.line_delta) + return new_number_token(cpp, i, tok) } line_macro :: proc(cpp: ^Preprocessor, tok: ^Token) -> ^Token { - tok := tok; + tok := tok for tok.origin != nil { - tok = tok.origin; + tok = tok.origin } - return new_string_token(cpp, tok.file.display_name, tok); + return new_string_token(cpp, tok.file.display_name, tok) } counter_macro :: proc(cpp: ^Preprocessor, tok: ^Token) -> ^Token { - i := cpp.counter; - cpp.counter += 1; - return new_number_token(cpp, i, tok); + i := cpp.counter + cpp.counter += 1 + return new_number_token(cpp, i, tok) } init_default_macros :: proc(cpp: ^Preprocessor) { - define_macro(cpp, "__C99_MACRO_WITH_VA_ARGS", "1"); - define_macro(cpp, "__alignof__", "_Alignof"); - define_macro(cpp, "__const__", "const"); - define_macro(cpp, "__inline__", "inline"); - define_macro(cpp, "__signed__", "signed"); - define_macro(cpp, "__typeof__", "typeof"); - define_macro(cpp, "__volatile__", "volatile"); - - add_builtin(cpp, "__FILE__", file_macro); - add_builtin(cpp, "__LINE__", line_macro); - add_builtin(cpp, "__COUNTER__", counter_macro); + define_macro(cpp, "__C99_MACRO_WITH_VA_ARGS", "1") + define_macro(cpp, "__alignof__", "_Alignof") + define_macro(cpp, "__const__", "const") + define_macro(cpp, "__inline__", "inline") + define_macro(cpp, "__signed__", "signed") + define_macro(cpp, "__typeof__", "typeof") + define_macro(cpp, "__volatile__", "volatile") + + add_builtin(cpp, "__FILE__", file_macro) + add_builtin(cpp, "__LINE__", line_macro) + add_builtin(cpp, "__COUNTER__", counter_macro) } init_lookup_tables :: proc(cpp: ^Preprocessor, allocator := context.allocator) { - context.allocator = allocator; - reserve(&cpp.macros, max(16, cap(cpp.macros))); - reserve(&cpp.pragma_once, max(16, cap(cpp.pragma_once))); - reserve(&cpp.include_guards, max(16, cap(cpp.include_guards))); - reserve(&cpp.filepath_cache, max(16, cap(cpp.filepath_cache))); + context.allocator = allocator + reserve(&cpp.macros, max(16, cap(cpp.macros))) + reserve(&cpp.pragma_once, max(16, cap(cpp.pragma_once))) + reserve(&cpp.include_guards, max(16, cap(cpp.include_guards))) + reserve(&cpp.filepath_cache, max(16, cap(cpp.filepath_cache))) } init_defaults :: proc(cpp: ^Preprocessor, lookup_tables_allocator := context.allocator) { if cpp.warn == nil { - cpp.warn = tokenizer.default_warn_handler; + cpp.warn = tokenizer.default_warn_handler } if cpp.err == nil { - cpp.err = tokenizer.default_error_handler; + cpp.err = tokenizer.default_error_handler } - init_lookup_tables(cpp, lookup_tables_allocator); - init_default_macros(cpp); + init_lookup_tables(cpp, lookup_tables_allocator) + init_default_macros(cpp) } diff --git a/core/c/frontend/preprocessor/unquote.odin b/core/c/frontend/preprocessor/unquote.odin index a72a3601c..5869fa7ef 100644 --- a/core/c/frontend/preprocessor/unquote.odin +++ b/core/c/frontend/preprocessor/unquote.odin @@ -5,150 +5,150 @@ import "core:unicode/utf8" unquote_char :: proc(str: string, quote: byte) -> (r: rune, multiple_bytes: bool, tail_string: string, success: bool) { hex_to_int :: proc(c: byte) -> int { switch c { - case '0'..='9': return int(c-'0'); - case 'a'..='f': return int(c-'a')+10; - case 'A'..='F': return int(c-'A')+10; + case '0'..='9': return int(c-'0') + case 'a'..='f': return int(c-'a')+10 + case 'A'..='F': return int(c-'A')+10 } - return -1; + return -1 } - w: int; + w: int if str[0] == quote && quote == '"' { - return; + return } else if str[0] >= 0x80 { - r, w = utf8.decode_rune_in_string(str); - return r, true, str[w:], true; + r, w = utf8.decode_rune_in_string(str) + return r, true, str[w:], true } else if str[0] != '\\' { - return rune(str[0]), false, str[1:], true; + return rune(str[0]), false, str[1:], true } if len(str) <= 1 { - return; + return } - s := str; - c := s[1]; - s = s[2:]; + s := str + c := s[1] + s = s[2:] switch c { - case: r = rune(c); + case: r = rune(c) - case 'a': r = '\a'; - case 'b': r = '\b'; - case 'e': r = '\e'; - case 'f': r = '\f'; - case 'n': r = '\n'; - case 'r': r = '\r'; - case 't': r = '\t'; - case 'v': r = '\v'; - case '\\': r = '\\'; + case 'a': r = '\a' + case 'b': r = '\b' + case 'e': r = '\e' + case 'f': r = '\f' + case 'n': r = '\n' + case 'r': r = '\r' + case 't': r = '\t' + case 'v': r = '\v' + case '\\': r = '\\' - case '"': r = '"'; - case '\'': r = '\''; + case '"': r = '"' + case '\'': r = '\'' case '0'..='7': - v := int(c-'0'); + v := int(c-'0') if len(s) < 2 { - return; + return } for i in 0..<len(s) { - d := int(s[i]-'0'); + d := int(s[i]-'0') if d < 0 || d > 7 { - return; + return } - v = (v<<3) | d; + v = (v<<3) | d } - s = s[2:]; + s = s[2:] if v > 0xff { - return; + return } - r = rune(v); + r = rune(v) case 'x', 'u', 'U': - count: int; + count: int switch c { - case 'x': count = 2; - case 'u': count = 4; - case 'U': count = 8; + case 'x': count = 2 + case 'u': count = 4 + case 'U': count = 8 } if len(s) < count { - return; + return } for i in 0..<count { - d := hex_to_int(s[i]); + d := hex_to_int(s[i]) if d < 0 { - return; + return } - r = (r<<4) | rune(d); + r = (r<<4) | rune(d) } - s = s[count:]; + s = s[count:] if c == 'x' { - break; + break } if r > utf8.MAX_RUNE { - return; + return } - multiple_bytes = true; + multiple_bytes = true } - success = true; - tail_string = s; - return; + success = true + tail_string = s + return } unquote_string :: proc(lit: string, allocator := context.allocator) -> (res: string, allocated, success: bool) { contains_rune :: proc(s: string, r: rune) -> int { for c, offset in s { if c == r { - return offset; + return offset } } - return -1; + return -1 } - assert(len(lit) >= 2); + assert(len(lit) >= 2) - s := lit; - quote := '"'; + s := lit + quote := '"' if s == `""` { - return "", false, true; + return "", false, true } if contains_rune(s, '\n') >= 0 { - return s, false, false; + return s, false, false } if contains_rune(s, '\\') < 0 && contains_rune(s, quote) < 0 { if quote == '"' { - return s, false, true; + return s, false, true } } - s = s[1:len(s)-1]; + s = s[1:len(s)-1] - buf_len := 3*len(s) / 2; - buf := make([]byte, buf_len, allocator); - offset := 0; + buf_len := 3*len(s) / 2 + buf := make([]byte, buf_len, allocator) + offset := 0 for len(s) > 0 { - r, multiple_bytes, tail_string, ok := unquote_char(s, byte(quote)); + r, multiple_bytes, tail_string, ok := unquote_char(s, byte(quote)) if !ok { - delete(buf); - return s, false, false; + delete(buf) + return s, false, false } - s = tail_string; + s = tail_string if r < 0x80 || !multiple_bytes { - buf[offset] = byte(r); - offset += 1; + buf[offset] = byte(r) + offset += 1 } else { - b, w := utf8.encode_rune(r); - copy(buf[offset:], b[:w]); - offset += w; + b, w := utf8.encode_rune(r) + copy(buf[offset:], b[:w]) + offset += w } } - new_string := string(buf[:offset]); + new_string := string(buf[:offset]) - return new_string, true, true; + return new_string, true, true } diff --git a/core/c/frontend/tokenizer/hide_set.odin b/core/c/frontend/tokenizer/hide_set.odin index 9cf3b4aea..ec8b77e6e 100644 --- a/core/c/frontend/tokenizer/hide_set.odin +++ b/core/c/frontend/tokenizer/hide_set.odin @@ -11,58 +11,58 @@ Hide_Set :: struct { new_hide_set :: proc(name: string) -> ^Hide_Set { - hs := new(Hide_Set); - hs.name = name; - return hs; + hs := new(Hide_Set) + hs.name = name + return hs } hide_set_contains :: proc(hs: ^Hide_Set, name: string) -> bool { for h := hs; h != nil; h = h.next { if h.name == name { - return true; + return true } } - return false; + return false } hide_set_union :: proc(a, b: ^Hide_Set) -> ^Hide_Set { - head: Hide_Set; - curr := &head; + head: Hide_Set + curr := &head for h := a; h != nil; h = h.next { - curr.next = new_hide_set(h.name); - curr = curr.next; + curr.next = new_hide_set(h.name) + curr = curr.next } - curr.next = b; - return head.next; + curr.next = b + return head.next } hide_set_intersection :: proc(a, b: ^Hide_Set) -> ^Hide_Set { - head: Hide_Set; - curr := &head; + head: Hide_Set + curr := &head for h := a; h != nil; h = h.next { if hide_set_contains(b, h.name) { - curr.next = new_hide_set(h.name); - curr = curr.next; + curr.next = new_hide_set(h.name) + curr = curr.next } } - return head.next; + return head.next } add_hide_set :: proc(tok: ^Token, hs: ^Hide_Set) -> ^Token { - head: Token; - curr := &head; + head: Token + curr := &head - tok := tok; + tok := tok for ; tok != nil; tok = tok.next { - t := copy_token(tok); - t.hide_set = hide_set_union(t.hide_set, hs); - curr.next = t; - curr = curr.next; + t := copy_token(tok) + t.hide_set = hide_set_union(t.hide_set, hs) + curr.next = t + curr = curr.next } - return head.next; + return head.next } diff --git a/core/c/frontend/tokenizer/token.odin b/core/c/frontend/tokenizer/token.odin index a85468e6a..c4760ea42 100644 --- a/core/c/frontend/tokenizer/token.odin +++ b/core/c/frontend/tokenizer/token.odin @@ -80,29 +80,29 @@ Token :: struct { origin: ^Token, } -Is_Keyword_Proc :: #type proc(tok: ^Token) -> bool; +Is_Keyword_Proc :: #type proc(tok: ^Token) -> bool copy_token :: proc(tok: ^Token) -> ^Token { - t := new_clone(tok^); - t.next = nil; - return t; + t := new_clone(tok^) + t.next = nil + return t } new_eof :: proc(tok: ^Token) -> ^Token { - t := new_clone(tok^); - t.kind = .EOF; - t.lit = ""; - return t; + t := new_clone(tok^) + t.kind = .EOF + t.lit = "" + return t } default_is_keyword :: proc(tok: ^Token) -> bool { if tok.kind == .Keyword { - return true; + return true } if len(tok.lit) > 0 { - return default_keyword_set[tok.lit]; + return default_keyword_set[tok.lit] } - return false; + return false } @@ -117,7 +117,7 @@ token_name := [Token_Kind]string { .PP_Number = "preprocessor number", .Comment = "comment", .EOF = "eof", -}; +} default_keyword_set := map[string]bool{ "auto" = true, @@ -166,4 +166,4 @@ default_keyword_set := map[string]bool{ "__restrict__" = true, "__thread" = true, "__attribute__" = true, -}; +} diff --git a/core/c/frontend/tokenizer/tokenizer.odin b/core/c/frontend/tokenizer/tokenizer.odin index 8a3747434..52ad42031 100644 --- a/core/c/frontend/tokenizer/tokenizer.odin +++ b/core/c/frontend/tokenizer/tokenizer.odin @@ -6,7 +6,7 @@ import "core:strings" import "core:unicode/utf8" -Error_Handler :: #type proc(pos: Pos, fmt: string, args: ..any); +Error_Handler :: #type proc(pos: Pos, fmt: string, args: ..any) Tokenizer :: struct { @@ -34,415 +34,415 @@ Tokenizer :: struct { } init_defaults :: proc(t: ^Tokenizer, err: Error_Handler = default_error_handler, warn: Error_Handler = default_warn_handler) { - t.err = err; - t.warn = warn; + t.err = err + t.warn = warn } @(private) offset_to_pos :: proc(t: ^Tokenizer, offset: int) -> (pos: Pos) { - pos.file = t.path; - pos.offset = offset; - pos.line = t.line_count; - pos.column = offset - t.line_offset + 1; - return; + pos.file = t.path + pos.offset = offset + pos.line = t.line_count + pos.column = offset - t.line_offset + 1 + return } default_error_handler :: proc(pos: Pos, msg: string, args: ..any) { - fmt.eprintf("%s(%d:%d) ", pos.file, pos.line, pos.column); - fmt.eprintf(msg, ..args); - fmt.eprintf("\n"); + fmt.eprintf("%s(%d:%d) ", pos.file, pos.line, pos.column) + fmt.eprintf(msg, ..args) + fmt.eprintf("\n") } default_warn_handler :: proc(pos: Pos, msg: string, args: ..any) { - fmt.eprintf("%s(%d:%d) warning: ", pos.file, pos.line, pos.column); - fmt.eprintf(msg, ..args); - fmt.eprintf("\n"); + fmt.eprintf("%s(%d:%d) warning: ", pos.file, pos.line, pos.column) + fmt.eprintf(msg, ..args) + fmt.eprintf("\n") } error_offset :: proc(t: ^Tokenizer, offset: int, msg: string, args: ..any) { - pos := offset_to_pos(t, offset); + pos := offset_to_pos(t, offset) if t.err != nil { - t.err(pos, msg, ..args); + t.err(pos, msg, ..args) } - t.error_count += 1; + t.error_count += 1 } warn_offset :: proc(t: ^Tokenizer, offset: int, msg: string, args: ..any) { - pos := offset_to_pos(t, offset); + pos := offset_to_pos(t, offset) if t.warn != nil { - t.warn(pos, msg, ..args); + t.warn(pos, msg, ..args) } - t.warning_count += 1; + t.warning_count += 1 } error :: proc(t: ^Tokenizer, tok: ^Token, msg: string, args: ..any) { - pos := tok.pos; + pos := tok.pos if t.err != nil { - t.err(pos, msg, ..args); + t.err(pos, msg, ..args) } - t.error_count += 1; + t.error_count += 1 } warn :: proc(t: ^Tokenizer, tok: ^Token, msg: string, args: ..any) { - pos := tok.pos; + pos := tok.pos if t.warn != nil { - t.warn(pos, msg, ..args); + t.warn(pos, msg, ..args) } - t.warning_count += 1; + t.warning_count += 1 } advance_rune :: proc(t: ^Tokenizer) { if t.read_offset < len(t.src) { - t.offset = t.read_offset; + t.offset = t.read_offset if t.ch == '\n' { - t.at_bol = true; - t.line_offset = t.offset; - t.line_count += 1; + t.at_bol = true + t.line_offset = t.offset + t.line_count += 1 } - r, w := rune(t.src[t.read_offset]), 1; + r, w := rune(t.src[t.read_offset]), 1 switch { case r == 0: - error_offset(t, t.offset, "illegal character NUL"); + error_offset(t, t.offset, "illegal character NUL") case r >= utf8.RUNE_SELF: - r, w = utf8.decode_rune(t.src[t.read_offset:]); + r, w = utf8.decode_rune(t.src[t.read_offset:]) if r == utf8.RUNE_ERROR && w == 1 { - error_offset(t, t.offset, "illegal UTF-8 encoding"); + error_offset(t, t.offset, "illegal UTF-8 encoding") } else if r == utf8.RUNE_BOM && t.offset > 0 { - error_offset(t, t.offset, "illegal byte order mark"); + error_offset(t, t.offset, "illegal byte order mark") } } - t.read_offset += w; - t.ch = r; + t.read_offset += w + t.ch = r } else { - t.offset = len(t.src); + t.offset = len(t.src) if t.ch == '\n' { - t.at_bol = true; - t.line_offset = t.offset; - t.line_count += 1; + t.at_bol = true + t.line_offset = t.offset + t.line_count += 1 } - t.ch = -1; + t.ch = -1 } } advance_rune_n :: proc(t: ^Tokenizer, n: int) { for in 0..<n { - advance_rune(t); + advance_rune(t) } } is_digit :: proc(r: rune) -> bool { - return '0' <= r && r <= '9'; + return '0' <= r && r <= '9' } skip_whitespace :: proc(t: ^Tokenizer) { for { switch t.ch { case ' ', '\t', '\r', '\v', '\f', '\n': - t.has_space = true; - advance_rune(t); + t.has_space = true + advance_rune(t) case: - return; + return } } } scan_comment :: proc(t: ^Tokenizer) -> string { - offset := t.offset-1; - next := -1; + offset := t.offset-1 + next := -1 general: { if t.ch == '/'{ // line comments - advance_rune(t); + advance_rune(t) for t.ch != '\n' && t.ch >= 0 { - advance_rune(t); + advance_rune(t) } - next = t.offset; + next = t.offset if t.ch == '\n' { - next += 1; + next += 1 } - break general; + break general } /* style comment */ - advance_rune(t); + advance_rune(t) for t.ch >= 0 { - ch := t.ch; - advance_rune(t); + ch := t.ch + advance_rune(t) if ch == '*' && t.ch == '/' { - advance_rune(t); - next = t.offset; - break general; + advance_rune(t) + next = t.offset + break general } } - error_offset(t, offset, "comment not terminated"); + error_offset(t, offset, "comment not terminated") } - lit := t.src[offset : t.offset]; + lit := t.src[offset : t.offset] // NOTE(bill): Strip CR for line comments for len(lit) > 2 && lit[1] == '/' && lit[len(lit)-1] == '\r' { - lit = lit[:len(lit)-1]; + lit = lit[:len(lit)-1] } - return string(lit); + return string(lit) } scan_identifier :: proc(t: ^Tokenizer) -> string { - offset := t.offset; + offset := t.offset for is_ident1(t.ch) { - advance_rune(t); + advance_rune(t) } - return string(t.src[offset : t.offset]); + return string(t.src[offset : t.offset]) } scan_string :: proc(t: ^Tokenizer) -> string { - offset := t.offset-1; + offset := t.offset-1 for { - ch := t.ch; + ch := t.ch if ch == '\n' || ch < 0 { - error_offset(t, offset, "string literal was not terminated"); - break; + error_offset(t, offset, "string literal was not terminated") + break } - advance_rune(t); + advance_rune(t) if ch == '"' { - break; + break } if ch == '\\' { - scan_escape(t); + scan_escape(t) } } - return string(t.src[offset : t.offset]); + return string(t.src[offset : t.offset]) } digit_val :: proc(r: rune) -> int { switch r { case '0'..='9': - return int(r-'0'); + return int(r-'0') case 'A'..='F': - return int(r-'A' + 10); + return int(r-'A' + 10) case 'a'..='f': - return int(r-'a' + 10); + return int(r-'a' + 10) } - return 16; + return 16 } scan_escape :: proc(t: ^Tokenizer) -> bool { - offset := t.offset; + offset := t.offset - esc := t.ch; - n: int; - base, max: u32; + esc := t.ch + n: int + base, max: u32 switch esc { case 'a', 'b', 'e', 'f', 'n', 't', 'v', 'r', '\\', '\'', '"': - advance_rune(t); - return true; + advance_rune(t) + return true case '0'..='7': for digit_val(t.ch) < 8 { - advance_rune(t); + advance_rune(t) } - return true; + return true case 'x': - advance_rune(t); + advance_rune(t) for digit_val(t.ch) < 16 { - advance_rune(t); + advance_rune(t) } - return true; + return true case 'u': - advance_rune(t); - n, base, max = 4, 16, utf8.MAX_RUNE; + advance_rune(t) + n, base, max = 4, 16, utf8.MAX_RUNE case 'U': - advance_rune(t); - n, base, max = 8, 16, utf8.MAX_RUNE; + advance_rune(t) + n, base, max = 8, 16, utf8.MAX_RUNE case: if t.ch < 0 { - error_offset(t, offset, "escape sequence was not terminated"); + error_offset(t, offset, "escape sequence was not terminated") } else { - break; + break } - return false; + return false } - x: u32; + x: u32 main_loop: for n > 0 { - d := u32(digit_val(t.ch)); + d := u32(digit_val(t.ch)) if d >= base { if t.ch == '"' || t.ch == '\'' { - break main_loop; + break main_loop } if t.ch < 0 { - error_offset(t, t.offset, "escape sequence was not terminated"); + error_offset(t, t.offset, "escape sequence was not terminated") } else { - error_offset(t, t.offset, "illegal character '%r' : %d in escape sequence", t.ch, t.ch); + error_offset(t, t.offset, "illegal character '%r' : %d in escape sequence", t.ch, t.ch) } - return false; + return false } - x = x*base + d; - advance_rune(t); - n -= 1; + x = x*base + d + advance_rune(t) + n -= 1 } if x > max || 0xd800 <= x && x <= 0xe000 { - error_offset(t, offset, "escape sequence is an invalid Unicode code point"); - return false; + error_offset(t, offset, "escape sequence is an invalid Unicode code point") + return false } - return true; + return true } scan_rune :: proc(t: ^Tokenizer) -> string { - offset := t.offset-1; - valid := true; - n := 0; + offset := t.offset-1 + valid := true + n := 0 for { - ch := t.ch; + ch := t.ch if ch == '\n' || ch < 0 { if valid { - error_offset(t, offset, "rune literal not terminated"); - valid = false; + error_offset(t, offset, "rune literal not terminated") + valid = false } - break; + break } - advance_rune(t); + advance_rune(t) if ch == '\'' { - break; + break } - n += 1; + n += 1 if ch == '\\' { if !scan_escape(t) { - valid = false; + valid = false } } } if valid && n != 1 { - error_offset(t, offset, "illegal rune literal"); + error_offset(t, offset, "illegal rune literal") } - return string(t.src[offset : t.offset]); + return string(t.src[offset : t.offset]) } scan_number :: proc(t: ^Tokenizer, seen_decimal_point: bool) -> (Token_Kind, string) { scan_mantissa :: proc(t: ^Tokenizer, base: int) { for digit_val(t.ch) < base { - advance_rune(t); + advance_rune(t) } } scan_exponent :: proc(t: ^Tokenizer) { if t.ch == 'e' || t.ch == 'E' || t.ch == 'p' || t.ch == 'P' { - advance_rune(t); + advance_rune(t) if t.ch == '-' || t.ch == '+' { - advance_rune(t); + advance_rune(t) } if digit_val(t.ch) < 10 { - scan_mantissa(t, 10); + scan_mantissa(t, 10) } else { - error_offset(t, t.offset, "illegal floating-point exponent"); + error_offset(t, t.offset, "illegal floating-point exponent") } } } scan_fraction :: proc(t: ^Tokenizer) -> (early_exit: bool) { if t.ch == '.' && peek(t) == '.' { - return true; + return true } if t.ch == '.' { - advance_rune(t); - scan_mantissa(t, 10); + advance_rune(t) + scan_mantissa(t, 10) } - return false; + return false } - check_end := true; + check_end := true - offset := t.offset; - seen_point := seen_decimal_point; + offset := t.offset + seen_point := seen_decimal_point if seen_point { - offset -= 1; - scan_mantissa(t, 10); - scan_exponent(t); + offset -= 1 + scan_mantissa(t, 10) + scan_exponent(t) } else { if t.ch == '0' { int_base :: proc(t: ^Tokenizer, base: int, msg: string) { - prev := t.offset; - advance_rune(t); - scan_mantissa(t, base); + prev := t.offset + advance_rune(t) + scan_mantissa(t, base) if t.offset - prev <= 1 { - error_offset(t, t.offset, msg); + error_offset(t, t.offset, msg) } } - advance_rune(t); + advance_rune(t) switch t.ch { case 'b', 'B': - int_base(t, 2, "illegal binary integer"); + int_base(t, 2, "illegal binary integer") case 'x', 'X': - int_base(t, 16, "illegal hexadecimal integer"); + int_base(t, 16, "illegal hexadecimal integer") case: - seen_point = false; - scan_mantissa(t, 10); + seen_point = false + scan_mantissa(t, 10) if t.ch == '.' { - seen_point = true; + seen_point = true if scan_fraction(t) { - check_end = false; + check_end = false } } if check_end { - scan_exponent(t); - check_end = false; + scan_exponent(t) + check_end = false } } } } if check_end { - scan_mantissa(t, 10); + scan_mantissa(t, 10) if !scan_fraction(t) { - scan_exponent(t); + scan_exponent(t) } } - return .Number, string(t.src[offset : t.offset]); + return .Number, string(t.src[offset : t.offset]) } scan_punct :: proc(t: ^Tokenizer, ch: rune) -> (kind: Token_Kind) { - kind = .Punct; + kind = .Punct switch ch { case: - kind = .Invalid; + kind = .Invalid case '<', '>': if t.ch == ch { - advance_rune(t); + advance_rune(t) } if t.ch == '=' { - advance_rune(t); + advance_rune(t) } case '!', '+', '-', '*', '/', '%', '^', '=': if t.ch == '=' { - advance_rune(t); + advance_rune(t) } case '#': if t.ch == '#' { - advance_rune(t); + advance_rune(t) } case '&': if t.ch == '=' || t.ch == '&' { - advance_rune(t); + advance_rune(t) } case '|': if t.ch == '=' || t.ch == '|' { - advance_rune(t); + advance_rune(t) } case '(', ')', '[', ']', '{', '}': // okay @@ -452,216 +452,216 @@ scan_punct :: proc(t: ^Tokenizer, ch: rune) -> (kind: Token_Kind) { // okay case '.': if t.ch == '.' && peek(t) == '.' { - advance_rune(t); - advance_rune(t); // consume last '.' + advance_rune(t) + advance_rune(t) // consume last '.' } } - return; + return } peek :: proc(t: ^Tokenizer) -> byte { if t.read_offset < len(t.src) { - return t.src[t.read_offset]; + return t.src[t.read_offset] } - return 0; + return 0 } peek_str :: proc(t: ^Tokenizer, str: string) -> bool { if t.read_offset < len(t.src) { - return strings.has_prefix(string(t.src[t.offset:]), str); + return strings.has_prefix(string(t.src[t.offset:]), str) } - return false; + return false } scan_literal_prefix :: proc(t: ^Tokenizer, str: string, prefix: ^string) -> bool { if peek_str(t, str) { - offset := t.offset; + offset := t.offset for _ in str { - advance_rune(t); + advance_rune(t) } - prefix^ = string(t.src[offset:][:len(str)-1]); - return true; + prefix^ = string(t.src[offset:][:len(str)-1]) + return true } - return false; + return false } allow_next_to_be_newline :: proc(t: ^Tokenizer) -> bool { if t.ch == '\n' { - advance_rune(t); - return true; + advance_rune(t) + return true } else if t.ch == '\r' && peek(t) == '\n' { // allow for MS-DOS style line endings - advance_rune(t); // \r - advance_rune(t); // \n - return true; + advance_rune(t) // \r + advance_rune(t) // \n + return true } - return false; + return false } scan :: proc(t: ^Tokenizer, f: ^File) -> ^Token { - skip_whitespace(t); + skip_whitespace(t) - offset := t.offset; + offset := t.offset - kind: Token_Kind; - lit: string; - prefix: string; + kind: Token_Kind + lit: string + prefix: string switch ch := t.ch; { case scan_literal_prefix(t, `u8"`, &prefix): - kind = .String; - lit = scan_string(t); + kind = .String + lit = scan_string(t) case scan_literal_prefix(t, `u"`, &prefix): - kind = .String; - lit = scan_string(t); + kind = .String + lit = scan_string(t) case scan_literal_prefix(t, `L"`, &prefix): - kind = .String; - lit = scan_string(t); + kind = .String + lit = scan_string(t) case scan_literal_prefix(t, `U"`, &prefix): - kind = .String; - lit = scan_string(t); + kind = .String + lit = scan_string(t) case scan_literal_prefix(t, `u'`, &prefix): - kind = .Char; - lit = scan_rune(t); + kind = .Char + lit = scan_rune(t) case scan_literal_prefix(t, `L'`, &prefix): - kind = .Char; - lit = scan_rune(t); + kind = .Char + lit = scan_rune(t) case scan_literal_prefix(t, `U'`, &prefix): - kind = .Char; - lit = scan_rune(t); + kind = .Char + lit = scan_rune(t) case is_ident0(ch): - lit = scan_identifier(t); - kind = .Ident; + lit = scan_identifier(t) + kind = .Ident case '0' <= ch && ch <= '9': - kind, lit = scan_number(t, false); + kind, lit = scan_number(t, false) case: - advance_rune(t); + advance_rune(t) switch ch { case -1: - kind = .EOF; + kind = .EOF case '\\': - kind = .Punct; + kind = .Punct if allow_next_to_be_newline(t) { - t.at_bol = true; - t.has_space = false; - return scan(t, f); + t.at_bol = true + t.has_space = false + return scan(t, f) } case '.': if is_digit(t.ch) { - kind, lit = scan_number(t, true); + kind, lit = scan_number(t, true) } else { - kind = scan_punct(t, ch); + kind = scan_punct(t, ch) } case '"': - kind = .String; - lit = scan_string(t); + kind = .String + lit = scan_string(t) case '\'': - kind = .Char; - lit = scan_rune(t); + kind = .Char + lit = scan_rune(t) case '/': if t.ch == '/' || t.ch == '*' { - kind = .Comment; - lit = scan_comment(t); - t.has_space = true; - break; + kind = .Comment + lit = scan_comment(t) + t.has_space = true + break } - fallthrough; + fallthrough case: - kind = scan_punct(t, ch); + kind = scan_punct(t, ch) if kind == .Invalid && ch != utf8.RUNE_BOM { - error_offset(t, t.offset, "illegal character '%r': %d", ch, ch); + error_offset(t, t.offset, "illegal character '%r': %d", ch, ch) } } } if lit == "" { - lit = string(t.src[offset : t.offset]); + lit = string(t.src[offset : t.offset]) } if kind == .Comment { - return scan(t, f); + return scan(t, f) } - tok := new(Token); - tok.kind = kind; - tok.lit = lit; - tok.pos = offset_to_pos(t, offset); - tok.file = f; - tok.prefix = prefix; - tok.at_bol = t.at_bol; - tok.has_space = t.has_space; + tok := new(Token) + tok.kind = kind + tok.lit = lit + tok.pos = offset_to_pos(t, offset) + tok.file = f + tok.prefix = prefix + tok.at_bol = t.at_bol + tok.has_space = t.has_space - t.at_bol, t.has_space = false, false; + t.at_bol, t.has_space = false, false - return tok; + return tok } tokenize :: proc(t: ^Tokenizer, f: ^File) -> ^Token { setup_tokenizer: { - t.src = f.src; - t.ch = ' '; - t.offset = 0; - t.read_offset = 0; - t.line_offset = 0; - t.line_count = len(t.src) > 0 ? 1 : 0; - t.error_count = 0; - t.path = f.name; + t.src = f.src + t.ch = ' ' + t.offset = 0 + t.read_offset = 0 + t.line_offset = 0 + t.line_count = len(t.src) > 0 ? 1 : 0 + t.error_count = 0 + t.path = f.name - advance_rune(t); + advance_rune(t) if t.ch == utf8.RUNE_BOM { - advance_rune(t); + advance_rune(t) } } - t.at_bol = true; - t.has_space = false; + t.at_bol = true + t.has_space = false - head: Token; - curr := &head; + head: Token + curr := &head for { - tok := scan(t, f); + tok := scan(t, f) if tok == nil { - break; + break } - curr.next = tok; - curr = curr.next; + curr.next = tok + curr = curr.next if tok.kind == .EOF { - break; + break } } - return head.next; + return head.next } add_new_file :: proc(t: ^Tokenizer, name: string, src: []byte, id: int) -> ^File { - file := new(File); - file.id = id; - file.src = src; - file.name = name; - file.display_name = name; - return file; + file := new(File) + file.id = id + file.src = src + file.name = name + file.display_name = name + return file } tokenize_file :: proc(t: ^Tokenizer, path: string, id: int, loc := #caller_location) -> ^Token { - src, ok := os.read_entire_file(path); + src, ok := os.read_entire_file(path) if !ok { - return nil; + return nil } - return tokenize(t, add_new_file(t, path, src, id)); + return tokenize(t, add_new_file(t, path, src, id)) } inline_tokenize :: proc(t: ^Tokenizer, tok: ^Token, src: []byte) -> ^Token { - file := new(File); - file.src = src; + file := new(File) + file.src = src if tok.file != nil { - file.id = tok.file.id; - file.name = tok.file.name; - file.display_name = tok.file.name; + file.id = tok.file.id + file.name = tok.file.name + file.display_name = tok.file.name } - return tokenize(t, file); + return tokenize(t, file) } diff --git a/core/c/frontend/tokenizer/unicode.odin b/core/c/frontend/tokenizer/unicode.odin index 41c48eb73..317ee160e 100644 --- a/core/c/frontend/tokenizer/unicode.odin +++ b/core/c/frontend/tokenizer/unicode.odin @@ -4,10 +4,10 @@ package c_frontend_tokenizer in_range :: proc(range: []rune, c: rune) -> bool #no_bounds_check { for i := 0; range[i] != -1; i += 2 { if range[i] <= c && c <= range[i+1] { - return true; + return true } } - return false; + return false } @@ -15,11 +15,11 @@ in_range :: proc(range: []rune, c: rune) -> bool #no_bounds_check { // // is_ident0 returns true if a given character is acceptable as the first character of an identifier. is_ident0 :: proc(c: rune) -> bool { - return in_range(_range_ident0, c); + return in_range(_range_ident0, c) } // is_ident0 returns true if a given character is acceptable as a non-first character of an identifier. is_ident1 :: proc(c: rune) -> bool { - return is_ident0(c) || in_range(_range_ident1, c); + return is_ident0(c) || in_range(_range_ident1, c) } // Returns the number of columns needed to display a given character in a fixed-width font. @@ -27,18 +27,18 @@ is_ident1 :: proc(c: rune) -> bool { char_width :: proc(c: rune) -> int { switch { case in_range(_range_width0, c): - return 0; + return 0 case in_range(_range_width2, c): - return 2; + return 2 } - return 1; + return 1 } display_width :: proc(str: string) -> (w: int) { for c in str { - w += char_width(c); + w += char_width(c) } - return; + return } @@ -59,12 +59,12 @@ _range_ident0 := []rune{ 0x90000, 0x9FFFD, 0xA0000, 0xAFFFD, 0xB0000, 0xBFFFD, 0xC0000, 0xCFFFD, 0xD0000, 0xDFFFD, 0xE0000, 0xEFFFD, -1, -}; +} _range_ident1 := []rune{ '0', '9', '$', '$', 0x0300, 0x036F, 0x1DC0, 0x1DFF, 0x20D0, 0x20FF, 0xFE20, 0xFE2F, -1, -}; +} _range_width0 := []rune{ @@ -105,7 +105,7 @@ _range_width0 := []rune{ 0x1D167, 0x1D169, 0x1D173, 0x1D182, 0x1D185, 0x1D18B, 0x1D1AA, 0x1D1AD, 0x1D242, 0x1D244, 0xE0001, 0xE0001, 0xE0020, 0xE007F, 0xE0100, 0xE01EF, -1, -}; +} _range_width2 := []rune{ 0x1100, 0x115F, 0x2329, 0x2329, 0x232A, 0x232A, 0x2E80, 0x303E, @@ -113,4 +113,4 @@ _range_width2 := []rune{ 0xFE30, 0xFE6F, 0xFF00, 0xFF60, 0xFFE0, 0xFFE6, 0x1F000, 0x1F644, 0x20000, 0x2FFFD, 0x30000, 0x3FFFD, -1, -}; +} diff --git a/core/compress/common.odin b/core/compress/common.odin index ca63168a9..2364f1c8d 100644 --- a/core/compress/common.odin +++ b/core/compress/common.odin @@ -22,7 +22,7 @@ import "core:bytes" When a decompression routine doesn't stream its output, but writes to a buffer, we pre-allocate an output buffer to speed up decompression. The default is 1 MiB. */ -COMPRESS_OUTPUT_ALLOCATE_MIN :: int(#config(COMPRESS_OUTPUT_ALLOCATE_MIN, 1 << 20)); +COMPRESS_OUTPUT_ALLOCATE_MIN :: int(#config(COMPRESS_OUTPUT_ALLOCATE_MIN, 1 << 20)) /* This bounds the maximum a buffer will resize to as needed, or the maximum we'll @@ -36,12 +36,12 @@ when size_of(uintptr) == 8 { For 64-bit platforms, we set the default max buffer size to 4 GiB, which is GZIP and PKZIP's max payload size. */ - COMPRESS_OUTPUT_ALLOCATE_MAX :: int(#config(COMPRESS_OUTPUT_ALLOCATE_MAX, 1 << 32)); + COMPRESS_OUTPUT_ALLOCATE_MAX :: int(#config(COMPRESS_OUTPUT_ALLOCATE_MAX, 1 << 32)) } else { /* For 32-bit platforms, we set the default max buffer size to 512 MiB. */ - COMPRESS_OUTPUT_ALLOCATE_MAX :: int(#config(COMPRESS_OUTPUT_ALLOCATE_MAX, 1 << 29)); + COMPRESS_OUTPUT_ALLOCATE_MAX :: int(#config(COMPRESS_OUTPUT_ALLOCATE_MAX, 1 << 29)) } @@ -179,78 +179,78 @@ Context_Stream_Input :: struct #packed { // TODO: Make these return compress.Error errors. input_size_from_memory :: proc(z: ^Context_Memory_Input) -> (res: i64, err: Error) { - return i64(len(z.input_data)), nil; + return i64(len(z.input_data)), nil } input_size_from_stream :: proc(z: ^Context_Stream_Input) -> (res: i64, err: Error) { - return io.size(z.input), nil; + return io.size(z.input), nil } -input_size :: proc{input_size_from_memory, input_size_from_stream}; +input_size :: proc{input_size_from_memory, input_size_from_stream} @(optimization_mode="speed") read_slice_from_memory :: #force_inline proc(z: ^Context_Memory_Input, size: int) -> (res: []u8, err: io.Error) { #no_bounds_check { if len(z.input_data) >= size { - res = z.input_data[:size]; - z.input_data = z.input_data[size:]; - return res, .None; + res = z.input_data[:size] + z.input_data = z.input_data[size:] + return res, .None } } if len(z.input_data) == 0 { - return []u8{}, .EOF; + return []u8{}, .EOF } else { - return []u8{}, .Short_Buffer; + return []u8{}, .Short_Buffer } } @(optimization_mode="speed") read_slice_from_stream :: #force_inline proc(z: ^Context_Stream_Input, size: int) -> (res: []u8, err: io.Error) { - b := make([]u8, size, context.temp_allocator); - _, e := z.input->impl_read(b[:]); + b := make([]u8, size, context.temp_allocator) + _, e := z.input->impl_read(b[:]) if e == .None { - return b, .None; + return b, .None } - return []u8{}, e; + return []u8{}, e } -read_slice :: proc{read_slice_from_memory, read_slice_from_stream}; +read_slice :: proc{read_slice_from_memory, read_slice_from_stream} @(optimization_mode="speed") read_data :: #force_inline proc(z: ^$C, $T: typeid) -> (res: T, err: io.Error) { - b, e := read_slice(z, size_of(T)); + b, e := read_slice(z, size_of(T)) if e == .None { - return (^T)(&b[0])^, .None; + return (^T)(&b[0])^, .None } - return T{}, e; + return T{}, e } @(optimization_mode="speed") read_u8_from_memory :: #force_inline proc(z: ^Context_Memory_Input) -> (res: u8, err: io.Error) { #no_bounds_check { if len(z.input_data) >= 1 { - res = z.input_data[0]; - z.input_data = z.input_data[1:]; - return res, .None; + res = z.input_data[0] + z.input_data = z.input_data[1:] + return res, .None } } - return 0, .EOF; + return 0, .EOF } @(optimization_mode="speed") read_u8_from_stream :: #force_inline proc(z: ^Context_Stream_Input) -> (res: u8, err: io.Error) { - b, e := read_slice_from_stream(z, 1); + b, e := read_slice_from_stream(z, 1) if e == .None { - return b[0], .None; + return b[0], .None } - return 0, e; + return 0, e } -read_u8 :: proc{read_u8_from_memory, read_u8_from_stream}; +read_u8 :: proc{read_u8_from_memory, read_u8_from_stream} /* You would typically only use this at the end of Inflate, to drain bits from the code buffer @@ -259,64 +259,64 @@ read_u8 :: proc{read_u8_from_memory, read_u8_from_stream}; @(optimization_mode="speed") read_u8_prefer_code_buffer_lsb :: #force_inline proc(z: ^$C) -> (res: u8, err: io.Error) { if z.num_bits >= 8 { - res = u8(read_bits_no_refill_lsb(z, 8)); + res = u8(read_bits_no_refill_lsb(z, 8)) } else { - size, _ := input_size(z); + size, _ := input_size(z) if size > 0 { - res, err = read_u8(z); + res, err = read_u8(z) } else { - err = .EOF; + err = .EOF } } - return; + return } @(optimization_mode="speed") peek_data_from_memory :: #force_inline proc(z: ^Context_Memory_Input, $T: typeid) -> (res: T, err: io.Error) { - size :: size_of(T); + size :: size_of(T) #no_bounds_check { if len(z.input_data) >= size { - buf := z.input_data[:size]; - return (^T)(&buf[0])^, .None; + buf := z.input_data[:size] + return (^T)(&buf[0])^, .None } } if len(z.input_data) == 0 { - return T{}, .EOF; + return T{}, .EOF } else { - return T{}, .Short_Buffer; + return T{}, .Short_Buffer } } @(optimization_mode="speed") peek_data_from_stream :: #force_inline proc(z: ^Context_Stream_Input, $T: typeid) -> (res: T, err: io.Error) { - size :: size_of(T); + size :: size_of(T) // Get current position to read from. - curr, e1 := z.input->impl_seek(0, .Current); + curr, e1 := z.input->impl_seek(0, .Current) if e1 != .None { - return T{}, e1; + return T{}, e1 } - r, e2 := io.to_reader_at(z.input); + r, e2 := io.to_reader_at(z.input) if !e2 { - return T{}, .Empty; + return T{}, .Empty } when size <= 128 { - b: [size]u8; + b: [size]u8 } else { - b := make([]u8, size, context.temp_allocator); + b := make([]u8, size, context.temp_allocator) } - _, e3 := io.read_at(r, b[:], curr); + _, e3 := io.read_at(r, b[:], curr) if e3 != .None { - return T{}, .Empty; + return T{}, .Empty } - res = (^T)(&b[0])^; - return res, .None; + res = (^T)(&b[0])^ + return res, .None } -peek_data :: proc{peek_data_from_memory, peek_data_from_stream}; +peek_data :: proc{peek_data_from_memory, peek_data_from_stream} @@ -324,31 +324,31 @@ peek_data :: proc{peek_data_from_memory, peek_data_from_stream}; @(optimization_mode="speed") peek_back_byte :: #force_inline proc(z: ^$C, offset: i64) -> (res: u8, err: io.Error) { // Look back into the sliding window. - return z.output.buf[z.bytes_written - offset], .None; + return z.output.buf[z.bytes_written - offset], .None } // Generalized bit reader LSB @(optimization_mode="speed") refill_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width := i8(48)) { - refill := u64(width); - b := u64(0); + refill := u64(width) + b := u64(0) if z.num_bits > refill { - return; + return } for { if len(z.input_data) != 0 { - b = u64(z.input_data[0]); - z.input_data = z.input_data[1:]; + b = u64(z.input_data[0]) + z.input_data = z.input_data[1:] } else { - b = 0; + b = 0 } - z.code_buffer |= b << u8(z.num_bits); - z.num_bits += 8; + z.code_buffer |= b << u8(z.num_bits) + z.num_bits += 8 if z.num_bits > refill { - break; + break } } } @@ -356,123 +356,123 @@ refill_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width := // Generalized bit reader LSB @(optimization_mode="speed") refill_lsb_from_stream :: proc(z: ^Context_Stream_Input, width := i8(24)) { - refill := u64(width); + refill := u64(width) for { if z.num_bits > refill { - break; + break } if z.code_buffer == 0 && z.num_bits > 63 { - z.num_bits = 0; + z.num_bits = 0 } if z.code_buffer >= 1 << uint(z.num_bits) { // Code buffer is malformed. - z.num_bits = max(u64); - return; + z.num_bits = max(u64) + return } - b, err := read_u8(z); + b, err := read_u8(z) if err != .None { // This is fine at the end of the file. - return; + return } - z.code_buffer |= (u64(b) << u8(z.num_bits)); - z.num_bits += 8; + z.code_buffer |= (u64(b) << u8(z.num_bits)) + z.num_bits += 8 } } -refill_lsb :: proc{refill_lsb_from_memory, refill_lsb_from_stream}; +refill_lsb :: proc{refill_lsb_from_memory, refill_lsb_from_stream} @(optimization_mode="speed") consume_bits_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width: u8) { - z.code_buffer >>= width; - z.num_bits -= u64(width); + z.code_buffer >>= width + z.num_bits -= u64(width) } @(optimization_mode="speed") consume_bits_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width: u8) { - z.code_buffer >>= width; - z.num_bits -= u64(width); + z.code_buffer >>= width + z.num_bits -= u64(width) } -consume_bits_lsb :: proc{consume_bits_lsb_from_memory, consume_bits_lsb_from_stream}; +consume_bits_lsb :: proc{consume_bits_lsb_from_memory, consume_bits_lsb_from_stream} @(optimization_mode="speed") peek_bits_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width: u8) -> u32 { if z.num_bits < u64(width) { - refill_lsb(z); + refill_lsb(z) } - return u32(z.code_buffer & ~(~u64(0) << width)); + return u32(z.code_buffer & ~(~u64(0) << width)) } @(optimization_mode="speed") peek_bits_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width: u8) -> u32 { if z.num_bits < u64(width) { - refill_lsb(z); + refill_lsb(z) } - return u32(z.code_buffer & ~(~u64(0) << width)); + return u32(z.code_buffer & ~(~u64(0) << width)) } -peek_bits_lsb :: proc{peek_bits_lsb_from_memory, peek_bits_lsb_from_stream}; +peek_bits_lsb :: proc{peek_bits_lsb_from_memory, peek_bits_lsb_from_stream} @(optimization_mode="speed") peek_bits_no_refill_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width: u8) -> u32 { - assert(z.num_bits >= u64(width)); - return u32(z.code_buffer & ~(~u64(0) << width)); + assert(z.num_bits >= u64(width)) + return u32(z.code_buffer & ~(~u64(0) << width)) } @(optimization_mode="speed") peek_bits_no_refill_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width: u8) -> u32 { - assert(z.num_bits >= u64(width)); - return u32(z.code_buffer & ~(~u64(0) << width)); + assert(z.num_bits >= u64(width)) + return u32(z.code_buffer & ~(~u64(0) << width)) } -peek_bits_no_refill_lsb :: proc{peek_bits_no_refill_lsb_from_memory, peek_bits_no_refill_lsb_from_stream}; +peek_bits_no_refill_lsb :: proc{peek_bits_no_refill_lsb_from_memory, peek_bits_no_refill_lsb_from_stream} @(optimization_mode="speed") read_bits_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width: u8) -> u32 { - k := #force_inline peek_bits_lsb(z, width); + k := #force_inline peek_bits_lsb(z, width) #force_inline consume_bits_lsb(z, width); - return k; + return k } @(optimization_mode="speed") read_bits_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width: u8) -> u32 { - k := peek_bits_lsb(z, width); - consume_bits_lsb(z, width); - return k; + k := peek_bits_lsb(z, width) + consume_bits_lsb(z, width) + return k } -read_bits_lsb :: proc{read_bits_lsb_from_memory, read_bits_lsb_from_stream}; +read_bits_lsb :: proc{read_bits_lsb_from_memory, read_bits_lsb_from_stream} @(optimization_mode="speed") read_bits_no_refill_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width: u8) -> u32 { - k := #force_inline peek_bits_no_refill_lsb(z, width); + k := #force_inline peek_bits_no_refill_lsb(z, width) #force_inline consume_bits_lsb(z, width); - return k; + return k } @(optimization_mode="speed") read_bits_no_refill_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width: u8) -> u32 { - k := peek_bits_no_refill_lsb(z, width); - consume_bits_lsb(z, width); - return k; + k := peek_bits_no_refill_lsb(z, width) + consume_bits_lsb(z, width) + return k } -read_bits_no_refill_lsb :: proc{read_bits_no_refill_lsb_from_memory, read_bits_no_refill_lsb_from_stream}; +read_bits_no_refill_lsb :: proc{read_bits_no_refill_lsb_from_memory, read_bits_no_refill_lsb_from_stream} @(optimization_mode="speed") discard_to_next_byte_lsb_from_memory :: proc(z: ^Context_Memory_Input) { - discard := u8(z.num_bits & 7); + discard := u8(z.num_bits & 7) #force_inline consume_bits_lsb(z, discard); } @(optimization_mode="speed") discard_to_next_byte_lsb_from_stream :: proc(z: ^Context_Stream_Input) { - discard := u8(z.num_bits & 7); - consume_bits_lsb(z, discard); + discard := u8(z.num_bits & 7) + consume_bits_lsb(z, discard) } discard_to_next_byte_lsb :: proc{discard_to_next_byte_lsb_from_memory, discard_to_next_byte_lsb_from_stream};
\ No newline at end of file diff --git a/core/compress/gzip/example.odin b/core/compress/gzip/example.odin index 9dfd68f23..91bcb858a 100644 --- a/core/compress/gzip/example.odin +++ b/core/compress/gzip/example.odin @@ -28,62 +28,62 @@ TEST: []u8 = { 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x2b, 0x48, 0xac, 0xcc, 0xc9, 0x4f, 0x4c, 0x01, 0x00, 0x15, 0x6a, 0x2c, 0x42, 0x07, 0x00, 0x00, 0x00, -}; +} main :: proc() { // Set up output buffer. - buf := bytes.Buffer{}; + buf := bytes.Buffer{} stdout :: proc(s: string) { - os.write_string(os.stdout, s); + os.write_string(os.stdout, s) } stderr :: proc(s: string) { - os.write_string(os.stderr, s); + os.write_string(os.stderr, s) } - args := os.args; + args := os.args if len(args) < 2 { - stderr("No input file specified.\n"); - err := load(slice=TEST, buf=&buf, known_gzip_size=len(TEST)); + stderr("No input file specified.\n") + err := load(slice=TEST, buf=&buf, known_gzip_size=len(TEST)) if err == nil { - stdout("Displaying test vector: "); - stdout(bytes.buffer_to_string(&buf)); - stdout("\n"); + stdout("Displaying test vector: ") + stdout(bytes.buffer_to_string(&buf)) + stdout("\n") } else { - fmt.printf("gzip.load returned %v\n", err); + fmt.printf("gzip.load returned %v\n", err) } - bytes.buffer_destroy(&buf); - os.exit(0); + bytes.buffer_destroy(&buf) + os.exit(0) } // The rest are all files. - args = args[1:]; - err: Error; + args = args[1:] + err: Error for file in args { if file == "-" { // Read from stdin - s := os.stream_from_handle(os.stdin); + s := os.stream_from_handle(os.stdin) ctx := &compress.Context_Stream_Input{ input = s, - }; - err = load(ctx, &buf); + } + err = load(ctx, &buf) } else { - err = load(file, &buf); + err = load(file, &buf) } if err != nil { if err != E_General.File_Not_Found { - stderr("File not found: "); - stderr(file); - stderr("\n"); - os.exit(1); + stderr("File not found: ") + stderr(file) + stderr("\n") + os.exit(1) } - stderr("GZIP returned an error.\n"); - bytes.buffer_destroy(&buf); - os.exit(2); + stderr("GZIP returned an error.\n") + bytes.buffer_destroy(&buf) + os.exit(2) } - stdout(bytes.buffer_to_string(&buf)); + stdout(bytes.buffer_to_string(&buf)) } - bytes.buffer_destroy(&buf); + bytes.buffer_destroy(&buf) } diff --git a/core/compress/gzip/gzip.odin b/core/compress/gzip/gzip.odin index 6a17627bc..1ef7cc827 100644 --- a/core/compress/gzip/gzip.odin +++ b/core/compress/gzip/gzip.odin @@ -46,7 +46,7 @@ Header_Flag :: enum u8 { reserved_2 = 6, reserved_3 = 7, } -Header_Flags :: distinct bit_set[Header_Flag; u8]; +Header_Flags :: distinct bit_set[Header_Flag; u8] OS :: enum u8 { FAT = 0, @@ -82,7 +82,7 @@ OS_Name :: #partial [OS]string{ .QDOS = "QDOS", .Acorn_RISCOS = "Acorn RISCOS", .Unknown = "Unknown", -}; +} Compression :: enum u8 { DEFLATE = 8, @@ -93,74 +93,74 @@ Compression_Flags :: enum u8 { Fastest_Compression = 4, } -Error :: compress.Error; -E_General :: compress.General_Error; -E_GZIP :: compress.GZIP_Error; -E_ZLIB :: compress.ZLIB_Error; -E_Deflate :: compress.Deflate_Error; +Error :: compress.Error +E_General :: compress.General_Error +E_GZIP :: compress.GZIP_Error +E_ZLIB :: compress.ZLIB_Error +E_Deflate :: compress.Deflate_Error -GZIP_MAX_PAYLOAD_SIZE :: int(max(u32le)); +GZIP_MAX_PAYLOAD_SIZE :: int(max(u32le)) -load :: proc{load_from_slice, load_from_file, load_from_context}; +load :: proc{load_from_slice, load_from_file, load_from_context} load_from_file :: proc(filename: string, buf: ^bytes.Buffer, expected_output_size := -1, allocator := context.allocator) -> (err: Error) { - data, ok := os.read_entire_file(filename, allocator); - defer delete(data); + data, ok := os.read_entire_file(filename, allocator) + defer delete(data) - err = E_General.File_Not_Found; + err = E_General.File_Not_Found if ok { - err = load_from_slice(data, buf, len(data), expected_output_size, allocator); + err = load_from_slice(data, buf, len(data), expected_output_size, allocator) } - return; + return } load_from_slice :: proc(slice: []u8, buf: ^bytes.Buffer, known_gzip_size := -1, expected_output_size := -1, allocator := context.allocator) -> (err: Error) { - buf := buf; + buf := buf z := &compress.Context_Memory_Input{ input_data = slice, output = buf, - }; - return load_from_context(z, buf, known_gzip_size, expected_output_size, allocator); + } + return load_from_context(z, buf, known_gzip_size, expected_output_size, allocator) } load_from_context :: proc(z: ^$C, buf: ^bytes.Buffer, known_gzip_size := -1, expected_output_size := -1, allocator := context.allocator) -> (err: Error) { - buf := buf; - expected_output_size := expected_output_size; + buf := buf + expected_output_size := expected_output_size - input_data_consumed := 0; + input_data_consumed := 0 - z.output = buf; + z.output = buf if expected_output_size > GZIP_MAX_PAYLOAD_SIZE { - return E_GZIP.Payload_Size_Exceeds_Max_Payload; + return E_GZIP.Payload_Size_Exceeds_Max_Payload } if expected_output_size > compress.COMPRESS_OUTPUT_ALLOCATE_MAX { - return E_GZIP.Output_Exceeds_COMPRESS_OUTPUT_ALLOCATE_MAX; + return E_GZIP.Output_Exceeds_COMPRESS_OUTPUT_ALLOCATE_MAX } - b: []u8; + b: []u8 - header, e := compress.read_data(z, Header); + header, e := compress.read_data(z, Header) if e != .None { - return E_General.File_Too_Short; + return E_General.File_Too_Short } - input_data_consumed += size_of(Header); + input_data_consumed += size_of(Header) if header.magic != .GZIP { - return E_GZIP.Invalid_GZIP_Signature; + return E_GZIP.Invalid_GZIP_Signature } if header.compression_method != .DEFLATE { - return E_General.Unknown_Compression_Method; + return E_General.Unknown_Compression_Method } if header.os >= ._Unknown { - header.os = .Unknown; + header.os = .Unknown } if .reserved_1 in header.flags || .reserved_2 in header.flags || .reserved_3 in header.flags { - return E_GZIP.Reserved_Flag_Set; + return E_GZIP.Reserved_Flag_Set } // printf("signature: %v\n", header.magic); @@ -171,84 +171,84 @@ load_from_context :: proc(z: ^$C, buf: ^bytes.Buffer, known_gzip_size := -1, exp // printf("os: %v\n", OS_Name[header.os]); if .extra in header.flags { - xlen, e_extra := compress.read_data(z, u16le); - input_data_consumed += 2; + xlen, e_extra := compress.read_data(z, u16le) + input_data_consumed += 2 if e_extra != .None { - return E_General.Stream_Too_Short; + return E_General.Stream_Too_Short } // printf("Extra data present (%v bytes)\n", xlen); if xlen < 4 { // Minimum length is 2 for ID + 2 for a field length, if set to zero. - return E_GZIP.Invalid_Extra_Data; + return E_GZIP.Invalid_Extra_Data } - field_id: [2]u8; - field_length: u16le; - field_error: io.Error; + field_id: [2]u8 + field_length: u16le + field_error: io.Error for xlen >= 4 { // println("Parsing Extra field(s)."); - field_id, field_error = compress.read_data(z, [2]u8); + field_id, field_error = compress.read_data(z, [2]u8) if field_error != .None { // printf("Parsing Extra returned: %v\n", field_error); - return E_General.Stream_Too_Short; + return E_General.Stream_Too_Short } - xlen -= 2; - input_data_consumed += 2; + xlen -= 2 + input_data_consumed += 2 - field_length, field_error = compress.read_data(z, u16le); + field_length, field_error = compress.read_data(z, u16le) if field_error != .None { // printf("Parsing Extra returned: %v\n", field_error); - return E_General.Stream_Too_Short; + return E_General.Stream_Too_Short } - xlen -= 2; - input_data_consumed += 2; + xlen -= 2 + input_data_consumed += 2 if xlen <= 0 { // We're not going to try and recover by scanning for a ZLIB header. // Who knows what else is wrong with this file. - return E_GZIP.Invalid_Extra_Data; + return E_GZIP.Invalid_Extra_Data } // printf(" Field \"%v\" of length %v found: ", string(field_id[:]), field_length); if field_length > 0 { - b, field_error = compress.read_slice(z, int(field_length)); + b, field_error = compress.read_slice(z, int(field_length)) if field_error != .None { // printf("Parsing Extra returned: %v\n", field_error); - return E_General.Stream_Too_Short; + return E_General.Stream_Too_Short } - xlen -= field_length; - input_data_consumed += int(field_length); + xlen -= field_length + input_data_consumed += int(field_length) // printf("%v\n", string(field_data)); } if xlen != 0 { - return E_GZIP.Invalid_Extra_Data; + return E_GZIP.Invalid_Extra_Data } } } if .name in header.flags { // Should be enough. - name: [1024]u8; - i := 0; - name_error: io.Error; + name: [1024]u8 + i := 0 + name_error: io.Error for i < len(name) { - b, name_error = compress.read_slice(z, 1); + b, name_error = compress.read_slice(z, 1) if name_error != .None { - return E_General.Stream_Too_Short; + return E_General.Stream_Too_Short } - input_data_consumed += 1; + input_data_consumed += 1 if b[0] == 0 { - break; + break } - name[i] = b[0]; - i += 1; + name[i] = b[0] + i += 1 if i >= len(name) { - return E_GZIP.Original_Name_Too_Long; + return E_GZIP.Original_Name_Too_Long } } // printf("Original filename: %v\n", string(name[:i])); @@ -256,34 +256,34 @@ load_from_context :: proc(z: ^$C, buf: ^bytes.Buffer, known_gzip_size := -1, exp if .comment in header.flags { // Should be enough. - comment: [1024]u8; - i := 0; - comment_error: io.Error; + comment: [1024]u8 + i := 0 + comment_error: io.Error for i < len(comment) { - b, comment_error = compress.read_slice(z, 1); + b, comment_error = compress.read_slice(z, 1) if comment_error != .None { - return E_General.Stream_Too_Short; + return E_General.Stream_Too_Short } - input_data_consumed += 1; + input_data_consumed += 1 if b[0] == 0 { - break; + break } - comment[i] = b[0]; - i += 1; + comment[i] = b[0] + i += 1 if i >= len(comment) { - return E_GZIP.Comment_Too_Long; + return E_GZIP.Comment_Too_Long } } // printf("Comment: %v\n", string(comment[:i])); } if .header_crc in header.flags { - crc_error: io.Error; - _, crc_error = compress.read_slice(z, 2); - input_data_consumed += 2; + crc_error: io.Error + _, crc_error = compress.read_slice(z, 2) + input_data_consumed += 2 if crc_error != .None { - return E_General.Stream_Too_Short; + return E_General.Stream_Too_Short } /* We don't actually check the CRC16 (lower 2 bytes of CRC32 of header data until the CRC field). @@ -294,7 +294,7 @@ load_from_context :: proc(z: ^$C, buf: ^bytes.Buffer, known_gzip_size := -1, exp /* We should have arrived at the ZLIB payload. */ - payload_u32le: u32le; + payload_u32le: u32le // fmt.printf("known_gzip_size: %v | expected_output_size: %v\n", known_gzip_size, expected_output_size); @@ -314,12 +314,12 @@ load_from_context :: proc(z: ^$C, buf: ^bytes.Buffer, known_gzip_size := -1, exp */ if known_gzip_size > -1 { - offset := i64(known_gzip_size - input_data_consumed - 4); - size, _ := compress.input_size(z); + offset := i64(known_gzip_size - input_data_consumed - 4) + size, _ := compress.input_size(z) if size >= offset + 4 { - length_bytes := z.input_data[offset:][:4]; - payload_u32le = (^u32le)(&length_bytes[0])^; - expected_output_size = int(payload_u32le); + length_bytes := z.input_data[offset:][:4] + payload_u32le = (^u32le)(&length_bytes[0])^ + expected_output_size = int(payload_u32le) } } else { /* @@ -331,37 +331,37 @@ load_from_context :: proc(z: ^$C, buf: ^bytes.Buffer, known_gzip_size := -1, exp // fmt.printf("GZIP: Expected Payload Size: %v\n", expected_output_size); - zlib_error := zlib.inflate_raw(z=z, expected_output_size=expected_output_size); + zlib_error := zlib.inflate_raw(z=z, expected_output_size=expected_output_size) if zlib_error != nil { - return zlib_error; + return zlib_error } /* Read CRC32 using the ctx bit reader because zlib may leave bytes in there. */ - compress.discard_to_next_byte_lsb(z); + compress.discard_to_next_byte_lsb(z) - footer_error: io.Error; + footer_error: io.Error - payload_crc_b: [4]u8; + payload_crc_b: [4]u8 for _, i in payload_crc_b { - payload_crc_b[i], footer_error = compress.read_u8_prefer_code_buffer_lsb(z); + payload_crc_b[i], footer_error = compress.read_u8_prefer_code_buffer_lsb(z) } - payload_crc := transmute(u32le)payload_crc_b; + payload_crc := transmute(u32le)payload_crc_b - payload := bytes.buffer_to_bytes(buf); - crc32 := u32le(hash.crc32(payload)); + payload := bytes.buffer_to_bytes(buf) + crc32 := u32le(hash.crc32(payload)) if crc32 != payload_crc { - return E_GZIP.Payload_CRC_Invalid; + return E_GZIP.Payload_CRC_Invalid } - payload_len_b: [4]u8; + payload_len_b: [4]u8 for _, i in payload_len_b { - payload_len_b[i], footer_error = compress.read_u8_prefer_code_buffer_lsb(z); + payload_len_b[i], footer_error = compress.read_u8_prefer_code_buffer_lsb(z) } - payload_len := transmute(u32le)payload_len_b; + payload_len := transmute(u32le)payload_len_b if len(payload) != int(payload_len) { - return E_GZIP.Payload_Length_Invalid; + return E_GZIP.Payload_Length_Invalid } - return nil; + return nil } diff --git a/core/compress/zlib/example.odin b/core/compress/zlib/example.odin index aab074fb4..fb7da5a08 100644 --- a/core/compress/zlib/example.odin +++ b/core/compress/zlib/example.odin @@ -34,19 +34,19 @@ main :: proc() { 98, 53, 8, 104, 213, 234, 201, 147, 7, 248, 192, 14, 170, 29, 25, 171, 15, 18, 59, 138, 112, 63, 23, 205, 110, 254, 136, 109, 78, 231, 63, 234, 138, 133, 204, - }; - OUTPUT_SIZE :: 438; + } + OUTPUT_SIZE :: 438 - buf: bytes.Buffer; + buf: bytes.Buffer // We can pass ", true" to inflate a raw DEFLATE stream instead of a ZLIB wrapped one. - err := inflate(input=ODIN_DEMO, buf=&buf, expected_output_size=OUTPUT_SIZE); - defer bytes.buffer_destroy(&buf); + err := inflate(input=ODIN_DEMO, buf=&buf, expected_output_size=OUTPUT_SIZE) + defer bytes.buffer_destroy(&buf) if err != nil { - fmt.printf("\nError: %v\n", err); + fmt.printf("\nError: %v\n", err) } - s := bytes.buffer_to_string(&buf); - fmt.printf("Input: %v bytes, output (%v bytes):\n%v\n", len(ODIN_DEMO), len(s), s); - assert(len(s) == OUTPUT_SIZE); + s := bytes.buffer_to_string(&buf) + fmt.printf("Input: %v bytes, output (%v bytes):\n%v\n", len(ODIN_DEMO), len(s), s) + assert(len(s) == OUTPUT_SIZE) } diff --git a/core/compress/zlib/zlib.odin b/core/compress/zlib/zlib.odin index 7a48d9440..ad9d44d4d 100644 --- a/core/compress/zlib/zlib.odin +++ b/core/compress/zlib/zlib.odin @@ -47,41 +47,41 @@ Options :: struct { level: u8, } -Error :: compress.Error; -E_General :: compress.General_Error; -E_ZLIB :: compress.ZLIB_Error; -E_Deflate :: compress.Deflate_Error; +Error :: compress.Error +E_General :: compress.General_Error +E_ZLIB :: compress.ZLIB_Error +E_Deflate :: compress.Deflate_Error -DEFLATE_MAX_CHUNK_SIZE :: 65535; -DEFLATE_MAX_LITERAL_SIZE :: 65535; -DEFLATE_MAX_DISTANCE :: 32768; -DEFLATE_MAX_LENGTH :: 258; +DEFLATE_MAX_CHUNK_SIZE :: 65535 +DEFLATE_MAX_LITERAL_SIZE :: 65535 +DEFLATE_MAX_DISTANCE :: 32768 +DEFLATE_MAX_LENGTH :: 258 -HUFFMAN_MAX_BITS :: 16; -HUFFMAN_FAST_BITS :: 9; -HUFFMAN_FAST_MASK :: ((1 << HUFFMAN_FAST_BITS) - 1); +HUFFMAN_MAX_BITS :: 16 +HUFFMAN_FAST_BITS :: 9 +HUFFMAN_FAST_MASK :: ((1 << HUFFMAN_FAST_BITS) - 1) Z_LENGTH_BASE := [31]u16{ 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59, 67,83,99,115,131,163,195,227,258,0,0, -}; +} Z_LENGTH_EXTRA := [31]u8{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0, -}; +} Z_DIST_BASE := [32]u16{ 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, 257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0, -}; +} Z_DIST_EXTRA := [32]u8{ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0, -}; +} Z_LENGTH_DEZIGZAG := []u8{ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15, -}; +} Z_FIXED_LENGTH := [288]u8{ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, @@ -93,17 +93,17 @@ Z_FIXED_LENGTH := [288]u8{ 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8, -}; +} Z_FIXED_DIST := [32]u8{ 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -}; +} /* Accelerate all cases in default tables. */ -ZFAST_BITS :: 9; -ZFAST_MASK :: ((1 << ZFAST_BITS) - 1); +ZFAST_BITS :: 9 +ZFAST_MASK :: ((1 << ZFAST_BITS) - 1) /* ZLIB-style Huffman encoding. @@ -116,22 +116,22 @@ Huffman_Table :: struct { firstsymbol: [16]u16, size: [288]u8, value: [288]u16, -}; +} // Implementation starts here @(optimization_mode="speed") z_bit_reverse :: #force_inline proc(n: u16, bits: u8) -> (r: u16) { - assert(bits <= 16); + assert(bits <= 16) // NOTE: Can optimize with llvm.bitreverse.i64 or some bit twiddling // by reversing all of the bits and masking out the unneeded ones. - r = n; - r = ((r & 0xAAAA) >> 1) | ((r & 0x5555) << 1); - r = ((r & 0xCCCC) >> 2) | ((r & 0x3333) << 2); - r = ((r & 0xF0F0) >> 4) | ((r & 0x0F0F) << 4); - r = ((r & 0xFF00) >> 8) | ((r & 0x00FF) << 8); - - r >>= (16 - bits); - return; + r = n + r = ((r & 0xAAAA) >> 1) | ((r & 0x5555) << 1) + r = ((r & 0xCCCC) >> 2) | ((r & 0x3333) << 2) + r = ((r & 0xF0F0) >> 4) | ((r & 0x0F0F) << 4) + r = ((r & 0xFF00) >> 8) | ((r & 0x00FF) << 8) + + r >>= (16 - bits) + return } @@ -145,16 +145,16 @@ grow_buffer :: proc(buf: ^[dynamic]u8) -> (err: compress.Error) { /* Double until we reach the maximum allowed. */ - new_size := min(len(buf) << 1, compress.COMPRESS_OUTPUT_ALLOCATE_MAX); - resize(buf, new_size); + new_size := min(len(buf) << 1, compress.COMPRESS_OUTPUT_ALLOCATE_MAX) + resize(buf, new_size) if len(buf) != new_size { /* Resize failed. */ - return .Resize_Failed; + return .Resize_Failed } - return nil; + return nil } /* @@ -167,17 +167,17 @@ write_byte :: #force_inline proc(z: ^$C, c: u8) -> (err: io.Error) #no_bounds_ch Resize if needed. */ if int(z.bytes_written) + 1 >= len(z.output.buf) { - e := grow_buffer(&z.output.buf); + e := grow_buffer(&z.output.buf) if e != nil { - return .Short_Write; + return .Short_Write } } #no_bounds_check { - z.output.buf[z.bytes_written] = c; + z.output.buf[z.bytes_written] = c } - z.bytes_written += 1; - return .None; + z.bytes_written += 1 + return .None } @(optimization_mode="speed") @@ -192,20 +192,20 @@ repl_byte :: proc(z: ^$C, count: u16, c: u8) -> (err: io.Error) #no_bounds_chec Resize if needed. */ if int(z.bytes_written) + int(count) >= len(z.output.buf) { - e := grow_buffer(&z.output.buf); + e := grow_buffer(&z.output.buf) if e != nil { - return .Short_Write; + return .Short_Write } } #no_bounds_check { for _ in 0..<count { - z.output.buf[z.bytes_written] = c; - z.bytes_written += 1; + z.output.buf[z.bytes_written] = c + z.bytes_written += 1 } } - return .None; + return .None } @(optimization_mode="speed") @@ -216,178 +216,178 @@ repl_bytes :: proc(z: ^$C, count: u16, distance: u16) -> (err: io.Error) { the output stream, just give it _that_ slice. */ - offset := i64(distance); + offset := i64(distance) if int(z.bytes_written) + int(count) >= len(z.output.buf) { - e := grow_buffer(&z.output.buf); + e := grow_buffer(&z.output.buf) if e != nil { - return .Short_Write; + return .Short_Write } } #no_bounds_check { for _ in 0..<count { - c := z.output.buf[z.bytes_written - offset]; - z.output.buf[z.bytes_written] = c; - z.bytes_written += 1; + c := z.output.buf[z.bytes_written - offset] + z.output.buf[z.bytes_written] = c + z.bytes_written += 1 } } - return .None; + return .None } allocate_huffman_table :: proc(allocator := context.allocator) -> (z: ^Huffman_Table, err: Error) { - return new(Huffman_Table, allocator), nil; + return new(Huffman_Table, allocator), nil } @(optimization_mode="speed") build_huffman :: proc(z: ^Huffman_Table, code_lengths: []u8) -> (err: Error) { - sizes: [HUFFMAN_MAX_BITS+1]int; - next_code: [HUFFMAN_MAX_BITS]int; + sizes: [HUFFMAN_MAX_BITS+1]int + next_code: [HUFFMAN_MAX_BITS]int - k := int(0); + k := int(0) - mem.zero_slice(sizes[:]); - mem.zero_slice(z.fast[:]); + mem.zero_slice(sizes[:]) + mem.zero_slice(z.fast[:]) for v in code_lengths { - sizes[v] += 1; + sizes[v] += 1 } - sizes[0] = 0; + sizes[0] = 0 for i in 1..<(HUFFMAN_MAX_BITS+1) { if sizes[i] > (1 << uint(i)) { - return E_Deflate.Huffman_Bad_Sizes; + return E_Deflate.Huffman_Bad_Sizes } } - code := int(0); + code := int(0) for i in 1..<HUFFMAN_MAX_BITS { - next_code[i] = code; - z.firstcode[i] = u16(code); - z.firstsymbol[i] = u16(k); - code = code + sizes[i]; + next_code[i] = code + z.firstcode[i] = u16(code) + z.firstsymbol[i] = u16(k) + code = code + sizes[i] if sizes[i] != 0 { if code - 1 >= (1 << u16(i)) { - return E_Deflate.Huffman_Bad_Code_Lengths; + return E_Deflate.Huffman_Bad_Code_Lengths } } - z.maxcode[i] = code << (HUFFMAN_MAX_BITS - uint(i)); - code <<= 1; - k += int(sizes[i]); + z.maxcode[i] = code << (HUFFMAN_MAX_BITS - uint(i)) + code <<= 1 + k += int(sizes[i]) } - z.maxcode[HUFFMAN_MAX_BITS] = 0x10000; // Sentinel - c: int; + z.maxcode[HUFFMAN_MAX_BITS] = 0x10000 // Sentinel + c: int for v, ci in code_lengths { if v != 0 { - c = next_code[v] - int(z.firstcode[v]) + int(z.firstsymbol[v]); - fastv := u16((u16(v) << 9) | u16(ci)); - z.size[c] = u8(v); - z.value[c] = u16(ci); + c = next_code[v] - int(z.firstcode[v]) + int(z.firstsymbol[v]) + fastv := u16((u16(v) << 9) | u16(ci)) + z.size[c] = u8(v) + z.value[c] = u16(ci) if v <= ZFAST_BITS { - j := z_bit_reverse(u16(next_code[v]), v); + j := z_bit_reverse(u16(next_code[v]), v) for j < (1 << ZFAST_BITS) { - z.fast[j] = fastv; - j += (1 << v); + z.fast[j] = fastv + j += (1 << v) } } - next_code[v] += 1; + next_code[v] += 1 } } - return nil; + return nil } @(optimization_mode="speed") decode_huffman_slowpath :: proc(z: ^$C, t: ^Huffman_Table) -> (r: u16, err: Error) #no_bounds_check { - code := u16(compress.peek_bits_lsb(z,16)); + code := u16(compress.peek_bits_lsb(z,16)) - k := int(z_bit_reverse(code, 16)); - s: u8; + k := int(z_bit_reverse(code, 16)) + s: u8 #no_bounds_check for s = HUFFMAN_FAST_BITS+1; ; { if k < t.maxcode[s] { - break; + break } - s += 1; + s += 1 } if s >= 16 { - return 0, E_Deflate.Bad_Huffman_Code; + return 0, E_Deflate.Bad_Huffman_Code } // code size is s, so: - b := (k >> (16-s)) - int(t.firstcode[s]) + int(t.firstsymbol[s]); + b := (k >> (16-s)) - int(t.firstcode[s]) + int(t.firstsymbol[s]) if b >= size_of(t.size) { - return 0, E_Deflate.Bad_Huffman_Code; + return 0, E_Deflate.Bad_Huffman_Code } if t.size[b] != s { - return 0, E_Deflate.Bad_Huffman_Code; + return 0, E_Deflate.Bad_Huffman_Code } - compress.consume_bits_lsb(z, s); + compress.consume_bits_lsb(z, s) - r = t.value[b]; - return r, nil; + r = t.value[b] + return r, nil } @(optimization_mode="speed") decode_huffman :: proc(z: ^$C, t: ^Huffman_Table) -> (r: u16, err: Error) #no_bounds_check { if z.num_bits < 16 { if z.num_bits > 63 { - return 0, E_ZLIB.Code_Buffer_Malformed; + return 0, E_ZLIB.Code_Buffer_Malformed } - compress.refill_lsb(z); + compress.refill_lsb(z) if z.num_bits > 63 { - return 0, E_General.Stream_Too_Short; + return 0, E_General.Stream_Too_Short } } - #no_bounds_check b := t.fast[z.code_buffer & ZFAST_MASK]; + #no_bounds_check b := t.fast[z.code_buffer & ZFAST_MASK] if b != 0 { - s := u8(b >> ZFAST_BITS); - compress.consume_bits_lsb(z, s); - return b & 511, nil; + s := u8(b >> ZFAST_BITS) + compress.consume_bits_lsb(z, s) + return b & 511, nil } - return decode_huffman_slowpath(z, t); + return decode_huffman_slowpath(z, t) } @(optimization_mode="speed") parse_huffman_block :: proc(z: ^$C, z_repeat, z_offset: ^Huffman_Table) -> (err: Error) #no_bounds_check { #no_bounds_check for { - value, e := decode_huffman(z, z_repeat); + value, e := decode_huffman(z, z_repeat) if e != nil { - return err; + return err } if value < 256 { - e := write_byte(z, u8(value)); + e := write_byte(z, u8(value)) if e != .None { - return E_General.Output_Too_Short; + return E_General.Output_Too_Short } } else { if value == 256 { // End of block - return nil; + return nil } - value -= 257; - length := Z_LENGTH_BASE[value]; + value -= 257 + length := Z_LENGTH_BASE[value] if Z_LENGTH_EXTRA[value] > 0 { - length += u16(compress.read_bits_lsb(z, Z_LENGTH_EXTRA[value])); + length += u16(compress.read_bits_lsb(z, Z_LENGTH_EXTRA[value])) } - value, e = decode_huffman(z, z_offset); + value, e = decode_huffman(z, z_offset) if e != nil { - return E_Deflate.Bad_Huffman_Code; + return E_Deflate.Bad_Huffman_Code } - distance := Z_DIST_BASE[value]; + distance := Z_DIST_BASE[value] if Z_DIST_EXTRA[value] > 0 { - distance += u16(compress.read_bits_lsb(z, Z_DIST_EXTRA[value])); + distance += u16(compress.read_bits_lsb(z, Z_DIST_EXTRA[value])) } if z.bytes_written < i64(distance) { // Distance is longer than we've decoded so far. - return E_Deflate.Bad_Distance; + return E_Deflate.Bad_Distance } /* @@ -402,17 +402,17 @@ parse_huffman_block :: proc(z: ^$C, z_repeat, z_offset: ^Huffman_Table) -> (err: Replicate the last outputted byte, length times. */ if length > 0 { - c := z.output.buf[z.bytes_written - i64(distance)]; - e := repl_byte(z, length, c); + c := z.output.buf[z.bytes_written - i64(distance)] + e := repl_byte(z, length, c) if e != .None { - return E_General.Output_Too_Short; + return E_General.Output_Too_Short } } } else { if length > 0 { - e := repl_bytes(z, length, distance); + e := repl_bytes(z, length, distance) if e != .None { - return E_General.Output_Too_Short; + return E_General.Output_Too_Short } } } @@ -430,27 +430,27 @@ inflate_from_context :: proc(using ctx: ^compress.Context_Memory_Input, raw := f */ if !raw { - size, size_err := compress.input_size(ctx); + size, size_err := compress.input_size(ctx) if size < 6 || size_err != nil { - return E_General.Stream_Too_Short; + return E_General.Stream_Too_Short } - cmf, _ := compress.read_u8(ctx); + cmf, _ := compress.read_u8(ctx) - method := Compression_Method(cmf & 0xf); + method := Compression_Method(cmf & 0xf) if method != .DEFLATE { - return E_General.Unknown_Compression_Method; + return E_General.Unknown_Compression_Method } if cinfo := (cmf >> 4) & 0xf; cinfo > 7 { - return E_ZLIB.Unsupported_Window_Size; + return E_ZLIB.Unsupported_Window_Size } - flg, _ := compress.read_u8(ctx); + flg, _ := compress.read_u8(ctx) - fcheck := flg & 0x1f; - fcheck_computed := (cmf << 8 | flg) & 0x1f; + fcheck := flg & 0x1f + fcheck_computed := (cmf << 8 | flg) & 0x1f if fcheck != fcheck_computed { - return E_General.Checksum_Failed; + return E_General.Checksum_Failed } /* @@ -458,7 +458,7 @@ inflate_from_context :: proc(using ctx: ^compress.Context_Memory_Input, raw := f They're application specific and PNG doesn't use them. */ if fdict := (flg >> 5) & 1; fdict != 0 { - return E_ZLIB.FDICT_Unsupported; + return E_ZLIB.FDICT_Unsupported } // flevel := Compression_Level((flg >> 6) & 3); @@ -471,36 +471,36 @@ inflate_from_context :: proc(using ctx: ^compress.Context_Memory_Input, raw := f } // Parse ZLIB stream without header. - inflate_raw(z=ctx, expected_output_size=expected_output_size) or_return; + inflate_raw(z=ctx, expected_output_size=expected_output_size) or_return if !raw { - compress.discard_to_next_byte_lsb(ctx); + compress.discard_to_next_byte_lsb(ctx) - adler_b: [4]u8; + adler_b: [4]u8 for _, i in adler_b { - adler_b[i], _ = compress.read_u8_prefer_code_buffer_lsb(ctx); + adler_b[i], _ = compress.read_u8_prefer_code_buffer_lsb(ctx) } - adler := transmute(u32be)adler_b; + adler := transmute(u32be)adler_b - output_hash := hash.adler32(ctx.output.buf[:]); + output_hash := hash.adler32(ctx.output.buf[:]) if output_hash != u32(adler) { - return E_General.Checksum_Failed; + return E_General.Checksum_Failed } } - return nil; + return nil } // TODO: Check alignment of reserve/resize. @(optimization_mode="speed") inflate_raw :: proc(z: ^$C, expected_output_size := -1, allocator := context.allocator) -> (err: Error) #no_bounds_check { - expected_output_size := expected_output_size; + expected_output_size := expected_output_size /* Always set up a minimum allocation size. */ - expected_output_size = max(max(expected_output_size, compress.COMPRESS_OUTPUT_ALLOCATE_MIN), 512); + expected_output_size = max(max(expected_output_size, compress.COMPRESS_OUTPUT_ALLOCATE_MIN), 512) // fmt.printf("\nZLIB: Expected Payload Size: %v\n\n", expected_output_size); @@ -508,34 +508,34 @@ inflate_raw :: proc(z: ^$C, expected_output_size := -1, allocator := context.all /* Try to pre-allocate the output buffer. */ - reserve(&z.output.buf, expected_output_size); - resize (&z.output.buf, expected_output_size); + reserve(&z.output.buf, expected_output_size) + resize (&z.output.buf, expected_output_size) }; if len(z.output.buf) != expected_output_size { - return .Resize_Failed; + return .Resize_Failed } - z.num_bits = 0; - z.code_buffer = 0; + z.num_bits = 0 + z.code_buffer = 0 - z_repeat: ^Huffman_Table; - z_offset: ^Huffman_Table; - codelength_ht: ^Huffman_Table; - defer free(z_repeat); - defer free(z_offset); - defer free(codelength_ht); + z_repeat: ^Huffman_Table + z_offset: ^Huffman_Table + codelength_ht: ^Huffman_Table + defer free(z_repeat) + defer free(z_offset) + defer free(codelength_ht) - z_repeat = allocate_huffman_table(allocator=context.allocator) or_return; - z_offset = allocate_huffman_table(allocator=context.allocator) or_return; - codelength_ht = allocate_huffman_table(allocator=context.allocator) or_return; + z_repeat = allocate_huffman_table(allocator=context.allocator) or_return + z_offset = allocate_huffman_table(allocator=context.allocator) or_return + codelength_ht = allocate_huffman_table(allocator=context.allocator) or_return - final := u32(0); - type := u32(0); + final := u32(0) + type := u32(0) for { - final = compress.read_bits_lsb(z, 1); - type = compress.read_bits_lsb(z, 2); + final = compress.read_bits_lsb(z, 1) + type = compress.read_bits_lsb(z, 2) // fmt.printf("Final: %v | Type: %v\n", final, type); @@ -544,16 +544,16 @@ inflate_raw :: proc(z: ^$C, expected_output_size := -1, allocator := context.all // Uncompressed block // Discard bits until next byte boundary - compress.discard_to_next_byte_lsb(z); + compress.discard_to_next_byte_lsb(z) - uncompressed_len := i16(compress.read_bits_lsb(z, 16)); - length_check := i16(compress.read_bits_lsb(z, 16)); + uncompressed_len := i16(compress.read_bits_lsb(z, 16)) + length_check := i16(compress.read_bits_lsb(z, 16)) // fmt.printf("LEN: %v, ~LEN: %v, NLEN: %v, ~NLEN: %v\n", uncompressed_len, ~uncompressed_len, length_check, ~length_check); if ~uncompressed_len != length_check { - return E_Deflate.Len_Nlen_Mismatch; + return E_Deflate.Len_Nlen_Mismatch } /* @@ -561,116 +561,116 @@ inflate_raw :: proc(z: ^$C, expected_output_size := -1, allocator := context.all and a single Adler32 update after. */ #no_bounds_check for uncompressed_len > 0 { - compress.refill_lsb(z); - lit := compress.read_bits_lsb(z, 8); - write_byte(z, u8(lit)); - uncompressed_len -= 1; + compress.refill_lsb(z) + lit := compress.read_bits_lsb(z, 8) + write_byte(z, u8(lit)) + uncompressed_len -= 1 } case 3: - return E_Deflate.BType_3; + return E_Deflate.BType_3 case: // log.debugf("Err: %v | Final: %v | Type: %v\n", err, final, type); if type == 1 { // Use fixed code lengths. - build_huffman(z_repeat, Z_FIXED_LENGTH[:]) or_return; - build_huffman(z_offset, Z_FIXED_DIST[:]) or_return; + build_huffman(z_repeat, Z_FIXED_LENGTH[:]) or_return + build_huffman(z_offset, Z_FIXED_DIST[:]) or_return } else { - lencodes: [286+32+137]u8; - codelength_sizes: [19]u8; + lencodes: [286+32+137]u8 + codelength_sizes: [19]u8 //i: u32; - n: u32; + n: u32 - compress.refill_lsb(z, 14); - hlit := compress.read_bits_no_refill_lsb(z, 5) + 257; - hdist := compress.read_bits_no_refill_lsb(z, 5) + 1; - hclen := compress.read_bits_no_refill_lsb(z, 4) + 4; - ntot := hlit + hdist; + compress.refill_lsb(z, 14) + hlit := compress.read_bits_no_refill_lsb(z, 5) + 257 + hdist := compress.read_bits_no_refill_lsb(z, 5) + 1 + hclen := compress.read_bits_no_refill_lsb(z, 4) + 4 + ntot := hlit + hdist #no_bounds_check for i in 0..<hclen { - s := compress.read_bits_lsb(z, 3); - codelength_sizes[Z_LENGTH_DEZIGZAG[i]] = u8(s); + s := compress.read_bits_lsb(z, 3) + codelength_sizes[Z_LENGTH_DEZIGZAG[i]] = u8(s) } - build_huffman(codelength_ht, codelength_sizes[:]) or_return; + build_huffman(codelength_ht, codelength_sizes[:]) or_return - n = 0; - c: u16; + n = 0 + c: u16 for n < ntot { - c = decode_huffman(z, codelength_ht) or_return; + c = decode_huffman(z, codelength_ht) or_return if c < 0 || c >= 19 { - return E_Deflate.Huffman_Bad_Code_Lengths; + return E_Deflate.Huffman_Bad_Code_Lengths } if c < 16 { - lencodes[n] = u8(c); - n += 1; + lencodes[n] = u8(c) + n += 1 } else { - fill := u8(0); - compress.refill_lsb(z, 7); + fill := u8(0) + compress.refill_lsb(z, 7) switch c { case 16: - c = u16(compress.read_bits_no_refill_lsb(z, 2) + 3); + c = u16(compress.read_bits_no_refill_lsb(z, 2) + 3) if n == 0 { - return E_Deflate.Huffman_Bad_Code_Lengths; + return E_Deflate.Huffman_Bad_Code_Lengths } - fill = lencodes[n - 1]; + fill = lencodes[n - 1] case 17: - c = u16(compress.read_bits_no_refill_lsb(z, 3) + 3); + c = u16(compress.read_bits_no_refill_lsb(z, 3) + 3) case 18: - c = u16(compress.read_bits_no_refill_lsb(z, 7) + 11); + c = u16(compress.read_bits_no_refill_lsb(z, 7) + 11) case: - return E_Deflate.Huffman_Bad_Code_Lengths; + return E_Deflate.Huffman_Bad_Code_Lengths } if ntot - n < u32(c) { - return E_Deflate.Huffman_Bad_Code_Lengths; + return E_Deflate.Huffman_Bad_Code_Lengths } - nc := n + u32(c); + nc := n + u32(c) #no_bounds_check for ; n < nc; n += 1 { - lencodes[n] = fill; + lencodes[n] = fill } } } if n != ntot { - return E_Deflate.Huffman_Bad_Code_Lengths; + return E_Deflate.Huffman_Bad_Code_Lengths } - build_huffman(z_repeat, lencodes[:hlit]) or_return; - build_huffman(z_offset, lencodes[hlit:ntot]) or_return; + build_huffman(z_repeat, lencodes[:hlit]) or_return + build_huffman(z_offset, lencodes[hlit:ntot]) or_return } - parse_huffman_block(z, z_repeat, z_offset) or_return; + parse_huffman_block(z, z_repeat, z_offset) or_return } if final == 1 { - break; + break } } if int(z.bytes_written) != len(z.output.buf) { - resize(&z.output.buf, int(z.bytes_written)); + resize(&z.output.buf, int(z.bytes_written)) } - return nil; + return nil } inflate_from_byte_array :: proc(input: []u8, buf: ^bytes.Buffer, raw := false, expected_output_size := -1) -> (err: Error) { - ctx := compress.Context_Memory_Input{}; + ctx := compress.Context_Memory_Input{} - ctx.input_data = input; - ctx.output = buf; + ctx.input_data = input + ctx.output = buf - return inflate_from_context(ctx=&ctx, raw=raw, expected_output_size=expected_output_size); + return inflate_from_context(ctx=&ctx, raw=raw, expected_output_size=expected_output_size) } inflate_from_byte_array_raw :: proc(input: []u8, buf: ^bytes.Buffer, raw := false, expected_output_size := -1) -> (err: Error) { - ctx := compress.Context_Memory_Input{}; + ctx := compress.Context_Memory_Input{} - ctx.input_data = input; - ctx.output = buf; + ctx.input_data = input + ctx.output = buf - return inflate_raw(z=&ctx, expected_output_size=expected_output_size); + return inflate_raw(z=&ctx, expected_output_size=expected_output_size) } inflate :: proc{inflate_from_context, inflate_from_byte_array};
\ No newline at end of file diff --git a/core/container/array.odin b/core/container/array.odin index 74dcd847f..2d5a64ec3 100644 --- a/core/container/array.odin +++ b/core/container/array.odin @@ -10,7 +10,7 @@ Array :: struct($T: typeid) { allocator: mem.Allocator, } -ARRAY_DEFAULT_CAPACITY :: 16; +ARRAY_DEFAULT_CAPACITY :: 16 /* array_init :: proc { @@ -46,171 +46,171 @@ array_grow array_init_none :: proc(a: ^$A/Array, allocator := context.allocator) { - array_init_len_cap(a, 0, ARRAY_DEFAULT_CAPACITY, allocator); + array_init_len_cap(a, 0, ARRAY_DEFAULT_CAPACITY, allocator) } array_init_len :: proc(a: ^$A/Array, len: int, allocator := context.allocator) { - array_init_len_cap(a, len, len, allocator); + array_init_len_cap(a, len, len, allocator) } array_init_len_cap :: proc(a: ^$A/Array($T), len: int, cap: int, allocator := context.allocator) { - a.allocator = allocator; - a.data = (^T)(mem.alloc(size_of(T)*cap, align_of(T), a.allocator)); - a.len = len; - a.cap = cap; + a.allocator = allocator + a.data = (^T)(mem.alloc(size_of(T)*cap, align_of(T), a.allocator)) + a.len = len + a.cap = cap } -array_init :: proc{array_init_none, array_init_len, array_init_len_cap}; +array_init :: proc{array_init_none, array_init_len, array_init_len_cap} array_delete :: proc(a: $A/Array) { - mem.free(a.data, a.allocator); + mem.free(a.data, a.allocator) } array_len :: proc(a: $A/Array) -> int { - return a.len; + return a.len } array_cap :: proc(a: $A/Array) -> int { - return a.cap; + return a.cap } array_space :: proc(a: $A/Array) -> int { - return a.cap - a.len; + return a.cap - a.len } array_slice :: proc(a: $A/Array($T)) -> []T { - s := mem.Raw_Slice{a.data, a.len}; - return transmute([]T)s; + s := mem.Raw_Slice{a.data, a.len} + return transmute([]T)s } array_cap_slice :: proc(a: $A/Array($T)) -> []T { - s := mem.Raw_Slice{a.data, a.cap}; - return transmute([]T)s; + s := mem.Raw_Slice{a.data, a.cap} + return transmute([]T)s } array_get :: proc(a: $A/Array($T), index: int, loc := #caller_location) -> T { - runtime.bounds_check_error_loc(loc, index, array_len(a)); - return (^T)(uintptr(a.data) + size_of(T)*uintptr(index))^; + runtime.bounds_check_error_loc(loc, index, array_len(a)) + return (^T)(uintptr(a.data) + size_of(T)*uintptr(index))^ } array_get_ptr :: proc(a: $A/Array($T), index: int, loc := #caller_location) -> ^T { - runtime.bounds_check_error_loc(loc, index, array_len(a)); - return (^T)(uintptr(a.data) + size_of(T)*uintptr(index)); + runtime.bounds_check_error_loc(loc, index, array_len(a)) + return (^T)(uintptr(a.data) + size_of(T)*uintptr(index)) } array_set :: proc(a: ^$A/Array($T), index: int, item: T, loc := #caller_location) { - runtime.bounds_check_error_loc(loc, index, array_len(a^)); - (^T)(uintptr(a.data) + size_of(T)*uintptr(index))^ = item; + runtime.bounds_check_error_loc(loc, index, array_len(a^)) + (^T)(uintptr(a.data) + size_of(T)*uintptr(index))^ = item } array_reserve :: proc(a: ^$A/Array, capacity: int) { if capacity > a.len { - array_set_capacity(a, capacity); + array_set_capacity(a, capacity) } } array_resize :: proc(a: ^$A/Array, length: int) { if length > a.len { - array_set_capacity(a, length); + array_set_capacity(a, length) } - a.len = length; + a.len = length } array_push_back :: proc(a: ^$A/Array($T), item: T) { if array_space(a^) == 0 { - array_grow(a); + array_grow(a) } - a.len += 1; - array_set(a, a.len-1, item); + a.len += 1 + array_set(a, a.len-1, item) } array_push_front :: proc(a: ^$A/Array($T), item: T) { if array_space(a^) == 0 { - array_grow(a); + array_grow(a) } - a.len += 1; - data := array_slice(a^); - copy(data[1:], data[:]); - data[0] = item; + a.len += 1 + data := array_slice(a^) + copy(data[1:], data[:]) + data[0] = item } array_pop_back :: proc(a: ^$A/Array($T), loc := #caller_location) -> T { - assert(condition=a.len > 0, loc=loc); - item := array_get(a^, a.len-1); - a.len -= 1; - return item; + assert(condition=a.len > 0, loc=loc) + item := array_get(a^, a.len-1) + a.len -= 1 + return item } array_pop_front :: proc(a: ^$A/Array($T), loc := #caller_location) -> T { - assert(condition=a.len > 0, loc=loc); - item := array_get(a^, 0); - s := array_slice(a^); - copy(s[:], s[1:]); - a.len -= 1; - return item; + assert(condition=a.len > 0, loc=loc) + item := array_get(a^, 0) + s := array_slice(a^) + copy(s[:], s[1:]) + a.len -= 1 + return item } array_consume :: proc(a: ^$A/Array($T), count: int, loc := #caller_location) { - assert(condition=a.len >= count, loc=loc); - a.len -= count; + assert(condition=a.len >= count, loc=loc) + a.len -= count } array_trim :: proc(a: ^$A/Array($T)) { - array_set_capacity(a, a.len); + array_set_capacity(a, a.len) } array_clear :: proc(a: ^$A/Array($T)) { - array_resize(a, 0); + array_resize(a, 0) } array_clone :: proc(a: $A/Array($T), allocator := context.allocator) -> A { - res: A; - array_init(&res, array_len(a), array_len(a), allocator); - copy(array_slice(res), array_slice(a)); - return res; + res: A + array_init(&res, array_len(a), array_len(a), allocator) + copy(array_slice(res), array_slice(a)) + return res } array_push_back_elems :: proc(a: ^$A/Array($T), items: ..T) { if array_space(a^) < len(items) { - array_grow(a, a.len + len(items)); + array_grow(a, a.len + len(items)) } - offset := a.len; - data := array_cap_slice(a^); - n := copy(data[a.len:], items); - a.len += n; + offset := a.len + data := array_cap_slice(a^) + n := copy(data[a.len:], items) + a.len += n } -array_push :: proc{array_push_back, array_push_back_elems}; -array_append :: proc{array_push_back, array_push_back_elems}; +array_push :: proc{array_push_back, array_push_back_elems} +array_append :: proc{array_push_back, array_push_back_elems} array_set_capacity :: proc(a: ^$A/Array($T), new_capacity: int) { if new_capacity == a.cap { - return; + return } if new_capacity < a.len { - array_resize(a, new_capacity); + array_resize(a, new_capacity) } - new_data: ^T; + new_data: ^T if new_capacity > 0 { if a.allocator.procedure == nil { - a.allocator = context.allocator; + a.allocator = context.allocator } - new_data = (^T)(mem.alloc(size_of(T)*new_capacity, align_of(T), a.allocator)); + new_data = (^T)(mem.alloc(size_of(T)*new_capacity, align_of(T), a.allocator)) if new_data != nil { - mem.copy(new_data, a.data, size_of(T)*a.len); + mem.copy(new_data, a.data, size_of(T)*a.len) } } - mem.free(a.data, a.allocator); - a.data = new_data; - a.cap = new_capacity; + mem.free(a.data, a.allocator) + a.data = new_data + a.cap = new_capacity } array_grow :: proc(a: ^$A/Array, min_capacity: int = 0) { - new_capacity := max(array_len(a^)*2 + 8, min_capacity); - array_set_capacity(a, new_capacity); + new_capacity := max(array_len(a^)*2 + 8, min_capacity) + array_set_capacity(a, new_capacity) } diff --git a/core/container/bloom_filter.odin b/core/container/bloom_filter.odin index 2a93c3b66..8af7aeb85 100644 --- a/core/container/bloom_filter.odin +++ b/core/container/bloom_filter.odin @@ -2,7 +2,7 @@ package container import "core:mem" -Bloom_Hash_Proc :: #type proc(data: []byte) -> u32; +Bloom_Hash_Proc :: #type proc(data: []byte) -> u32 Bloom_Hash :: struct { hash_proc: Bloom_Hash_Proc, @@ -16,65 +16,65 @@ Bloom_Filter :: struct { } bloom_filter_init :: proc(b: ^Bloom_Filter, size: int, allocator := context.allocator) { - b.allocator = allocator; - b.bits = make([]byte, size, allocator); + b.allocator = allocator + b.bits = make([]byte, size, allocator) } bloom_filter_destroy :: proc(b: ^Bloom_Filter) { - context.allocator = b.allocator; - delete(b.bits); + context.allocator = b.allocator + delete(b.bits) for b.hash != nil { - hash := b.hash; - b.hash = b.hash.next; - free(hash); + hash := b.hash + b.hash = b.hash.next + free(hash) } } bloom_filter_add_hash_proc :: proc(b: ^Bloom_Filter, hash_proc: Bloom_Hash_Proc) { - context.allocator = b.allocator; - h := new(Bloom_Hash); - h.hash_proc = hash_proc; + context.allocator = b.allocator + h := new(Bloom_Hash) + h.hash_proc = hash_proc - head := &b.hash; + head := &b.hash for head^ != nil { - head = &(head^.next); + head = &(head^.next) } - head^ = h; + head^ = h } bloom_filter_add :: proc(b: ^Bloom_Filter, item: []byte) { #no_bounds_check for h := b.hash; h != nil; h = h.next { - hash := h.hash_proc(item); - hash %= u32(len(b.bits) * 8); - b.bits[hash >> 3] |= 1 << (hash & 3); + hash := h.hash_proc(item) + hash %= u32(len(b.bits) * 8) + b.bits[hash >> 3] |= 1 << (hash & 3) } } bloom_filter_add_string :: proc(b: ^Bloom_Filter, item: string) { - bloom_filter_add(b, transmute([]byte)item); + bloom_filter_add(b, transmute([]byte)item) } bloom_filter_add_raw :: proc(b: ^Bloom_Filter, data: rawptr, size: int) { - item := mem.slice_ptr((^byte)(data), size); - bloom_filter_add(b, item); + item := mem.slice_ptr((^byte)(data), size) + bloom_filter_add(b, item) } bloom_filter_test :: proc(b: ^Bloom_Filter, item: []byte) -> bool { #no_bounds_check for h := b.hash; h != nil; h = h.next { - hash := h.hash_proc(item); - hash %= u32(len(b.bits) * 8); + hash := h.hash_proc(item) + hash %= u32(len(b.bits) * 8) if (b.bits[hash >> 3] & (1 << (hash & 3)) == 0) { - return false; + return false } } - return true; + return true } bloom_filter_test_string :: proc(b: ^Bloom_Filter, item: string) -> bool { - return bloom_filter_test(b, transmute([]byte)item); + return bloom_filter_test(b, transmute([]byte)item) } bloom_filter_test_raw :: proc(b: ^Bloom_Filter, data: rawptr, size: int) -> bool { - item := mem.slice_ptr((^byte)(data), size); - return bloom_filter_test(b, item); + item := mem.slice_ptr((^byte)(data), size) + return bloom_filter_test(b, item) } diff --git a/core/container/map.odin b/core/container/map.odin index c8d2bf996..54cbc22fc 100644 --- a/core/container/map.odin +++ b/core/container/map.odin @@ -1,7 +1,7 @@ package container import "core:intrinsics" -_ :: intrinsics; +_ :: intrinsics Map :: struct($Key, $Value: typeid) where intrinsics.type_is_valid_map_key(Key) { @@ -49,187 +49,187 @@ multi_map_remove_all */ -map_init :: proc{map_init_none, map_init_cap}; +map_init :: proc{map_init_none, map_init_cap} map_init_none :: proc(m: ^$M/Map($Key, $Value), allocator := context.allocator) { - m.hash.allocator = allocator; - m.entries.allocator = allocator; + m.hash.allocator = allocator + m.entries.allocator = allocator } map_init_cap :: proc(m: ^$M/Map($Key, $Value), cap: int, allocator := context.allocator) { - m.hash.allocator = allocator; - m.entries.allocator = allocator; - map_reserve(m, cap); + m.hash.allocator = allocator + m.entries.allocator = allocator + map_reserve(m, cap) } map_delete :: proc(m: $M/Map($Key, $Value)) { - array_delete(m.hash); - array_delete(m.entries); + array_delete(m.hash) + array_delete(m.entries) } map_has :: proc(m: $M/Map($Key, $Value), key: Key) -> bool { - return _map_find_or_fail(m, key) >= 0; + return _map_find_or_fail(m, key) >= 0 } map_get :: proc(m: $M/Map($Key, $Value), key: Key) -> (res: Value, ok: bool) #optional_ok { - i := _map_find_or_fail(m, key); + i := _map_find_or_fail(m, key) if i < 0 { - return {}, false; + return {}, false } - return array_get(m.entries, i).value, true; + return array_get(m.entries, i).value, true } map_get_default :: proc(m: $M/Map($Key, $Value), key: Key, default: Value) -> (res: Value, ok: bool) #optional_ok { - i := _map_find_or_fail(m, key); + i := _map_find_or_fail(m, key) if i < 0 { - return default, false; + return default, false } - return array_get(m.entries, i).value, true; + return array_get(m.entries, i).value, true } map_get_ptr :: proc(m: $M/Map($Key, $Value), key: Key) -> ^Value { - i := _map_find_or_fail(m, key); + i := _map_find_or_fail(m, key) if i < 0 { - return nil; + return nil } - return array_get_ptr(m.entries, i).value; + return array_get_ptr(m.entries, i).value } map_set :: proc(m: ^$M/Map($Key, $Value), key: Key, value: Value) { if array_len(m.hash) == 0 { - _map_grow(m); + _map_grow(m) } - i := _map_find_or_make(m, key); - array_get_ptr(m.entries, i).value = value; + i := _map_find_or_make(m, key) + array_get_ptr(m.entries, i).value = value if _map_full(m^) { - _map_grow(m); + _map_grow(m) } } map_remove :: proc(m: ^$M/Map($Key, $Value), key: Key) { - fr := _map_find_key(m^, key); + fr := _map_find_key(m^, key) if fr.entry_index >= 0 { - _map_erase(m, fr); + _map_erase(m, fr) } } map_reserve :: proc(m: ^$M/Map($Key, $Value), new_size: int) { - nm: M; - map_init(&nm, m.hash.allocator); - array_resize(&nm.hash, new_size); - array_reserve(&nm.entries, array_len(m.entries)); + nm: M + map_init(&nm, m.hash.allocator) + array_resize(&nm.hash, new_size) + array_reserve(&nm.entries, array_len(m.entries)) for i in 0..<new_size { - array_set(&nm.hash, i, -1); + array_set(&nm.hash, i, -1) } for i in 0..<array_len(m.entries) { - e := array_get(m.entries, i); - multi_map_insert(&nm, e.key, e.value); + e := array_get(m.entries, i) + multi_map_insert(&nm, e.key, e.value) } - map_delete(m^); - m^ = nm; + map_delete(m^) + m^ = nm } map_clear :: proc(m: ^$M/Map($Key, $Value)) { - array_clear(&m.hash); - array_clear(&m.entries); + array_clear(&m.hash) + array_clear(&m.entries) } multi_map_find_first :: proc(m: $M/Map($Key, $Value), key: Key) -> ^Map_Entry(Key, Value) { - i := _map_find_or_fail(m, key); + i := _map_find_or_fail(m, key) if i < 0 { - return nil; + return nil } - return array_get_ptr(m.entries, i); + return array_get_ptr(m.entries, i) } multi_map_find_next :: proc(m: $M/Map($Key, $Value), e: ^Map_Entry(Key, Value)) -> ^Map_Entry(Key, Value) { - i := e.next; + i := e.next for i >= 0 { - it := array_get_ptr(m.entries, i); + it := array_get_ptr(m.entries, i) if it.hash == e.hash && it.key == e.key { - return it; + return it } - i = it.next; + i = it.next } - return nil; + return nil } multi_map_count :: proc(m: $M/Map($Key, $Value), key: Key) -> int { - n := 0; - e := multi_map_find_first(m, key); + n := 0 + e := multi_map_find_first(m, key) for e != nil { - n += 1; - e = multi_map_find_next(m, e); + n += 1 + e = multi_map_find_next(m, e) } - return n; + return n } -multi_map_get :: proc{multi_map_get_array, multi_map_get_slice}; +multi_map_get :: proc{multi_map_get_array, multi_map_get_slice} multi_map_get_array :: proc(m: $M/Map($Key, $Value), key: Key, items: ^Array(Value)) { if items == nil { - return; + return } - e := multi_map_find_first(m, key); + e := multi_map_find_first(m, key) for e != nil { - array_append(items, e.value); - e = multi_map_find_next(m, e); + array_append(items, e.value) + e = multi_map_find_next(m, e) } } multi_map_get_slice :: proc(m: $M/Map($Key, $Value), key: Key, items: []Value) { - e := multi_map_find_first(m, key); - i := 0; + e := multi_map_find_first(m, key) + i := 0 for e != nil && i < len(items) { - items[i] = e.value; - i += 1; - e = multi_map_find_next(m, e); + items[i] = e.value + i += 1 + e = multi_map_find_next(m, e) } } multi_map_get_as_slice :: proc(m: $M/Map($Key, $Value), key: Key) -> []Value { - items: Array(Value); - array_init(&items, 0); + items: Array(Value) + array_init(&items, 0) - e := multi_map_find_first(m, key); + e := multi_map_find_first(m, key) for e != nil { - array_append(&items, e.value); - e = multi_map_find_next(m, e); + array_append(&items, e.value) + e = multi_map_find_next(m, e) } - return array_slice(items); + return array_slice(items) } multi_map_insert :: proc(m: ^$M/Map($Key, $Value), key: Key, value: Value) { if array_len(m.hash) == 0 { - _map_grow(m); + _map_grow(m) } - i := _map_make(m, key); - array_get_ptr(m.entries, i).value = value; + i := _map_make(m, key) + array_get_ptr(m.entries, i).value = value if _map_full(m^) { - _map_grow(m); + _map_grow(m) } } multi_map_remove :: proc(m: ^$M/Map($Key, $Value), e: ^Map_Entry(Key, Value)) { - fr := _map_find_entry(m, e); + fr := _map_find_entry(m, e) if fr.entry_index >= 0 { - _map_erase(m, fr); + _map_erase(m, fr) } } multi_map_remove_all :: proc(m: ^$M/Map($Key, $Value), key: Key) { for map_exist(m^, key) { - map_remove(m, key); + map_remove(m, key) } } @@ -244,134 +244,134 @@ Map_Find_Result :: struct { } _map_add_entry :: proc(m: ^$M/Map($Key, $Value), key: Key) -> int where intrinsics.type_is_valid_map_key(Key) { - hasher := intrinsics.type_hasher_proc(Key); + hasher := intrinsics.type_hasher_proc(Key) - e: Map_Entry(Key, Value); - e.key = key; - e.hash = hasher(&e.key, 0); - e.next = -1; - idx := array_len(m.entries); - array_push(&m.entries, e); - return idx; + e: Map_Entry(Key, Value) + e.key = key + e.hash = hasher(&e.key, 0) + e.next = -1 + idx := array_len(m.entries) + array_push(&m.entries, e) + return idx } _map_erase :: proc(m: ^$M/Map, fr: Map_Find_Result) { if fr.entry_prev < 0 { - array_set(&m.hash, fr.hash_index, array_get(m.entries, fr.entry_index).next); + array_set(&m.hash, fr.hash_index, array_get(m.entries, fr.entry_index).next) } else { - array_get_ptr(m.entries, fr.entry_prev).next = array_get(m.entries, fr.entry_index).next; + array_get_ptr(m.entries, fr.entry_prev).next = array_get(m.entries, fr.entry_index).next } if fr.entry_index == array_len(m.entries)-1 { - array_pop_back(&m.entries); - return; + array_pop_back(&m.entries) + return } - array_set(&m.entries, fr.entry_index, array_get(m.entries, array_len(m.entries)-1)); - last := _map_find_key(m^, array_get(m.entries, fr.entry_index).key); + array_set(&m.entries, fr.entry_index, array_get(m.entries, array_len(m.entries)-1)) + last := _map_find_key(m^, array_get(m.entries, fr.entry_index).key) if last.entry_prev < 0 { - array_get_ptr(m.entries, last.entry_prev).next = fr.entry_index; + array_get_ptr(m.entries, last.entry_prev).next = fr.entry_index } else { - array_set(&m.hash, last.hash_index, fr.entry_index); + array_set(&m.hash, last.hash_index, fr.entry_index) } } _map_find_key :: proc(m: $M/Map($Key, $Value), key: Key) -> Map_Find_Result where intrinsics.type_is_valid_map_key(Key) { - fr: Map_Find_Result; - fr.hash_index = -1; - fr.entry_prev = -1; - fr.entry_index = -1; + fr: Map_Find_Result + fr.hash_index = -1 + fr.entry_prev = -1 + fr.entry_index = -1 if array_len(m.hash) == 0 { - return fr; + return fr } - hasher := intrinsics.type_hasher_proc(Key); + hasher := intrinsics.type_hasher_proc(Key) - key := key; - hash := hasher(&key, 0); + key := key + hash := hasher(&key, 0) - fr.hash_index = int(hash % uintptr(array_len(m.hash))); - fr.entry_index = array_get(m.hash, fr.hash_index); + fr.hash_index = int(hash % uintptr(array_len(m.hash))) + fr.entry_index = array_get(m.hash, fr.hash_index) for fr.entry_index >= 0 { - it := array_get_ptr(m.entries, fr.entry_index); + it := array_get_ptr(m.entries, fr.entry_index) if it.hash == hash && it.key == key { - return fr; + return fr } - fr.entry_prev = fr.entry_index; - fr.entry_index = it.next; + fr.entry_prev = fr.entry_index + fr.entry_index = it.next } - return fr; + return fr } _map_find_entry :: proc(m: ^$M/Map($Key, $Value), e: ^Map_Entry(Key, Value)) -> Map_Find_Result { - fr: Map_Find_Result; - fr.hash_index = -1; - fr.entry_prev = -1; - fr.entry_index = -1; + fr: Map_Find_Result + fr.hash_index = -1 + fr.entry_prev = -1 + fr.entry_index = -1 if array_len(m.hash) == 0 { - return fr; + return fr } - fr.hash_index = int(e.hash % uintptr(array_len(m.hash))); - fr.entry_index = array_get(m.hash, fr.hash_index); + fr.hash_index = int(e.hash % uintptr(array_len(m.hash))) + fr.entry_index = array_get(m.hash, fr.hash_index) for fr.entry_index >= 0 { - it := array_get_ptr(m.entries, fr.entry_index); + it := array_get_ptr(m.entries, fr.entry_index) if it == e { - return fr; + return fr } - fr.entry_prev = fr.entry_index; - fr.entry_index = it.next; + fr.entry_prev = fr.entry_index + fr.entry_index = it.next } - return fr; + return fr } _map_find_or_fail :: proc(m: $M/Map($Key, $Value), key: Key) -> int { - return _map_find_key(m, key).entry_index; + return _map_find_key(m, key).entry_index } _map_find_or_make :: proc(m: ^$M/Map($Key, $Value), key: Key) -> int { - fr := _map_find_key(m^, key); + fr := _map_find_key(m^, key) if fr.entry_index >= 0 { - return fr.entry_index; + return fr.entry_index } - i := _map_add_entry(m, key); + i := _map_add_entry(m, key) if fr.entry_prev < 0 { - array_set(&m.hash, fr.hash_index, i); + array_set(&m.hash, fr.hash_index, i) } else { - array_get_ptr(m.entries, fr.entry_prev).next = i; + array_get_ptr(m.entries, fr.entry_prev).next = i } - return i; + return i } _map_make :: proc(m: ^$M/Map($Key, $Value), key: Key) -> int { - fr := _map_find_key(m^, key); - i := _map_add_entry(m, key); + fr := _map_find_key(m^, key) + i := _map_add_entry(m, key) if fr.entry_prev < 0 { - array_set(&m.hash, fr.hash_index, i); + array_set(&m.hash, fr.hash_index, i) } else { - array_get_ptr(m.entries, fr.entry_prev).next = i; + array_get_ptr(m.entries, fr.entry_prev).next = i } - array_get_ptr(m.entries, i).next = fr.entry_index; + array_get_ptr(m.entries, i).next = fr.entry_index - return i; + return i } _map_full :: proc(m: $M/Map($Key, $Value)) -> bool { // TODO(bill): Determine good max load factor - return array_len(m.entries) >= (array_len(m.hash) / 4)*3; + return array_len(m.entries) >= (array_len(m.hash) / 4)*3 } _map_grow :: proc(m: ^$M/Map($Key, $Value)) { - new_size := array_len(m.entries) * 4 + 7; // TODO(bill): Determine good grow rate - map_reserve(m, new_size); + new_size := array_len(m.entries) * 4 + 7 // TODO(bill): Determine good grow rate + map_reserve(m, new_size) } diff --git a/core/container/priority_queue.odin b/core/container/priority_queue.odin index f1ceac3a4..e5bbe85c7 100644 --- a/core/container/priority_queue.odin +++ b/core/container/priority_queue.odin @@ -7,107 +7,107 @@ Priority_Queue :: struct($T: typeid) { } priority_queue_init_none :: proc(q: ^$Q/Priority_Queue($T), f: proc(item: T) -> int, allocator := context.allocator) { - queue_init_len(q, f, 0, allocator); + queue_init_len(q, f, 0, allocator) } priority_queue_init_len :: proc(q: ^$Q/Priority_Queue($T), f: proc(item: T) -> int, len: int, allocator := context.allocator) { - queue_init_len_cap(q, f, 0, 16, allocator); + queue_init_len_cap(q, f, 0, 16, allocator) } priority_queue_init_len_cap :: proc(q: ^$Q/Priority_Queue($T), f: proc(item: T) -> int, len: int, cap: int, allocator := context.allocator) { - array_init(&q.data, len, cap, allocator); - q.len = len; - q.priority = f; + array_init(&q.data, len, cap, allocator) + q.len = len + q.priority = f } -priority_queue_init :: proc{priority_queue_init_none, priority_queue_init_len, priority_queue_init_len_cap}; +priority_queue_init :: proc{priority_queue_init_none, priority_queue_init_len, priority_queue_init_len_cap} priority_queue_delete :: proc(q: $Q/Priority_Queue($T)) { - array_delete(q.data); + array_delete(q.data) } priority_queue_clear :: proc(q: ^$Q/Priority_Queue($T)) { - q.len = 0; + q.len = 0 } priority_queue_len :: proc(q: $Q/Priority_Queue($T)) -> int { - return q.len; + return q.len } priority_queue_cap :: proc(q: $Q/Priority_Queue($T)) -> int { - return array_cap(q.data); + return array_cap(q.data) } priority_queue_space :: proc(q: $Q/Priority_Queue($T)) -> int { - return array_len(q.data) - q.len; + return array_len(q.data) - q.len } priority_queue_reserve :: proc(q: ^$Q/Priority_Queue($T), capacity: int) { if capacity > q.len { - array_resize(&q.data, new_capacity); + array_resize(&q.data, new_capacity) } } priority_queue_resize :: proc(q: ^$Q/Priority_Queue($T), length: int) { if length > q.len { - array_resize(&q.data, new_capacity); + array_resize(&q.data, new_capacity) } - q.len = length; + q.len = length } _priority_queue_grow :: proc(q: ^$Q/Priority_Queue($T), min_capacity: int = 0) { - new_capacity := max(array_len(q.data)*2 + 8, min_capacity); - array_resize(&q.data, new_capacity); + new_capacity := max(array_len(q.data)*2 + 8, min_capacity) + array_resize(&q.data, new_capacity) } priority_queue_push :: proc(q: ^$Q/Priority_Queue($T), item: T) { if array_len(q.data) - q.len == 0 { - _priority_queue_grow(q); + _priority_queue_grow(q) } - s := array_slice(q.data); - s[q.len] = item; + s := array_slice(q.data) + s[q.len] = item - i := q.len; + i := q.len for i > 0 { - p := (i - 1) / 2; - if q.priority(s[p]) <= q.priority(item) do break; - s[i] = s[p]; - i = p; + p := (i - 1) / 2 + if q.priority(s[p]) <= q.priority(item) do break + s[i] = s[p] + i = p } - q.len += 1; - if q.len > 0 do s[i] = item; + q.len += 1 + if q.len > 0 do s[i] = item } priority_queue_pop :: proc(q: ^$Q/Priority_Queue($T)) -> T { - assert(q.len > 0); + assert(q.len > 0) - s := array_slice(q.data); - min := s[0]; - root := s[q.len-1]; - q.len -= 1; + s := array_slice(q.data) + min := s[0] + root := s[q.len-1] + q.len -= 1 - i := 0; + i := 0 for i * 2 + 1 < q.len { - a := i * 2 + 1; - b := i * 2 + 2; - c := b < q.len && q.priority(s[b]) < q.priority(s[a]) ? b : a; + a := i * 2 + 1 + b := i * 2 + 2 + c := b < q.len && q.priority(s[b]) < q.priority(s[a]) ? b : a - if q.priority(s[c]) >= q.priority(root) do break; - s[i] = s[c]; - i = c; + if q.priority(s[c]) >= q.priority(root) do break + s[i] = s[c] + i = c } - if q.len > 0 do s[i] = root; - return min; + if q.len > 0 do s[i] = root + return min } priority_queue_peek :: proc(q: ^$Q/Priority_Queue($T)) -> T { - assert(q.len > 0); + assert(q.len > 0) - s := array_slice(q.data); - return s[0]; + s := array_slice(q.data) + return s[0] } diff --git a/core/container/queue.odin b/core/container/queue.odin index b4ca0ae8f..bab4a18e6 100644 --- a/core/container/queue.odin +++ b/core/container/queue.odin @@ -32,144 +32,144 @@ queue_consume */ queue_init_none :: proc(q: ^$Q/Queue($T), allocator := context.allocator) { - queue_init_len(q, 0, allocator); + queue_init_len(q, 0, allocator) } queue_init_len :: proc(q: ^$Q/Queue($T), len: int, allocator := context.allocator) { - queue_init_len_cap(q, 0, 16, allocator); + queue_init_len_cap(q, 0, 16, allocator) } queue_init_len_cap :: proc(q: ^$Q/Queue($T), len: int, cap: int, allocator := context.allocator) { - array_init(&q.data, len, cap, allocator); - q.len = len; - q.offset = 0; + array_init(&q.data, len, cap, allocator) + q.len = len + q.offset = 0 } -queue_init :: proc{queue_init_none, queue_init_len, queue_init_len_cap}; +queue_init :: proc{queue_init_none, queue_init_len, queue_init_len_cap} queue_delete :: proc(q: $Q/Queue($T)) { - array_delete(q.data); + array_delete(q.data) } queue_clear :: proc(q: ^$Q/Queue($T)) { - q.len = 0; + q.len = 0 } queue_len :: proc(q: $Q/Queue($T)) -> int { - return q.len; + return q.len } queue_cap :: proc(q: $Q/Queue($T)) -> int { - return array_cap(q.data); + return array_cap(q.data) } queue_space :: proc(q: $Q/Queue($T)) -> int { - return array_len(q.data) - q.len; + return array_len(q.data) - q.len } queue_get :: proc(q: $Q/Queue($T), index: int) -> T { - i := (index + q.offset) % array_len(q.data); - data := array_slice(q.data); - return data[i]; + i := (index + q.offset) % array_len(q.data) + data := array_slice(q.data) + return data[i] } queue_set :: proc(q: ^$Q/Queue($T), index: int, item: T) { - i := (index + q.offset) % array_len(q.data); - data := array_slice(q.data); - data[i] = item; + i := (index + q.offset) % array_len(q.data) + data := array_slice(q.data) + data[i] = item } queue_reserve :: proc(q: ^$Q/Queue($T), capacity: int) { if capacity > q.len { - _queue_increase_capacity(q, capacity); + _queue_increase_capacity(q, capacity) } } queue_resize :: proc(q: ^$Q/Queue($T), length: int) { if length > q.len { - _queue_increase_capacity(q, length); + _queue_increase_capacity(q, length) } - q.len = length; + q.len = length } queue_push_back :: proc(q: ^$Q/Queue($T), item: T) { if queue_space(q^) == 0 { - _queue_grow(q); + _queue_grow(q) } - queue_set(q, q.len, item); - q.len += 1; + queue_set(q, q.len, item) + q.len += 1 } queue_push_front :: proc(q: ^$Q/Queue($T), item: T) { if queue_space(q^) == 0 { - _queue_grow(q); + _queue_grow(q) } - q.offset = (q.offset - 1 + array_len(q.data)) % array_len(q.data); - q.len += 1; - queue_set(q, 0, item); + q.offset = (q.offset - 1 + array_len(q.data)) % array_len(q.data) + q.len += 1 + queue_set(q, 0, item) } queue_pop_front :: proc(q: ^$Q/Queue($T)) -> T { - assert(q.len > 0); - item := queue_get(q^, 0); - q.offset = (q.offset + 1) % array_len(q.data); - q.len -= 1; + assert(q.len > 0) + item := queue_get(q^, 0) + q.offset = (q.offset + 1) % array_len(q.data) + q.len -= 1 if q.len == 0 { - q.offset = 0; + q.offset = 0 } - return item; + return item } queue_pop_back :: proc(q: ^$Q/Queue($T)) -> T { - assert(q.len > 0); - item := queue_get(q^, q.len-1); - q.len -= 1; - return item; + assert(q.len > 0) + item := queue_get(q^, q.len-1) + q.len -= 1 + return item } queue_consume :: proc(q: ^$Q/Queue($T), count: int) { - q.offset = (q.offset + count) & array_len(q.data); - q.len -= count; + q.offset = (q.offset + count) & array_len(q.data) + q.len -= count } queue_push_elems :: proc(q: ^$Q/Queue($T), items: ..T) { if queue_space(q^) < len(items) { - _queue_grow(q, q.len + len(items)); + _queue_grow(q, q.len + len(items)) } - size := array_len(q.data); - insert := (q.offset + q.len) % size; + size := array_len(q.data) + insert := (q.offset + q.len) % size - to_insert := len(items); + to_insert := len(items) if insert + to_insert > size { - to_insert = size - insert; + to_insert = size - insert } - the_items := items[:]; + the_items := items[:] - data := array_slice(q.data); + data := array_slice(q.data) - q.len += copy(data[insert:][:to_insert], the_items); - the_items = the_items[to_insert:]; - q.len += copy(data[:], the_items); + q.len += copy(data[insert:][:to_insert], the_items) + the_items = the_items[to_insert:] + q.len += copy(data[:], the_items) } -queue_push :: proc{queue_push_back, queue_push_elems}; +queue_push :: proc{queue_push_back, queue_push_elems} _queue_increase_capacity :: proc(q: ^$Q/Queue($T), new_capacity: int) { - end := array_len(q.data); - array_resize(&q.data, new_capacity); + end := array_len(q.data) + array_resize(&q.data, new_capacity) if q.offset + q.len > end { - end_items := q.len + end; - data := array_slice(q.data); - copy(data[new_capacity-end_items:][:end_items], data[q.offset:][:end_items]); - q.offset += new_capacity - end; + end_items := q.len + end + data := array_slice(q.data) + copy(data[new_capacity-end_items:][:end_items], data[q.offset:][:end_items]) + q.offset += new_capacity - end } } _queue_grow :: proc(q: ^$Q/Queue($T), min_capacity: int = 0) { - new_capacity := max(array_len(q.data)*2 + 8, min_capacity); - _queue_increase_capacity(q, new_capacity); + new_capacity := max(array_len(q.data)*2 + 8, min_capacity) + _queue_increase_capacity(q, new_capacity) } diff --git a/core/container/ring.odin b/core/container/ring.odin index c1edc9dbc..61492ec84 100644 --- a/core/container/ring.odin +++ b/core/container/ring.odin @@ -7,68 +7,68 @@ Ring :: struct($T: typeid) { } ring_init :: proc(r: ^$R/Ring) -> ^R { - r.prev, r.next = r, r; - return r; + r.prev, r.next = r, r + return r } ring_next :: proc(r: ^$R/Ring) -> ^R { if r.next == nil { - return ring_init(r); + return ring_init(r) } - return r.next; + return r.next } ring_prev :: proc(r: ^$R/Ring) -> ^R { if r.prev == nil { - return ring_init(r); + return ring_init(r) } - return r.prev; + return r.prev } ring_move :: proc(r: ^$R/Ring, n: int) -> ^R { - r := r; + r := r if r.next == nil { - return ring_init(r); + return ring_init(r) } switch { case n < 0: for _ in n..<0 { - r = r.prev; + r = r.prev } case n > 0: for _ in 0..<n { - r = r.next; + r = r.next } } - return r; + return r } ring_link :: proc(r, s: ^$R/Ring) -> ^R { - n := ring_next(r); + n := ring_next(r) if s != nil { - p := ring_prev(s); - r.next = s; - s.prev = r; - n.prev = p; - p.next = n; + p := ring_prev(s) + r.next = s + s.prev = r + n.prev = p + p.next = n } - return n; + return n } ring_unlink :: proc(r: ^$R/Ring, n: int) -> ^R { if n <= 0 { - return nil; + return nil } - return ring_link(r, ring_move(r, n+1)); + return ring_link(r, ring_move(r, n+1)) } ring_len :: proc(r: ^$R/Ring) -> int { - n := 0; + n := 0 if r != nil { - n = 1; + n = 1 for p := ring_next(r); p != r; p = p.next { - n += 1; + n += 1 } } - return n; + return n } diff --git a/core/container/set.odin b/core/container/set.odin index 7ab67cf2e..562ac5409 100644 --- a/core/container/set.odin +++ b/core/container/set.odin @@ -26,88 +26,88 @@ set_reserve set_clear */ -set_init :: proc{set_init_none, set_init_cap}; +set_init :: proc{set_init_none, set_init_cap} set_init_none :: proc(m: ^Set, allocator := context.allocator) { - m.hash.allocator = allocator; - m.entries.allocator = allocator; + m.hash.allocator = allocator + m.entries.allocator = allocator } set_init_cap :: proc(m: ^Set, cap: int, allocator := context.allocator) { - m.hash.allocator = allocator; - m.entries.allocator = allocator; - set_reserve(m, cap); + m.hash.allocator = allocator + m.entries.allocator = allocator + set_reserve(m, cap) } set_delete :: proc(m: Set) { - array_delete(m.hash); - array_delete(m.entries); + array_delete(m.hash) + array_delete(m.entries) } set_in :: proc(m: Set, key: u64) -> bool { - return _set_find_or_fail(m, key) >= 0; + return _set_find_or_fail(m, key) >= 0 } set_not_in :: proc(m: Set, key: u64) -> bool { - return _set_find_or_fail(m, key) < 0; + return _set_find_or_fail(m, key) < 0 } set_add :: proc(m: ^Set, key: u64) { if array_len(m.hash) == 0 { - _set_grow(m); + _set_grow(m) } - _ = _set_find_or_make(m, key); + _ = _set_find_or_make(m, key) if _set_full(m^) { - _set_grow(m); + _set_grow(m) } } set_remove :: proc(m: ^Set, key: u64) { - fr := _set_find_key(m^, key); + fr := _set_find_key(m^, key) if fr.entry_index >= 0 { - _set_erase(m, fr); + _set_erase(m, fr) } } set_reserve :: proc(m: ^Set, new_size: int) { - nm: Set; - set_init(&nm, m.hash.allocator); - array_resize(&nm.hash, new_size); - array_reserve(&nm.entries, array_len(m.entries)); + nm: Set + set_init(&nm, m.hash.allocator) + array_resize(&nm.hash, new_size) + array_reserve(&nm.entries, array_len(m.entries)) for i in 0..<new_size { - array_set(&nm.hash, i, -1); + array_set(&nm.hash, i, -1) } for i in 0..<array_len(m.entries) { - e := array_get(m.entries, i); - set_add(&nm, e.key); + e := array_get(m.entries, i) + set_add(&nm, e.key) } - set_delete(m^); - m^ = nm; + set_delete(m^) + m^ = nm } set_clear :: proc(m: ^Set) { - array_clear(&m.hash); - array_clear(&m.entries); + array_clear(&m.hash) + array_clear(&m.entries) } set_equal :: proc(a, b: Set) -> bool { - a_entries := array_slice(a.entries); - b_entries := array_slice(b.entries); + a_entries := array_slice(a.entries) + b_entries := array_slice(b.entries) if len(a_entries) != len(b_entries) { - return false; + return false } for e in a_entries { if set_not_in(b, e.key) { - return false; + return false } } - return true; + return true } @@ -115,126 +115,126 @@ set_equal :: proc(a, b: Set) -> bool { /// Internal _set_add_entry :: proc(m: ^Set, key: u64) -> int { - e: Set_Entry; - e.key = key; - e.next = -1; - idx := array_len(m.entries); - array_push(&m.entries, e); - return idx; + e: Set_Entry + e.key = key + e.next = -1 + idx := array_len(m.entries) + array_push(&m.entries, e) + return idx } _set_erase :: proc(m: ^Set, fr: Map_Find_Result) { if fr.entry_prev < 0 { - array_set(&m.hash, fr.hash_index, array_get(m.entries, fr.entry_index).next); + array_set(&m.hash, fr.hash_index, array_get(m.entries, fr.entry_index).next) } else { - array_get_ptr(m.entries, fr.entry_prev).next = array_get(m.entries, fr.entry_index).next; + array_get_ptr(m.entries, fr.entry_prev).next = array_get(m.entries, fr.entry_index).next } if fr.entry_index == array_len(m.entries)-1 { - array_pop_back(&m.entries); - return; + array_pop_back(&m.entries) + return } - array_set(&m.entries, fr.entry_index, array_get(m.entries, array_len(m.entries)-1)); - last := _set_find_key(m^, array_get(m.entries, fr.entry_index).key); + array_set(&m.entries, fr.entry_index, array_get(m.entries, array_len(m.entries)-1)) + last := _set_find_key(m^, array_get(m.entries, fr.entry_index).key) if last.entry_prev < 0 { - array_get_ptr(m.entries, last.entry_prev).next = fr.entry_index; + array_get_ptr(m.entries, last.entry_prev).next = fr.entry_index } else { - array_set(&m.hash, last.hash_index, fr.entry_index); + array_set(&m.hash, last.hash_index, fr.entry_index) } } _set_find_key :: proc(m: Set, key: u64) -> Map_Find_Result { - fr: Map_Find_Result; - fr.hash_index = -1; - fr.entry_prev = -1; - fr.entry_index = -1; + fr: Map_Find_Result + fr.hash_index = -1 + fr.entry_prev = -1 + fr.entry_index = -1 if array_len(m.hash) == 0 { - return fr; + return fr } - fr.hash_index = int(key % u64(array_len(m.hash))); - fr.entry_index = array_get(m.hash, fr.hash_index); + fr.hash_index = int(key % u64(array_len(m.hash))) + fr.entry_index = array_get(m.hash, fr.hash_index) for fr.entry_index >= 0 { - it := array_get_ptr(m.entries, fr.entry_index); + it := array_get_ptr(m.entries, fr.entry_index) if it.key == key { - return fr; + return fr } - fr.entry_prev = fr.entry_index; - fr.entry_index = it.next; + fr.entry_prev = fr.entry_index + fr.entry_index = it.next } - return fr; + return fr } _set_find_entry :: proc(m: ^Set, e: ^Set_Entry) -> Map_Find_Result { - fr: Map_Find_Result; - fr.hash_index = -1; - fr.entry_prev = -1; - fr.entry_index = -1; + fr: Map_Find_Result + fr.hash_index = -1 + fr.entry_prev = -1 + fr.entry_index = -1 if array_len(m.hash) == 0 { - return fr; + return fr } - fr.hash_index = int(e.key % u64(array_len(m.hash))); - fr.entry_index = array_get(m.hash, fr.hash_index); + fr.hash_index = int(e.key % u64(array_len(m.hash))) + fr.entry_index = array_get(m.hash, fr.hash_index) for fr.entry_index >= 0 { - it := array_get_ptr(m.entries, fr.entry_index); + it := array_get_ptr(m.entries, fr.entry_index) if it == e { - return fr; + return fr } - fr.entry_prev = fr.entry_index; - fr.entry_index = it.next; + fr.entry_prev = fr.entry_index + fr.entry_index = it.next } - return fr; + return fr } _set_find_or_fail :: proc(m: Set, key: u64) -> int { - return _set_find_key(m, key).entry_index; + return _set_find_key(m, key).entry_index } _set_find_or_make :: proc(m: ^Set, key: u64) -> int { - fr := _set_find_key(m^, key); + fr := _set_find_key(m^, key) if fr.entry_index >= 0 { - return fr.entry_index; + return fr.entry_index } - i := _set_add_entry(m, key); + i := _set_add_entry(m, key) if fr.entry_prev < 0 { - array_set(&m.hash, fr.hash_index, i); + array_set(&m.hash, fr.hash_index, i) } else { - array_get_ptr(m.entries, fr.entry_prev).next = i; + array_get_ptr(m.entries, fr.entry_prev).next = i } - return i; + return i } _set_make :: proc(m: ^Set, key: u64) -> int { - fr := _set_find_key(m^, key); - i := _set_add_entry(m, key); + fr := _set_find_key(m^, key) + i := _set_add_entry(m, key) if fr.entry_prev < 0 { - array_set(&m.hash, fr.hash_index, i); + array_set(&m.hash, fr.hash_index, i) } else { - array_get_ptr(m.entries, fr.entry_prev).next = i; + array_get_ptr(m.entries, fr.entry_prev).next = i } - array_get_ptr(m.entries, i).next = fr.entry_index; + array_get_ptr(m.entries, i).next = fr.entry_index - return i; + return i } _set_full :: proc(m: Set) -> bool { // TODO(bill): Determine good max load factor - return array_len(m.entries) >= (array_len(m.hash) / 4)*3; + return array_len(m.entries) >= (array_len(m.hash) / 4)*3 } _set_grow :: proc(m: ^Set) { - new_size := array_len(m.entries) * 4 + 7; // TODO(bill): Determine good grow rate - set_reserve(m, new_size); + new_size := array_len(m.entries) * 4 + 7 // TODO(bill): Determine good grow rate + set_reserve(m, new_size) } diff --git a/core/container/small_array.odin b/core/container/small_array.odin index 014837631..43b879d2d 100644 --- a/core/container/small_array.odin +++ b/core/container/small_array.odin @@ -7,89 +7,89 @@ Small_Array :: struct($N: int, $T: typeid) where N >= 0 { small_array_len :: proc(a: $A/Small_Array) -> int { - return a.len; + return a.len } small_array_cap :: proc(a: $A/Small_Array) -> int { - return len(a.data); + return len(a.data) } small_array_space :: proc(a: $A/Small_Array) -> int { - return len(a.data) - a.len; + return len(a.data) - a.len } small_array_slice :: proc(a: ^$A/Small_Array($N, $T)) -> []T { - return a.data[:a.len]; + return a.data[:a.len] } small_array_get :: proc(a: $A/Small_Array($N, $T), index: int, loc := #caller_location) -> T { - return a.data[index]; + return a.data[index] } small_array_get_ptr :: proc(a: $A/Small_Array($N, $T), index: int, loc := #caller_location) -> ^T { - return &a.data[index]; + return &a.data[index] } small_array_set :: proc(a: ^$A/Small_Array($N, $T), index: int, item: T, loc := #caller_location) { - a.data[index] = item; + a.data[index] = item } small_array_resize :: proc(a: ^$A/Small_Array, length: int) { - a.len = min(length, len(a.data)); + a.len = min(length, len(a.data)) } small_array_push_back :: proc(a: ^$A/Small_Array($N, $T), item: T) -> bool { if a.len < len(a.data) { - a.len += 1; - a.data[a.len-1] = item; - return true; + a.len += 1 + a.data[a.len-1] = item + return true } - return false; + return false } small_array_push_front :: proc(a: ^$A/Small_Array($N, $T), item: T) -> bool { if a.len < len(a.data) { - a.len += 1; - data := small_array_slice(a); - copy(data[1:], data[:]); - data[0] = item; - return true; + a.len += 1 + data := small_array_slice(a) + copy(data[1:], data[:]) + data[0] = item + return true } - return false; + return false } small_array_pop_back :: proc(a: ^$A/Small_Array($N, $T), loc := #caller_location) -> T { - assert(condition=a.len > 0, loc=loc); - item := a.data[a.len-1]; - a.len -= 1; - return item; + assert(condition=a.len > 0, loc=loc) + item := a.data[a.len-1] + a.len -= 1 + return item } small_array_pop_front :: proc(a: ^$A/Small_Array($N, $T), loc := #caller_location) -> T { - assert(condition=a.len > 0, loc=loc); - item := a.data[0]; - s := small_array_slice(a); - copy(s[:], s[1:]); - a.len -= 1; - return item; + assert(condition=a.len > 0, loc=loc) + item := a.data[0] + s := small_array_slice(a) + copy(s[:], s[1:]) + a.len -= 1 + return item } small_array_consume :: proc(a: ^$A/Small_Array($N, $T), count: int, loc := #caller_location) { - assert(condition=a.len >= count, loc=loc); - a.len -= count; + assert(condition=a.len >= count, loc=loc) + a.len -= count } small_array_clear :: proc(a: ^$A/Small_Array($N, $T)) { - small_array_resize(a, 0); + small_array_resize(a, 0) } small_array_push_back_elems :: proc(a: ^$A/Small_Array($N, $T), items: ..T) { - n := copy(a.data[a.len:], items[:]); - a.len += n; + n := copy(a.data[a.len:], items[:]) + a.len += n } -small_array_push :: proc{small_array_push_back, small_array_push_back_elems}; -small_array_append :: proc{small_array_push_back, small_array_push_back_elems}; +small_array_push :: proc{small_array_push_back, small_array_push_back_elems} +small_array_append :: proc{small_array_push_back, small_array_push_back_elems} diff --git a/core/dynlib/lib.odin b/core/dynlib/lib.odin index 7feed73da..00655d650 100644 --- a/core/dynlib/lib.odin +++ b/core/dynlib/lib.odin @@ -1,3 +1,3 @@ package dynlib -Library :: distinct rawptr; +Library :: distinct rawptr diff --git a/core/dynlib/lib_windows.odin b/core/dynlib/lib_windows.odin index a0d91f4c0..b9aae9cf1 100644 --- a/core/dynlib/lib_windows.odin +++ b/core/dynlib/lib_windows.odin @@ -7,19 +7,19 @@ import "core:strings" load_library :: proc(path: string, global_symbols := false) -> (Library, bool) { // NOTE(bill): 'global_symbols' is here only for consistency with POSIX which has RTLD_GLOBAL - wide_path := win32.utf8_to_wstring(path, context.temp_allocator); - handle := cast(Library)win32.LoadLibraryW(wide_path); - return handle, handle != nil; + wide_path := win32.utf8_to_wstring(path, context.temp_allocator) + handle := cast(Library)win32.LoadLibraryW(wide_path) + return handle, handle != nil } unload_library :: proc(library: Library) -> bool { - ok := win32.FreeLibrary(cast(win32.HMODULE)library); - return bool(ok); + ok := win32.FreeLibrary(cast(win32.HMODULE)library) + return bool(ok) } symbol_address :: proc(library: Library, symbol: string) -> (ptr: rawptr, found: bool) { - c_str := strings.clone_to_cstring(symbol, context.temp_allocator); - ptr = win32.GetProcAddress(cast(win32.HMODULE)library, c_str); - found = ptr != nil; - return; + c_str := strings.clone_to_cstring(symbol, context.temp_allocator) + ptr = win32.GetProcAddress(cast(win32.HMODULE)library, c_str) + found = ptr != nil + return } diff --git a/core/encoding/base32/base32.odin b/core/encoding/base32/base32.odin index 4e0e948e3..7ab35afd0 100644 --- a/core/encoding/base32/base32.odin +++ b/core/encoding/base32/base32.odin @@ -12,9 +12,9 @@ ENC_TABLE := [32]byte { 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', '2', '3', '4', '5', '6', '7',
-};
+}
-PADDING :: '=';
+PADDING :: '='
DEC_TABLE := [?]u8 {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -31,118 +31,118 @@ DEC_TABLE := [?]u8 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-};
+}
encode :: proc(data: []byte, ENC_TBL := ENC_TABLE, allocator := context.allocator) -> string {
- out_length := (len(data) + 4) / 5 * 8;
- out := make([]byte, out_length);
- _encode(out, data);
- return string(out);
+ out_length := (len(data) + 4) / 5 * 8
+ out := make([]byte, out_length)
+ _encode(out, data)
+ return string(out)
}
@private
_encode :: proc(out, data: []byte, ENC_TBL := ENC_TABLE, allocator := context.allocator) {
- out := out;
- data := data;
+ out := out
+ data := data
for len(data) > 0 {
- carry: byte;
+ carry: byte
switch len(data) {
case:
- out[7] = ENC_TABLE[data[4] & 0x1f];
- carry = data[4] >> 5;
- fallthrough;
+ out[7] = ENC_TABLE[data[4] & 0x1f]
+ carry = data[4] >> 5
+ fallthrough
case 4:
- out[6] = ENC_TABLE[carry | (data[3] << 3) & 0x1f];
- out[5] = ENC_TABLE[(data[3] >> 2) & 0x1f];
- carry = data[3] >> 7;
- fallthrough;
+ out[6] = ENC_TABLE[carry | (data[3] << 3) & 0x1f]
+ out[5] = ENC_TABLE[(data[3] >> 2) & 0x1f]
+ carry = data[3] >> 7
+ fallthrough
case 3:
- out[4] = ENC_TABLE[carry | (data[2] << 1) & 0x1f];
- carry = (data[2] >> 4) & 0x1f;
- fallthrough;
+ out[4] = ENC_TABLE[carry | (data[2] << 1) & 0x1f]
+ carry = (data[2] >> 4) & 0x1f
+ fallthrough
case 2:
- out[3] = ENC_TABLE[carry | (data[1] << 4) & 0x1f];
- out[2] = ENC_TABLE[(data[1] >> 1) & 0x1f];
- carry = (data[1] >> 6) & 0x1f;
- fallthrough;
+ out[3] = ENC_TABLE[carry | (data[1] << 4) & 0x1f]
+ out[2] = ENC_TABLE[(data[1] >> 1) & 0x1f]
+ carry = (data[1] >> 6) & 0x1f
+ fallthrough
case 1:
- out[1] = ENC_TABLE[carry | (data[0] << 2) & 0x1f];
- out[0] = ENC_TABLE[data[0] >> 3];
+ out[1] = ENC_TABLE[carry | (data[0] << 2) & 0x1f]
+ out[0] = ENC_TABLE[data[0] >> 3]
}
if len(data) < 5 {
- out[7] = byte(PADDING);
+ out[7] = byte(PADDING)
if len(data) < 4 {
- out[6] = byte(PADDING);
- out[5] = byte(PADDING);
+ out[6] = byte(PADDING)
+ out[5] = byte(PADDING)
if len(data) < 3 {
- out[4] = byte(PADDING);
+ out[4] = byte(PADDING)
if len(data) < 2 {
- out[3] = byte(PADDING);
- out[2] = byte(PADDING);
+ out[3] = byte(PADDING)
+ out[2] = byte(PADDING)
}
}
}
- break;
+ break
}
- data = data[5:];
- out = out[8:];
+ data = data[5:]
+ out = out[8:]
}
}
decode :: proc(data: string, DEC_TBL := DEC_TABLE, allocator := context.allocator) -> []byte #no_bounds_check{
if len(data) == 0 {
- return nil;
+ return nil
}
- outi := 0;
- data := data;
+ outi := 0
+ data := data
- out := make([]byte, len(data) / 8 * 5, allocator);
- end := false;
+ out := make([]byte, len(data) / 8 * 5, allocator)
+ end := false
for len(data) > 0 && !end {
- dbuf : [8]byte;
- dlen := 8;
+ dbuf : [8]byte
+ dlen := 8
for j := 0; j < 8; {
if len(data) == 0 {
- dlen, end = j, true;
- break;
+ dlen, end = j, true
+ break
}
- input := data[0];
- data = data[1:];
+ input := data[0]
+ data = data[1:]
if input == byte(PADDING) && j >= 2 && len(data) < 8 {
- assert(!(len(data) + j < 8 - 1), "Corrupted input");
+ assert(!(len(data) + j < 8 - 1), "Corrupted input")
for k := 0; k < 8-1-j; k +=1 {
- assert(len(data) < k || data[k] == byte(PADDING), "Corrupted input");
+ assert(len(data) < k || data[k] == byte(PADDING), "Corrupted input")
}
- dlen, end = j, true;
- assert(dlen != 1 && dlen != 3 && dlen != 6, "Corrupted input");
- break;
+ dlen, end = j, true
+ assert(dlen != 1 && dlen != 3 && dlen != 6, "Corrupted input")
+ break
}
- dbuf[j] = DEC_TABLE[input];
- assert(dbuf[j] != 0xff, "Corrupted input");
- j += 1;
+ dbuf[j] = DEC_TABLE[input]
+ assert(dbuf[j] != 0xff, "Corrupted input")
+ j += 1
}
switch dlen {
case 8:
- out[outi + 4] = dbuf[6] << 5 | dbuf[7];
- fallthrough;
+ out[outi + 4] = dbuf[6] << 5 | dbuf[7]
+ fallthrough
case 7:
- out[outi + 3] = dbuf[4] << 7 | dbuf[5] << 2 | dbuf[6] >> 3;
- fallthrough;
+ out[outi + 3] = dbuf[4] << 7 | dbuf[5] << 2 | dbuf[6] >> 3
+ fallthrough
case 5:
- out[outi + 2] = dbuf[3] << 4 | dbuf[4] >> 1;
- fallthrough;
+ out[outi + 2] = dbuf[3] << 4 | dbuf[4] >> 1
+ fallthrough
case 4:
- out[outi + 1] = dbuf[1] << 6 | dbuf[2] << 1 | dbuf[3] >> 4;
- fallthrough;
+ out[outi + 1] = dbuf[1] << 6 | dbuf[2] << 1 | dbuf[3] >> 4
+ fallthrough
case 2:
- out[outi + 0] = dbuf[0] << 3 | dbuf[1] >> 2;
+ out[outi + 0] = dbuf[0] << 3 | dbuf[1] >> 2
}
- outi += 5;
+ outi += 5
}
- return out;
+ return out
}
diff --git a/core/encoding/base64/base64.odin b/core/encoding/base64/base64.odin index 7c17a2860..ca509326b 100644 --- a/core/encoding/base64/base64.odin +++ b/core/encoding/base64/base64.odin @@ -16,9 +16,9 @@ ENC_TABLE := [64]byte { 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', -}; +} -PADDING :: '='; +PADDING :: '=' DEC_TABLE := [128]int { -1, -1, -1, -1, -1, -1, -1, -1, @@ -37,61 +37,61 @@ DEC_TABLE := [128]int { 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, -}; +} encode :: proc(data: []byte, ENC_TBL := ENC_TABLE, allocator := context.allocator) -> string #no_bounds_check { - length := len(data); + length := len(data) if length == 0 { - return ""; + return "" } - out_length := ((4 * length / 3) + 3) &~ 3; - out := make([]byte, out_length, allocator); + out_length := ((4 * length / 3) + 3) &~ 3 + out := make([]byte, out_length, allocator) - c0, c1, c2, block: int; + c0, c1, c2, block: int for i, d := 0, 0; i < length; i, d = i + 3, d + 4 { - c0, c1, c2 = int(data[i]), -1, -1; + c0, c1, c2 = int(data[i]), -1, -1 if i + 1 < length { c1 = int(data[i + 1]); } if i + 2 < length { c2 = int(data[i + 2]); } - block = (c0 << 16) | (max(c1, 0) << 8) | max(c2, 0); + block = (c0 << 16) | (max(c1, 0) << 8) | max(c2, 0) - out[d] = ENC_TBL[block >> 18 & 63]; - out[d + 1] = ENC_TBL[block >> 12 & 63]; - out[d + 2] = c1 == -1 ? PADDING : ENC_TBL[block >> 6 & 63]; - out[d + 3] = c2 == -1 ? PADDING : ENC_TBL[block & 63]; + out[d] = ENC_TBL[block >> 18 & 63] + out[d + 1] = ENC_TBL[block >> 12 & 63] + out[d + 2] = c1 == -1 ? PADDING : ENC_TBL[block >> 6 & 63] + out[d + 3] = c2 == -1 ? PADDING : ENC_TBL[block & 63] } - return string(out); + return string(out) } decode :: proc(data: string, DEC_TBL := DEC_TABLE, allocator := context.allocator) -> []byte #no_bounds_check { - length := len(data); + length := len(data) if length == 0 { - return nil; + return nil } - pad_count := data[length - 1] == PADDING ? (data[length - 2] == PADDING ? 2 : 1) : 0; - out_length := ((length * 6) >> 3) - pad_count; - out := make([]byte, out_length, allocator); + pad_count := data[length - 1] == PADDING ? (data[length - 2] == PADDING ? 2 : 1) : 0 + out_length := ((length * 6) >> 3) - pad_count + out := make([]byte, out_length, allocator) - c0, c1, c2, c3: int; - b0, b1, b2: int; + c0, c1, c2, c3: int + b0, b1, b2: int for i, j := 0, 0; i < length; i, j = i + 4, j + 3 { - c0 = DEC_TBL[data[i]]; - c1 = DEC_TBL[data[i + 1]]; - c2 = DEC_TBL[data[i + 2]]; - c3 = DEC_TBL[data[i + 3]]; - - b0 = (c0 << 2) | (c1 >> 4); - b1 = (c1 << 4) | (c2 >> 2); - b2 = (c2 << 6) | c3; - - out[j] = byte(b0); - out[j + 1] = byte(b1); - out[j + 2] = byte(b2); + c0 = DEC_TBL[data[i]] + c1 = DEC_TBL[data[i + 1]] + c2 = DEC_TBL[data[i + 2]] + c3 = DEC_TBL[data[i + 3]] + + b0 = (c0 << 2) | (c1 >> 4) + b1 = (c1 << 4) | (c2 >> 2) + b2 = (c2 << 6) | c3 + + out[j] = byte(b0) + out[j + 1] = byte(b1) + out[j + 2] = byte(b2) } - return out; + return out } diff --git a/core/encoding/csv/reader.odin b/core/encoding/csv/reader.odin index 4c28ea9f3..aecb73d7b 100644 --- a/core/encoding/csv/reader.odin +++ b/core/encoding/csv/reader.odin @@ -68,7 +68,7 @@ reader_error_kind_string := [Reader_Error_Kind]string{ .Quote = "extra or missing \" in quoted field", .Field_Count = "wrong field count", .Invalid_Delim = "invalid delimiter", -}; +} Reader_Error :: struct { kind: Reader_Error_Kind, @@ -83,35 +83,35 @@ Error :: union { io.Error, } -DEFAULT_RECORD_BUFFER_CAPACITY :: 256; +DEFAULT_RECORD_BUFFER_CAPACITY :: 256 // reader_init initializes a new Reader from r reader_init :: proc(reader: ^Reader, r: io.Reader, buffer_allocator := context.allocator) { - reader.comma = ','; - - context.allocator = buffer_allocator; - reserve(&reader.record_buffer, DEFAULT_RECORD_BUFFER_CAPACITY); - reserve(&reader.raw_buffer, 0); - reserve(&reader.field_indices, 0); - reserve(&reader.last_record, 0); - bufio.reader_init(&reader.r, r); + reader.comma = ',' + + context.allocator = buffer_allocator + reserve(&reader.record_buffer, DEFAULT_RECORD_BUFFER_CAPACITY) + reserve(&reader.raw_buffer, 0) + reserve(&reader.field_indices, 0) + reserve(&reader.last_record, 0) + bufio.reader_init(&reader.r, r) } // reader_init_with_string initializes a new Reader from s reader_init_with_string :: proc(reader: ^Reader, s: string, buffer_allocator := context.allocator) { - strings.reader_init(&reader.sr, s); - r, _ := io.to_reader(strings.reader_to_stream(&reader.sr)); - reader_init(reader, r, buffer_allocator); + strings.reader_init(&reader.sr, s) + r, _ := io.to_reader(strings.reader_to_stream(&reader.sr)) + reader_init(reader, r, buffer_allocator) } // reader_destroy destroys a Reader reader_destroy :: proc(r: ^Reader) { - delete(r.raw_buffer); - delete(r.record_buffer); - delete(r.field_indices); - delete(r.last_record); - bufio.reader_destroy(&r.r); + delete(r.raw_buffer) + delete(r.record_buffer) + delete(r.field_indices) + delete(r.last_record) + bufio.reader_destroy(&r.r) } // read reads a single record (a slice of fields) from r @@ -119,21 +119,21 @@ reader_destroy :: proc(r: ^Reader) { // All \r\n sequences are normalized to \n, including multi-line field read :: proc(r: ^Reader, allocator := context.allocator) -> (record: []string, err: Error) { if r.reuse_record { - record, err = _read_record(r, &r.last_record, allocator); - resize(&r.last_record, len(record)); - copy(r.last_record[:], record); + record, err = _read_record(r, &r.last_record, allocator) + resize(&r.last_record, len(record)) + copy(r.last_record[:], record) } else { - record, err = _read_record(r, nil, allocator); + record, err = _read_record(r, nil, allocator) } - return; + return } // is_io_error checks where an Error is a specific io.Error kind is_io_error :: proc(err: Error, io_err: io.Error) -> bool { if v, ok := err.(io.Error); ok { - return v == io_err; + return v == io_err } - return false; + return false } @@ -141,97 +141,97 @@ is_io_error :: proc(err: Error, io_err: io.Error) -> bool { // Each record is a slice of fields. // read_all is defined to read until an EOF, and does not treat, and does not treat EOF as an error read_all :: proc(r: ^Reader, allocator := context.allocator) -> ([][]string, Error) { - context.allocator = allocator; - records: [dynamic][]string; + context.allocator = allocator + records: [dynamic][]string for { - record, rerr := _read_record(r, nil, allocator); + record, rerr := _read_record(r, nil, allocator) if is_io_error(rerr, .EOF) { - return records[:], nil; + return records[:], nil } if rerr != nil { - return nil, rerr; + return nil, rerr } - append(&records, record); + append(&records, record) } } // read reads a single record (a slice of fields) from the provided input. read_from_string :: proc(input: string, record_allocator := context.allocator, buffer_allocator := context.allocator) -> (record: []string, n: int, err: Error) { - ir: strings.Reader; - strings.reader_init(&ir, input); - input_reader, _ := io.to_reader(strings.reader_to_stream(&ir)); - - r: Reader; - reader_init(&r, input_reader, buffer_allocator); - defer reader_destroy(&r); - record, err = read(&r, record_allocator); - n = int(r.r.r); - return; + ir: strings.Reader + strings.reader_init(&ir, input) + input_reader, _ := io.to_reader(strings.reader_to_stream(&ir)) + + r: Reader + reader_init(&r, input_reader, buffer_allocator) + defer reader_destroy(&r) + record, err = read(&r, record_allocator) + n = int(r.r.r) + return } // read_all reads all the remaining records from the provided input. read_all_from_string :: proc(input: string, records_allocator := context.allocator, buffer_allocator := context.allocator) -> ([][]string, Error) { - ir: strings.Reader; - strings.reader_init(&ir, input); - input_reader, _ := io.to_reader(strings.reader_to_stream(&ir)); - - r: Reader; - reader_init(&r, input_reader, buffer_allocator); - defer reader_destroy(&r); - return read_all(&r, records_allocator); + ir: strings.Reader + strings.reader_init(&ir, input) + input_reader, _ := io.to_reader(strings.reader_to_stream(&ir)) + + r: Reader + reader_init(&r, input_reader, buffer_allocator) + defer reader_destroy(&r) + return read_all(&r, records_allocator) } @private is_valid_delim :: proc(r: rune) -> bool { switch r { case 0, '"', '\r', '\n', utf8.RUNE_ERROR: - return false; + return false } - return utf8.valid_rune(r); + return utf8.valid_rune(r) } @private _read_record :: proc(r: ^Reader, dst: ^[dynamic]string, allocator := context.allocator) -> ([]string, Error) { read_line :: proc(r: ^Reader) -> ([]byte, io.Error) { - line, err := bufio.reader_read_slice(&r.r, '\n'); + line, err := bufio.reader_read_slice(&r.r, '\n') if err == .Buffer_Full { - clear(&r.raw_buffer); - append(&r.raw_buffer, ..line); + clear(&r.raw_buffer) + append(&r.raw_buffer, ..line) for err == .Buffer_Full { - line, err = bufio.reader_read_slice(&r.r, '\n'); - append(&r.raw_buffer, ..line); + line, err = bufio.reader_read_slice(&r.r, '\n') + append(&r.raw_buffer, ..line) } - line = r.raw_buffer[:]; + line = r.raw_buffer[:] } if len(line) > 0 && err == .EOF { - err = nil; + err = nil if line[len(line)-1] == '\r' { - line = line[:len(line)-1]; + line = line[:len(line)-1] } } - r.line_count += 1; + r.line_count += 1 // normalize \r\n to \n - n := len(line); + n := len(line) for n >= 2 && string(line[n-2:]) == "\r\n" { - line[n-2] = '\n'; - line = line[:n-1]; + line[n-2] = '\n' + line = line[:n-1] } - return line, err; + return line, err } length_newline :: proc(b: []byte) -> int { if len(b) > 0 && b[len(b)-1] == '\n' { - return 1; + return 1 } - return 0; + return 0 } next_rune :: proc(b: []byte) -> rune { - r, _ := utf8.decode_rune(b); - return r; + r, _ := utf8.decode_rune(b) + return r } if r.comma == r.comment || @@ -240,152 +240,152 @@ _read_record :: proc(r: ^Reader, dst: ^[dynamic]string, allocator := context.all err := Reader_Error{ kind = .Invalid_Delim, line = r.line_count, - }; - return nil, err; + } + return nil, err } - line, full_line: []byte; - err_read: io.Error; + line, full_line: []byte + err_read: io.Error for err_read == nil { - line, err_read = read_line(r); + line, err_read = read_line(r) if r.comment != 0 && next_rune(line) == r.comment { - line = nil; - continue; + line = nil + continue } if err_read == nil && len(line) == length_newline(line) { - line = nil; - continue; + line = nil + continue } - full_line = line; - break; + full_line = line + break } if is_io_error(err_read, .EOF) { - return nil, err_read; + return nil, err_read } - err: Error; - quote_len :: len(`"`); - comma_len := utf8.rune_size(r.comma); - record_line := r.line_count; - clear(&r.record_buffer); - clear(&r.field_indices); + err: Error + quote_len :: len(`"`) + comma_len := utf8.rune_size(r.comma) + record_line := r.line_count + clear(&r.record_buffer) + clear(&r.field_indices) parse_field: for { if r.trim_leading_space { - line = bytes.trim_left_space(line); + line = bytes.trim_left_space(line) } if len(line) == 0 || line[0] != '"' { - i := bytes.index_rune(line, r.comma); - field := line; + i := bytes.index_rune(line, r.comma) + field := line if i >= 0 { - field = field[:i]; + field = field[:i] } else { - field = field[:len(field) - length_newline(field)]; + field = field[:len(field) - length_newline(field)] } if !r.lazy_quotes { if j := bytes.index_byte(field, '"'); j >= 0 { - column := utf8.rune_count(full_line[:len(full_line) - len(line[j:])]); + column := utf8.rune_count(full_line[:len(full_line) - len(line[j:])]) err = Reader_Error{ kind = .Bare_Quote, start_line = record_line, line = r.line_count, column = column, - }; - break parse_field; + } + break parse_field } } - append(&r.record_buffer, ..field); - append(&r.field_indices, len(r.record_buffer)); + append(&r.record_buffer, ..field) + append(&r.field_indices, len(r.record_buffer)) if i >= 0 { - line = line[i+comma_len:]; - continue parse_field; + line = line[i+comma_len:] + continue parse_field } - break parse_field; + break parse_field } else { - line = line[quote_len:]; + line = line[quote_len:] for { - i := bytes.index_byte(line, '"'); + i := bytes.index_byte(line, '"') switch { case i >= 0: - append(&r.record_buffer, ..line[:i]); - line = line[i+quote_len:]; + append(&r.record_buffer, ..line[:i]) + line = line[i+quote_len:] switch ch := next_rune(line); { case ch == '"': // append quote - append(&r.record_buffer, '"'); - line = line[quote_len:]; + append(&r.record_buffer, '"') + line = line[quote_len:] case ch == r.comma: // end of field - line = line[comma_len:]; - append(&r.field_indices, len(r.record_buffer)); - continue parse_field; + line = line[comma_len:] + append(&r.field_indices, len(r.record_buffer)) + continue parse_field case length_newline(line) == len(line): // end of line - append(&r.field_indices, len(r.record_buffer)); - break parse_field; + append(&r.field_indices, len(r.record_buffer)) + break parse_field case r.lazy_quotes: // bare quote - append(&r.record_buffer, '"'); + append(&r.record_buffer, '"') case: // invalid non-escaped quote - column := utf8.rune_count(full_line[:len(full_line) - len(line) - quote_len]); + column := utf8.rune_count(full_line[:len(full_line) - len(line) - quote_len]) err = Reader_Error{ kind = .Quote, start_line = record_line, line = r.line_count, column = column, - }; - break parse_field; + } + break parse_field } case len(line) > 0: - append(&r.record_buffer, ..line); + append(&r.record_buffer, ..line) if err_read != nil { - break parse_field; + break parse_field } - line, err_read = read_line(r); + line, err_read = read_line(r) if is_io_error(err_read, .EOF) { - err_read = nil; + err_read = nil } - full_line = line; + full_line = line case: if !r.lazy_quotes && err_read == nil { - column := utf8.rune_count(full_line); + column := utf8.rune_count(full_line) err = Reader_Error{ kind = .Quote, start_line = record_line, line = r.line_count, column = column, - }; - break parse_field; + } + break parse_field } - append(&r.field_indices, len(r.record_buffer)); - break parse_field; + append(&r.field_indices, len(r.record_buffer)) + break parse_field } } } } if err == nil && err_read != nil { - err = err_read; + err = err_read } - context.allocator = allocator; - dst := dst; - str := string(r.record_buffer[:]); + context.allocator = allocator + dst := dst + str := string(r.record_buffer[:]) if dst == nil { // use local variable - dst = &([dynamic]string){}; + dst = &([dynamic]string){} } - clear(dst); - resize(dst, len(r.field_indices)); - pre_idx: int; + clear(dst) + resize(dst, len(r.field_indices)) + pre_idx: int for idx, i in r.field_indices { - field := str[pre_idx:idx]; + field := str[pre_idx:idx] if !r.reuse_record_buffer { - field = strings.clone(field); + field = strings.clone(field) } - dst[i] = field; - pre_idx = idx; + dst[i] = field + pre_idx = idx } if r.fields_per_record > 0 { @@ -396,11 +396,11 @@ _read_record :: proc(r: ^Reader, dst: ^[dynamic]string, allocator := context.all line = r.line_count, expected = r.fields_per_record, got = len(dst), - }; + } } } else if r.fields_per_record == 0 { - r.fields_per_record = len(dst); + r.fields_per_record = len(dst) } - return dst[:], err; + return dst[:], err } diff --git a/core/encoding/csv/writer.odin b/core/encoding/csv/writer.odin index 2176e6781..3a0038916 100644 --- a/core/encoding/csv/writer.odin +++ b/core/encoding/csv/writer.odin @@ -17,8 +17,8 @@ Writer :: struct { // writer_init initializes a Writer that writes to w writer_init :: proc(writer: ^Writer, w: io.Writer) { - writer.comma = ','; - writer.w = w; + writer.comma = ',' + writer.w = w } // write writes a single CSV records to w with any of the necessarily quoting. @@ -26,101 +26,101 @@ writer_init :: proc(writer: ^Writer, w: io.Writer) { // // If the underlying io.Writer requires flushing, make sure to call io.flush write :: proc(w: ^Writer, record: []string) -> io.Error { - CHAR_SET :: "\n\r\""; + CHAR_SET :: "\n\r\"" field_needs_quoting :: proc(w: ^Writer, field: string) -> bool { switch { case field == "": // No need to quote empty strings - return false; + return false case field == `\.`: // Postgres is weird - return true; + return true case w.comma < utf8.RUNE_SELF: // ASCII optimization for i in 0..<len(field) { switch field[i] { case '\n', '\r', '"', byte(w.comma): - return true; + return true } } case: if strings.contains_rune(field, w.comma) >= 0 { - return true; + return true } if strings.contains_any(field, CHAR_SET) { - return true; + return true } } // Leading spaces need quoting - r, _ := utf8.decode_rune_in_string(field); - return strings.is_space(r); + r, _ := utf8.decode_rune_in_string(field) + return strings.is_space(r) } if !is_valid_delim(w.comma) { - return .No_Progress; // TODO(bill): Is this a good error? + return .No_Progress // TODO(bill): Is this a good error? } for _, field_idx in record { // NOTE(bill): declared like this so that the field can be modified later if necessary - field := record[field_idx]; + field := record[field_idx] if field_idx > 0 { - io.write_rune(w.w, w.comma) or_return; + io.write_rune(w.w, w.comma) or_return } if !field_needs_quoting(w, field) { - io.write_string(w.w, field) or_return; - continue; + io.write_string(w.w, field) or_return + continue } - io.write_byte(w.w, '"') or_return; + io.write_byte(w.w, '"') or_return for len(field) > 0 { - i := strings.index_any(field, CHAR_SET); + i := strings.index_any(field, CHAR_SET) if i < 0 { - i = len(field); + i = len(field) } - io.write_string(w.w, field[:i]) or_return; - field = field[i:]; + io.write_string(w.w, field[:i]) or_return + field = field[i:] if len(field) > 0 { switch field[0] { case '\r': if !w.use_crlf { - io.write_byte(w.w, '\r') or_return; + io.write_byte(w.w, '\r') or_return } case '\n': if w.use_crlf { - io.write_string(w.w, "\r\n") or_return; + io.write_string(w.w, "\r\n") or_return } else { - io.write_byte(w.w, '\n') or_return; + io.write_byte(w.w, '\n') or_return } case '"': - io.write_string(w.w, `""`) or_return; + io.write_string(w.w, `""`) or_return } - field = field[1:]; + field = field[1:] } } - io.write_byte(w.w, '"') or_return; + io.write_byte(w.w, '"') or_return } if w.use_crlf { - _, err := io.write_string(w.w, "\r\n"); - return err; + _, err := io.write_string(w.w, "\r\n") + return err } - return io.write_byte(w.w, '\n'); + return io.write_byte(w.w, '\n') } // write_all writes multiple CSV records to w using write, and then flushes (if necessary). write_all :: proc(w: ^Writer, records: [][]string) -> io.Error { for record in records { - write(w, record) or_return; + write(w, record) or_return } - return writer_flush(w); + return writer_flush(w) } // writer_flush flushes the underlying io.Writer. // If the underlying io.Writer does not support flush, nil is returned. writer_flush :: proc(w: ^Writer) -> io.Error { - return io.flush(auto_cast w.w); + return io.flush(auto_cast w.w) } diff --git a/core/encoding/hxa/hxa.odin b/core/encoding/hxa/hxa.odin index 31113f907..f47661bad 100644 --- a/core/encoding/hxa/hxa.odin +++ b/core/encoding/hxa/hxa.odin @@ -2,10 +2,10 @@ package encoding_hxa import "core:mem" -LATEST_VERSION :: 3; -VERSION_API :: "0.3"; +LATEST_VERSION :: 3 +VERSION_API :: "0.3" -MAGIC_NUMBER :: 'H'<<0 | 'x'<<8 | 'A'<<16 | '\x00'<<24; +MAGIC_NUMBER :: 'H'<<0 | 'x'<<8 | 'A'<<16 | '\x00'<<24 Header :: struct #packed { magic_number: u32le, @@ -48,7 +48,7 @@ Meta_Value_Type :: enum u8 { Text = 3, Binary = 4, Meta = 5, -}; +} Meta :: struct { name: string, // name of the meta data value (maximum length is 255) @@ -74,7 +74,7 @@ Layer :: struct { } // Layers stacks are arrays of layers where all the layers have the same number of entries (polygons, edges, vertices or pixels) -Layer_Stack :: distinct []Layer; +Layer_Stack :: distinct []Layer Node_Geometry :: struct { vertex_count: u32le, // number of vertices @@ -92,7 +92,7 @@ Node_Image :: struct { image_stack: Layer_Stack, } -Node_Index :: distinct u32le; +Node_Index :: distinct u32le // A file consists of an array of nodes, All nodes have meta data. Geometry nodes have geometry, image nodes have pixels Node :: struct { @@ -114,15 +114,15 @@ If you use HxA for something not covered by the conventions but need a conventio /* Hard conventions */ /* ---------------- */ -CONVENTION_HARD_BASE_VERTEX_LAYER_NAME :: "vertex"; -CONVENTION_HARD_BASE_VERTEX_LAYER_ID :: 0; -CONVENTION_HARD_BASE_VERTEX_LAYER_COMPONENTS :: 3; -CONVENTION_HARD_BASE_CORNER_LAYER_NAME :: "reference"; -CONVENTION_HARD_BASE_CORNER_LAYER_ID :: 0; -CONVENTION_HARD_BASE_CORNER_LAYER_COMPONENTS :: 1; -CONVENTION_HARD_BASE_CORNER_LAYER_TYPE :: Layer_Data_Type.Int32; -CONVENTION_HARD_EDGE_NEIGHBOUR_LAYER_NAME :: "neighbour"; -CONVENTION_HARD_EDGE_NEIGHBOUR_LAYER_TYPE :: Layer_Data_Type.Int32; +CONVENTION_HARD_BASE_VERTEX_LAYER_NAME :: "vertex" +CONVENTION_HARD_BASE_VERTEX_LAYER_ID :: 0 +CONVENTION_HARD_BASE_VERTEX_LAYER_COMPONENTS :: 3 +CONVENTION_HARD_BASE_CORNER_LAYER_NAME :: "reference" +CONVENTION_HARD_BASE_CORNER_LAYER_ID :: 0 +CONVENTION_HARD_BASE_CORNER_LAYER_COMPONENTS :: 1 +CONVENTION_HARD_BASE_CORNER_LAYER_TYPE :: Layer_Data_Type.Int32 +CONVENTION_HARD_EDGE_NEIGHBOUR_LAYER_NAME :: "neighbour" +CONVENTION_HARD_EDGE_NEIGHBOUR_LAYER_TYPE :: Layer_Data_Type.Int32 @@ -131,63 +131,63 @@ CONVENTION_HARD_EDGE_NEIGHBOUR_LAYER_TYPE :: Layer_Data_Type.Int32; /* geometry layers */ -CONVENTION_SOFT_LAYER_SEQUENCE0 :: "sequence"; -CONVENTION_SOFT_LAYER_NAME_UV0 :: "uv"; -CONVENTION_SOFT_LAYER_NORMALS :: "normal"; -CONVENTION_SOFT_LAYER_BINORMAL :: "binormal"; -CONVENTION_SOFT_LAYER_TANGENT :: "tangent"; -CONVENTION_SOFT_LAYER_COLOR :: "color"; -CONVENTION_SOFT_LAYER_CREASES :: "creases"; -CONVENTION_SOFT_LAYER_SELECTION :: "select"; -CONVENTION_SOFT_LAYER_SKIN_WEIGHT :: "skining_weight"; -CONVENTION_SOFT_LAYER_SKIN_REFERENCE :: "skining_reference"; -CONVENTION_SOFT_LAYER_BLENDSHAPE :: "blendshape"; -CONVENTION_SOFT_LAYER_ADD_BLENDSHAPE :: "addblendshape"; -CONVENTION_SOFT_LAYER_MATERIAL_ID :: "material"; +CONVENTION_SOFT_LAYER_SEQUENCE0 :: "sequence" +CONVENTION_SOFT_LAYER_NAME_UV0 :: "uv" +CONVENTION_SOFT_LAYER_NORMALS :: "normal" +CONVENTION_SOFT_LAYER_BINORMAL :: "binormal" +CONVENTION_SOFT_LAYER_TANGENT :: "tangent" +CONVENTION_SOFT_LAYER_COLOR :: "color" +CONVENTION_SOFT_LAYER_CREASES :: "creases" +CONVENTION_SOFT_LAYER_SELECTION :: "select" +CONVENTION_SOFT_LAYER_SKIN_WEIGHT :: "skining_weight" +CONVENTION_SOFT_LAYER_SKIN_REFERENCE :: "skining_reference" +CONVENTION_SOFT_LAYER_BLENDSHAPE :: "blendshape" +CONVENTION_SOFT_LAYER_ADD_BLENDSHAPE :: "addblendshape" +CONVENTION_SOFT_LAYER_MATERIAL_ID :: "material" /* Image layers */ -CONVENTION_SOFT_ALBEDO :: "albedo"; -CONVENTION_SOFT_LIGHT :: "light"; -CONVENTION_SOFT_DISPLACEMENT :: "displacement"; -CONVENTION_SOFT_DISTORTION :: "distortion"; -CONVENTION_SOFT_AMBIENT_OCCLUSION :: "ambient_occlusion"; +CONVENTION_SOFT_ALBEDO :: "albedo" +CONVENTION_SOFT_LIGHT :: "light" +CONVENTION_SOFT_DISPLACEMENT :: "displacement" +CONVENTION_SOFT_DISTORTION :: "distortion" +CONVENTION_SOFT_AMBIENT_OCCLUSION :: "ambient_occlusion" /* tags layers */ -CONVENTION_SOFT_NAME :: "name"; -CONVENTION_SOFT_TRANSFORM :: "transform"; +CONVENTION_SOFT_NAME :: "name" +CONVENTION_SOFT_TRANSFORM :: "transform" /* destroy procedures */ meta_destroy :: proc(meta: Meta, allocator := context.allocator) { if nested, ok := meta.value.([]Meta); ok { for m in nested { - meta_destroy(m); + meta_destroy(m) } - delete(nested, allocator); + delete(nested, allocator) } } nodes_destroy :: proc(nodes: []Node, allocator := context.allocator) { for node in nodes { for meta in node.meta_data { - meta_destroy(meta); + meta_destroy(meta) } - delete(node.meta_data, allocator); + delete(node.meta_data, allocator) switch n in node.content { case Node_Geometry: - delete(n.corner_stack, allocator); - delete(n.edge_stack, allocator); - delete(n.face_stack, allocator); + delete(n.corner_stack, allocator) + delete(n.edge_stack, allocator) + delete(n.face_stack, allocator) case Node_Image: - delete(n.image_stack, allocator); + delete(n.image_stack, allocator) } } - delete(nodes, allocator); + delete(nodes, allocator) } file_destroy :: proc(file: File) { - nodes_destroy(file.nodes, file.allocator); - delete(file.backing, file.allocator); + nodes_destroy(file.nodes, file.allocator) + delete(file.backing, file.allocator) } diff --git a/core/encoding/hxa/read.odin b/core/encoding/hxa/read.odin index 0cf58dce0..ef7edc8b7 100644 --- a/core/encoding/hxa/read.odin +++ b/core/encoding/hxa/read.odin @@ -12,20 +12,20 @@ Read_Error :: enum { } read_from_file :: proc(filename: string, print_error := false, allocator := context.allocator) -> (file: File, err: Read_Error) { - context.allocator = allocator; + context.allocator = allocator - data, ok := os.read_entire_file(filename); + data, ok := os.read_entire_file(filename) if !ok { - err = .Unable_To_Read_File; - return; + err = .Unable_To_Read_File + return } defer if !ok { - delete(data); + delete(data) } else { - file.backing = data; + file.backing = data } - file, err = read(data, filename, print_error, allocator); - return; + file, err = read(data, filename, print_error, allocator) + return } read :: proc(data: []byte, filename := "<input>", print_error := false, allocator := context.allocator) -> (file: File, err: Read_Error) { @@ -34,182 +34,182 @@ read :: proc(data: []byte, filename := "<input>", print_error := false, allocato data: []byte, offset: int, print_error: bool, - }; + } read_value :: proc(r: ^Reader, $T: typeid) -> (value: T, err: Read_Error) { - remaining := len(r.data) - r.offset; + remaining := len(r.data) - r.offset if remaining < size_of(T) { - err = .Short_Read; - return; + err = .Short_Read + return } - ptr := raw_data(r.data[r.offset:]); - value = (^T)(ptr)^; - r.offset += size_of(T); - return; + ptr := raw_data(r.data[r.offset:]) + value = (^T)(ptr)^ + r.offset += size_of(T) + return } read_array :: proc(r: ^Reader, $T: typeid, count: int) -> (value: []T, err: Read_Error) { - remaining := len(r.data) - r.offset; + remaining := len(r.data) - r.offset if remaining < size_of(T)*count { - err = .Short_Read; - return; + err = .Short_Read + return } - ptr := raw_data(r.data[r.offset:]); + ptr := raw_data(r.data[r.offset:]) - value = mem.slice_ptr((^T)(ptr), count); - r.offset += size_of(T)*count; - return; + value = mem.slice_ptr((^T)(ptr), count) + r.offset += size_of(T)*count + return } read_string :: proc(r: ^Reader, count: int) -> (string, Read_Error) { - buf, err := read_array(r, byte, count); - return string(buf), err; + buf, err := read_array(r, byte, count) + return string(buf), err } read_name :: proc(r: ^Reader) -> (value: string, err: Read_Error) { - len := read_value(r, u8) or_return; - data := read_array(r, byte, int(len)) or_return; - return string(data[:len]), nil; + len := read_value(r, u8) or_return + data := read_array(r, byte, int(len)) or_return + return string(data[:len]), nil } read_meta :: proc(r: ^Reader, capacity: u32le) -> (meta_data: []Meta, err: Read_Error) { - meta_data = make([]Meta, int(capacity)); - count := 0; - defer meta_data = meta_data[:count]; + meta_data = make([]Meta, int(capacity)) + count := 0 + defer meta_data = meta_data[:count] for m in &meta_data { - m.name = read_name(r) or_return; + m.name = read_name(r) or_return - type := read_value(r, Meta_Value_Type) or_return; + type := read_value(r, Meta_Value_Type) or_return if type > max(Meta_Value_Type) { if r.print_error { - fmt.eprintf("HxA Error: file '%s' has meta value type %d. Maximum value is ", r.filename, u8(type), u8(max(Meta_Value_Type))); + fmt.eprintf("HxA Error: file '%s' has meta value type %d. Maximum value is ", r.filename, u8(type), u8(max(Meta_Value_Type))) } - err = .Invalid_Data; - return; + err = .Invalid_Data + return } - array_length := read_value(r, u32le) or_return; + array_length := read_value(r, u32le) or_return switch type { - case .Int64: m.value = read_array(r, i64le, int(array_length)) or_return; - case .Double: m.value = read_array(r, f64le, int(array_length)) or_return; - case .Node: m.value = read_array(r, Node_Index, int(array_length)) or_return; - case .Text: m.value = read_string(r, int(array_length)) or_return; - case .Binary: m.value = read_array(r, byte, int(array_length)) or_return; - case .Meta: m.value = read_meta(r, array_length) or_return; + case .Int64: m.value = read_array(r, i64le, int(array_length)) or_return + case .Double: m.value = read_array(r, f64le, int(array_length)) or_return + case .Node: m.value = read_array(r, Node_Index, int(array_length)) or_return + case .Text: m.value = read_string(r, int(array_length)) or_return + case .Binary: m.value = read_array(r, byte, int(array_length)) or_return + case .Meta: m.value = read_meta(r, array_length) or_return } - count += 1; + count += 1 } - return; + return } read_layer_stack :: proc(r: ^Reader, capacity: u32le) -> (layers: Layer_Stack, err: Read_Error) { - stack_count := read_value(r, u32le) or_return; - layer_count := 0; - layers = make(Layer_Stack, stack_count); - defer layers = layers[:layer_count]; + stack_count := read_value(r, u32le) or_return + layer_count := 0 + layers = make(Layer_Stack, stack_count) + defer layers = layers[:layer_count] for layer in &layers { - layer.name = read_name(r) or_return; - layer.components = read_value(r, u8) or_return; - type := read_value(r, Layer_Data_Type) or_return; + layer.name = read_name(r) or_return + layer.components = read_value(r, u8) or_return + type := read_value(r, Layer_Data_Type) or_return if type > max(type) { if r.print_error { - fmt.eprintf("HxA Error: file '%s' has layer data type %d. Maximum value is ", r.filename, u8(type), u8(max(Layer_Data_Type))); + fmt.eprintf("HxA Error: file '%s' has layer data type %d. Maximum value is ", r.filename, u8(type), u8(max(Layer_Data_Type))) } - err = .Invalid_Data; - return; + err = .Invalid_Data + return } - data_len := int(layer.components) * int(capacity); + data_len := int(layer.components) * int(capacity) switch type { - case .Uint8: layer.data = read_array(r, u8, data_len) or_return; - case .Int32: layer.data = read_array(r, i32le, data_len) or_return; - case .Float: layer.data = read_array(r, f32le, data_len) or_return; - case .Double: layer.data = read_array(r, f64le, data_len) or_return; + case .Uint8: layer.data = read_array(r, u8, data_len) or_return + case .Int32: layer.data = read_array(r, i32le, data_len) or_return + case .Float: layer.data = read_array(r, f32le, data_len) or_return + case .Double: layer.data = read_array(r, f64le, data_len) or_return } - layer_count += 1; + layer_count += 1 } - return; + return } if len(data) < size_of(Header) { - return; + return } - context.allocator = allocator; + context.allocator = allocator - header := cast(^Header)raw_data(data); - assert(header.magic_number == MAGIC_NUMBER); + header := cast(^Header)raw_data(data) + assert(header.magic_number == MAGIC_NUMBER) r := &Reader{ filename = filename, data = data[:], offset = size_of(Header), print_error = print_error, - }; + } - node_count := 0; - file.nodes = make([]Node, header.internal_node_count); + node_count := 0 + file.nodes = make([]Node, header.internal_node_count) defer if err != nil { - nodes_destroy(file.nodes); - file.nodes = nil; + nodes_destroy(file.nodes) + file.nodes = nil } - defer file.nodes = file.nodes[:node_count]; + defer file.nodes = file.nodes[:node_count] for node_idx in 0..<header.internal_node_count { - node := &file.nodes[node_count]; - type := read_value(r, Node_Type) or_return; + node := &file.nodes[node_count] + type := read_value(r, Node_Type) or_return if type > max(Node_Type) { if r.print_error { - fmt.eprintf("HxA Error: file '%s' has node type %d. Maximum value is ", r.filename, u8(type), u8(max(Node_Type))); + fmt.eprintf("HxA Error: file '%s' has node type %d. Maximum value is ", r.filename, u8(type), u8(max(Node_Type))) } - err = .Invalid_Data; - return; + err = .Invalid_Data + return } - node_count += 1; + node_count += 1 - node.meta_data = read_meta(r, read_value(r, u32le) or_return) or_return; + node.meta_data = read_meta(r, read_value(r, u32le) or_return) or_return switch type { case .Meta_Only: // Okay case .Geometry: - g: Node_Geometry; + g: Node_Geometry - g.vertex_count = read_value(r, u32le) or_return; - g.vertex_stack = read_layer_stack(r, g.vertex_count) or_return; - g.edge_corner_count = read_value(r, u32le) or_return; - g.corner_stack = read_layer_stack(r, g.edge_corner_count) or_return; + g.vertex_count = read_value(r, u32le) or_return + g.vertex_stack = read_layer_stack(r, g.vertex_count) or_return + g.edge_corner_count = read_value(r, u32le) or_return + g.corner_stack = read_layer_stack(r, g.edge_corner_count) or_return if header.version > 2 { - g.edge_stack = read_layer_stack(r, g.edge_corner_count) or_return; + g.edge_stack = read_layer_stack(r, g.edge_corner_count) or_return } - g.face_count = read_value(r, u32le) or_return; - g.face_stack = read_layer_stack(r, g.face_count) or_return; + g.face_count = read_value(r, u32le) or_return + g.face_stack = read_layer_stack(r, g.face_count) or_return - node.content = g; + node.content = g case .Image: - img: Node_Image; + img: Node_Image - img.type = read_value(r, Image_Type) or_return; - dimensions := int(img.type); + img.type = read_value(r, Image_Type) or_return + dimensions := int(img.type) if img.type == .Image_Cube { - dimensions = 2; + dimensions = 2 } - img.resolution = {1, 1, 1}; + img.resolution = {1, 1, 1} for d in 0..<dimensions { - img.resolution[d] = read_value(r, u32le) or_return; + img.resolution[d] = read_value(r, u32le) or_return } - size := img.resolution[0]*img.resolution[1]*img.resolution[2]; + size := img.resolution[0]*img.resolution[1]*img.resolution[2] if img.type == .Image_Cube { - size *= 6; + size *= 6 } - img.image_stack = read_layer_stack(r, size) or_return; + img.image_stack = read_layer_stack(r, size) or_return - node.content = img; + node.content = img } } - return; + return } diff --git a/core/encoding/hxa/write.odin b/core/encoding/hxa/write.odin index 4391e700a..e774018b2 100644 --- a/core/encoding/hxa/write.odin +++ b/core/encoding/hxa/write.odin @@ -10,36 +10,36 @@ Write_Error :: enum { } write_to_file :: proc(filepath: string, file: File) -> (err: Write_Error) { - required := required_write_size(file); - buf, alloc_err := make([]byte, required); + required := required_write_size(file) + buf, alloc_err := make([]byte, required) if alloc_err == .Out_Of_Memory { - return .Failed_File_Write; + return .Failed_File_Write } - defer delete(buf); + defer delete(buf) - write_internal(&Writer{data = buf}, file); + write_internal(&Writer{data = buf}, file) if !os.write_entire_file(filepath, buf) { - err =.Failed_File_Write; + err =.Failed_File_Write } - return; + return } write :: proc(buf: []byte, file: File) -> (n: int, err: Write_Error) { - required := required_write_size(file); + required := required_write_size(file) if len(buf) < required { - err = .Buffer_Too_Small; - return; + err = .Buffer_Too_Small + return } - n = required; - write_internal(&Writer{data = buf}, file); - return; + n = required + write_internal(&Writer{data = buf}, file) + return } required_write_size :: proc(file: File) -> (n: int) { - writer := &Writer{dummy_pass = true}; - write_internal(writer, file); - n = writer.offset; - return; + writer := &Writer{dummy_pass = true} + write_internal(writer, file) + n = writer.offset + return } @@ -48,146 +48,146 @@ Writer :: struct { data: []byte, offset: int, dummy_pass: bool, -}; +} @(private) write_internal :: proc(w: ^Writer, file: File) { write_value :: proc(w: ^Writer, value: $T) { if !w.dummy_pass { - remaining := len(w.data) - w.offset; - assert(size_of(T) <= remaining); - ptr := raw_data(w.data[w.offset:]); - (^T)(ptr)^ = value; + remaining := len(w.data) - w.offset + assert(size_of(T) <= remaining) + ptr := raw_data(w.data[w.offset:]) + (^T)(ptr)^ = value } - w.offset += size_of(T); + w.offset += size_of(T) } write_array :: proc(w: ^Writer, array: []$T) { if !w.dummy_pass { - remaining := len(w.data) - w.offset; - assert(size_of(T)*len(array) <= remaining); - ptr := raw_data(w.data[w.offset:]); - dst := mem.slice_ptr((^T)(ptr), len(array)); - copy(dst, array); + remaining := len(w.data) - w.offset + assert(size_of(T)*len(array) <= remaining) + ptr := raw_data(w.data[w.offset:]) + dst := mem.slice_ptr((^T)(ptr), len(array)) + copy(dst, array) } - w.offset += size_of(T)*len(array); + w.offset += size_of(T)*len(array) } write_string :: proc(w: ^Writer, str: string) { if !w.dummy_pass { - remaining := len(w.data) - w.offset; - assert(size_of(byte)*len(str) <= remaining); - ptr := raw_data(w.data[w.offset:]); - dst := mem.slice_ptr((^byte)(ptr), len(str)); - copy(dst, str); + remaining := len(w.data) - w.offset + assert(size_of(byte)*len(str) <= remaining) + ptr := raw_data(w.data[w.offset:]) + dst := mem.slice_ptr((^byte)(ptr), len(str)) + copy(dst, str) } - w.offset += size_of(byte)*len(str); + w.offset += size_of(byte)*len(str) } write_metadata :: proc(w: ^Writer, meta_data: []Meta) { for m in meta_data { - name_len := max(len(m.name), 255); - write_value(w, u8(name_len)); - write_string(w, m.name[:name_len]); + name_len := max(len(m.name), 255) + write_value(w, u8(name_len)) + write_string(w, m.name[:name_len]) - meta_data_type: Meta_Value_Type; - length: u32le = 0; + meta_data_type: Meta_Value_Type + length: u32le = 0 switch v in m.value { case []i64le: - meta_data_type = .Int64; - length = u32le(len(v)); + meta_data_type = .Int64 + length = u32le(len(v)) case []f64le: - meta_data_type = .Double; - length = u32le(len(v)); + meta_data_type = .Double + length = u32le(len(v)) case []Node_Index: - meta_data_type = .Node; - length = u32le(len(v)); + meta_data_type = .Node + length = u32le(len(v)) case string: - meta_data_type = .Text; - length = u32le(len(v)); + meta_data_type = .Text + length = u32le(len(v)) case []byte: - meta_data_type = .Binary; - length = u32le(len(v)); + meta_data_type = .Binary + length = u32le(len(v)) case []Meta: - meta_data_type = .Meta; - length = u32le(len(v)); + meta_data_type = .Meta + length = u32le(len(v)) } - write_value(w, meta_data_type); - write_value(w, length); + write_value(w, meta_data_type) + write_value(w, length) switch v in m.value { - case []i64le: write_array(w, v); - case []f64le: write_array(w, v); - case []Node_Index: write_array(w, v); - case string: write_string(w, v); - case []byte: write_array(w, v); - case []Meta: write_metadata(w, v); + case []i64le: write_array(w, v) + case []f64le: write_array(w, v) + case []Node_Index: write_array(w, v) + case string: write_string(w, v) + case []byte: write_array(w, v) + case []Meta: write_metadata(w, v) } } - return; + return } write_layer_stack :: proc(w: ^Writer, layers: Layer_Stack) { - write_value(w, u32(len(layers))); + write_value(w, u32(len(layers))) for layer in layers { - name_len := max(len(layer.name), 255); - write_value(w, u8(name_len)); - write_string(w, layer .name[:name_len]); + name_len := max(len(layer.name), 255) + write_value(w, u8(name_len)) + write_string(w, layer .name[:name_len]) - write_value(w, layer.components); + write_value(w, layer.components) - layer_data_type: Layer_Data_Type; + layer_data_type: Layer_Data_Type switch v in layer.data { - case []u8: layer_data_type = .Uint8; - case []i32le: layer_data_type = .Int32; - case []f32le: layer_data_type = .Float; - case []f64le: layer_data_type = .Double; + case []u8: layer_data_type = .Uint8 + case []i32le: layer_data_type = .Int32 + case []f32le: layer_data_type = .Float + case []f64le: layer_data_type = .Double } - write_value(w, layer_data_type); + write_value(w, layer_data_type) switch v in layer.data { - case []u8: write_array(w, v); - case []i32le: write_array(w, v); - case []f32le: write_array(w, v); - case []f64le: write_array(w, v); + case []u8: write_array(w, v) + case []i32le: write_array(w, v) + case []f32le: write_array(w, v) + case []f64le: write_array(w, v) } } - return; + return } write_value(w, &Header{ magic_number = MAGIC_NUMBER, version = LATEST_VERSION, internal_node_count = u32le(len(file.nodes)), - }); + }) for node in file.nodes { - node_type: Node_Type; + node_type: Node_Type switch content in node.content { - case Node_Geometry: node_type = .Geometry; - case Node_Image: node_type = .Image; + case Node_Geometry: node_type = .Geometry + case Node_Image: node_type = .Image } - write_value(w, node_type); + write_value(w, node_type) - write_value(w, u32(len(node.meta_data))); - write_metadata(w, node.meta_data); + write_value(w, u32(len(node.meta_data))) + write_metadata(w, node.meta_data) switch content in node.content { case Node_Geometry: - write_value(w, content.vertex_count); - write_layer_stack(w, content.vertex_stack); - write_value(w, content.edge_corner_count); - write_layer_stack(w, content.corner_stack); - write_layer_stack(w, content.edge_stack); - write_value(w, content.face_count); - write_layer_stack(w, content.face_stack); + write_value(w, content.vertex_count) + write_layer_stack(w, content.vertex_stack) + write_value(w, content.edge_corner_count) + write_layer_stack(w, content.corner_stack) + write_layer_stack(w, content.edge_stack) + write_value(w, content.face_count) + write_layer_stack(w, content.face_stack) case Node_Image: - write_value(w, content.type); - dimensions := int(content.type); + write_value(w, content.type) + dimensions := int(content.type) if content.type == .Image_Cube { - dimensions = 2; + dimensions = 2 } for d in 0..<dimensions { - write_value(w, content.resolution[d]); + write_value(w, content.resolution[d]) } - write_layer_stack(w, content.image_stack); + write_layer_stack(w, content.image_stack) } } } diff --git a/core/encoding/json/marshal.odin b/core/encoding/json/marshal.odin index d9a674d33..cea3c3df6 100644 --- a/core/encoding/json/marshal.odin +++ b/core/encoding/json/marshal.odin @@ -13,305 +13,305 @@ Marshal_Error :: enum { } marshal :: proc(v: any, allocator := context.allocator) -> ([]byte, Marshal_Error) { - b: strings.Builder; - strings.init_builder(&b, allocator); + b: strings.Builder + strings.init_builder(&b, allocator) - err := marshal_arg(&b, v); + err := marshal_arg(&b, v) if err != .None { - strings.destroy_builder(&b); - return nil, err; + strings.destroy_builder(&b) + return nil, err } if len(b.buf) == 0 { - strings.destroy_builder(&b); - return nil, err; + strings.destroy_builder(&b) + return nil, err } - return b.buf[:], err; + return b.buf[:], err } marshal_arg :: proc(b: ^strings.Builder, v: any) -> Marshal_Error { if v == nil { - strings.write_string(b, "null"); - return .None; + strings.write_string(b, "null") + return .None } - ti := runtime.type_info_base(type_info_of(v.id)); - a := any{v.data, ti.id}; + ti := runtime.type_info_base(type_info_of(v.id)) + a := any{v.data, ti.id} switch info in ti.variant { case runtime.Type_Info_Named: - unreachable(); + unreachable() case runtime.Type_Info_Integer: - buf: [21]byte; - u: u64; + buf: [21]byte + u: u64 switch i in a { - case i8: u = u64(i); - case i16: u = u64(i); - case i32: u = u64(i); - case i64: u = u64(i); - case int: u = u64(i); - case u8: u = u64(i); - case u16: u = u64(i); - case u32: u = u64(i); - case u64: u = u64(i); - case uint: u = u64(i); - case uintptr: u = u64(i); - - case i16le: u = u64(i); - case i32le: u = u64(i); - case i64le: u = u64(i); - case u16le: u = u64(i); - case u32le: u = u64(i); - case u64le: u = u64(i); - - case i16be: u = u64(i); - case i32be: u = u64(i); - case i64be: u = u64(i); - case u16be: u = u64(i); - case u32be: u = u64(i); - case u64be: u = u64(i); + case i8: u = u64(i) + case i16: u = u64(i) + case i32: u = u64(i) + case i64: u = u64(i) + case int: u = u64(i) + case u8: u = u64(i) + case u16: u = u64(i) + case u32: u = u64(i) + case u64: u = u64(i) + case uint: u = u64(i) + case uintptr: u = u64(i) + + case i16le: u = u64(i) + case i32le: u = u64(i) + case i64le: u = u64(i) + case u16le: u = u64(i) + case u32le: u = u64(i) + case u64le: u = u64(i) + + case i16be: u = u64(i) + case i32be: u = u64(i) + case i64be: u = u64(i) + case u16be: u = u64(i) + case u32be: u = u64(i) + case u64be: u = u64(i) } - s := strconv.append_bits(buf[:], u, 10, info.signed, 8*ti.size, "0123456789", nil); - strings.write_string(b, s); + s := strconv.append_bits(buf[:], u, 10, info.signed, 8*ti.size, "0123456789", nil) + strings.write_string(b, s) case runtime.Type_Info_Rune: - r := a.(rune); - strings.write_byte(b, '"'); - strings.write_escaped_rune(b, r, '"', true); - strings.write_byte(b, '"'); + r := a.(rune) + strings.write_byte(b, '"') + strings.write_escaped_rune(b, r, '"', true) + strings.write_byte(b, '"') case runtime.Type_Info_Float: - val: f64; + val: f64 switch f in a { - case f16: val = f64(f); - case f32: val = f64(f); - case f64: val = f64(f); + case f16: val = f64(f) + case f32: val = f64(f) + case f64: val = f64(f) } - buf: [386]byte; + buf: [386]byte - str := strconv.append_float(buf[1:], val, 'f', 2*ti.size, 8*ti.size); - s := buf[:len(str)+1]; + str := strconv.append_float(buf[1:], val, 'f', 2*ti.size, 8*ti.size) + s := buf[:len(str)+1] if s[1] == '+' || s[1] == '-' { - s = s[1:]; + s = s[1:] } else { - s[0] = '+'; + s[0] = '+' } if s[0] == '+' { - s = s[1:]; + s = s[1:] } - strings.write_string(b, string(s)); + strings.write_string(b, string(s)) case runtime.Type_Info_Complex: - return .Unsupported_Type; + return .Unsupported_Type case runtime.Type_Info_Quaternion: - return .Unsupported_Type; + return .Unsupported_Type case runtime.Type_Info_String: switch s in a { - case string: strings.write_quoted_string(b, s); - case cstring: strings.write_quoted_string(b, string(s)); + case string: strings.write_quoted_string(b, s) + case cstring: strings.write_quoted_string(b, string(s)) } case runtime.Type_Info_Boolean: - val: bool; + val: bool switch b in a { - case bool: val = bool(b); - case b8: val = bool(b); - case b16: val = bool(b); - case b32: val = bool(b); - case b64: val = bool(b); + case bool: val = bool(b) + case b8: val = bool(b) + case b16: val = bool(b) + case b32: val = bool(b) + case b64: val = bool(b) } - strings.write_string(b, val ? "true" : "false"); + strings.write_string(b, val ? "true" : "false") case runtime.Type_Info_Any: - return .Unsupported_Type; + return .Unsupported_Type case runtime.Type_Info_Type_Id: - return .Unsupported_Type; + return .Unsupported_Type case runtime.Type_Info_Pointer: - return .Unsupported_Type; + return .Unsupported_Type case runtime.Type_Info_Multi_Pointer: - return .Unsupported_Type; + return .Unsupported_Type case runtime.Type_Info_Procedure: - return .Unsupported_Type; + return .Unsupported_Type case runtime.Type_Info_Tuple: - return .Unsupported_Type; + return .Unsupported_Type case runtime.Type_Info_Enumerated_Array: - return .Unsupported_Type; + return .Unsupported_Type case runtime.Type_Info_Simd_Vector: - return .Unsupported_Type; + return .Unsupported_Type case runtime.Type_Info_Relative_Pointer: - return .Unsupported_Type; + return .Unsupported_Type case runtime.Type_Info_Relative_Slice: - return .Unsupported_Type; + return .Unsupported_Type case runtime.Type_Info_Array: - strings.write_byte(b, '['); + strings.write_byte(b, '[') for i in 0..<info.count { if i > 0 { strings.write_string(b, ", "); } - data := uintptr(v.data) + uintptr(i*info.elem_size); - marshal_arg(b, any{rawptr(data), info.elem.id}); + data := uintptr(v.data) + uintptr(i*info.elem_size) + marshal_arg(b, any{rawptr(data), info.elem.id}) } - strings.write_byte(b, ']'); + strings.write_byte(b, ']') case runtime.Type_Info_Dynamic_Array: - strings.write_byte(b, '['); - array := cast(^mem.Raw_Dynamic_Array)v.data; + strings.write_byte(b, '[') + array := cast(^mem.Raw_Dynamic_Array)v.data for i in 0..<array.len { if i > 0 { strings.write_string(b, ", "); } - data := uintptr(array.data) + uintptr(i*info.elem_size); - marshal_arg(b, any{rawptr(data), info.elem.id}); + data := uintptr(array.data) + uintptr(i*info.elem_size) + marshal_arg(b, any{rawptr(data), info.elem.id}) } - strings.write_byte(b, ']'); + strings.write_byte(b, ']') case runtime.Type_Info_Slice: - strings.write_byte(b, '['); - slice := cast(^mem.Raw_Slice)v.data; + strings.write_byte(b, '[') + slice := cast(^mem.Raw_Slice)v.data for i in 0..<slice.len { if i > 0 { strings.write_string(b, ", "); } - data := uintptr(slice.data) + uintptr(i*info.elem_size); - marshal_arg(b, any{rawptr(data), info.elem.id}); + data := uintptr(slice.data) + uintptr(i*info.elem_size) + marshal_arg(b, any{rawptr(data), info.elem.id}) } - strings.write_byte(b, ']'); + strings.write_byte(b, ']') case runtime.Type_Info_Map: - m := (^mem.Raw_Map)(v.data); + m := (^mem.Raw_Map)(v.data) - strings.write_byte(b, '{'); + strings.write_byte(b, '{') if m != nil { if info.generated_struct == nil { - return .Unsupported_Type; + return .Unsupported_Type } - entries := &m.entries; - gs := runtime.type_info_base(info.generated_struct).variant.(runtime.Type_Info_Struct); - ed := runtime.type_info_base(gs.types[1]).variant.(runtime.Type_Info_Dynamic_Array); - entry_type := ed.elem.variant.(runtime.Type_Info_Struct); - entry_size := ed.elem_size; + entries := &m.entries + gs := runtime.type_info_base(info.generated_struct).variant.(runtime.Type_Info_Struct) + ed := runtime.type_info_base(gs.types[1]).variant.(runtime.Type_Info_Dynamic_Array) + entry_type := ed.elem.variant.(runtime.Type_Info_Struct) + entry_size := ed.elem_size for i in 0..<entries.len { if i > 0 { strings.write_string(b, ", "); } - data := uintptr(entries.data) + uintptr(i*entry_size); - key := rawptr(data + entry_type.offsets[2]); - value := rawptr(data + entry_type.offsets[3]); + data := uintptr(entries.data) + uintptr(i*entry_size) + key := rawptr(data + entry_type.offsets[2]) + value := rawptr(data + entry_type.offsets[3]) - marshal_arg(b, any{key, info.key.id}); - strings.write_string(b, ": "); - marshal_arg(b, any{value, info.value.id}); + marshal_arg(b, any{key, info.key.id}) + strings.write_string(b, ": ") + marshal_arg(b, any{value, info.value.id}) } } - strings.write_byte(b, '}'); + strings.write_byte(b, '}') case runtime.Type_Info_Struct: - strings.write_byte(b, '{'); + strings.write_byte(b, '{') for name, i in info.names { if i > 0 { strings.write_string(b, ", "); } - strings.write_quoted_string(b, name); - strings.write_string(b, ": "); + strings.write_quoted_string(b, name) + strings.write_string(b, ": ") - id := info.types[i].id; - data := rawptr(uintptr(v.data) + info.offsets[i]); - marshal_arg(b, any{data, id}); + id := info.types[i].id + data := rawptr(uintptr(v.data) + info.offsets[i]) + marshal_arg(b, any{data, id}) } - strings.write_byte(b, '}'); + strings.write_byte(b, '}') case runtime.Type_Info_Union: - tag_ptr := uintptr(v.data) + info.tag_offset; - tag_any := any{rawptr(tag_ptr), info.tag_type.id}; + tag_ptr := uintptr(v.data) + info.tag_offset + tag_any := any{rawptr(tag_ptr), info.tag_type.id} - tag: i64 = -1; + tag: i64 = -1 switch i in tag_any { - case u8: tag = i64(i); - case i8: tag = i64(i); - case u16: tag = i64(i); - case i16: tag = i64(i); - case u32: tag = i64(i); - case i32: tag = i64(i); - case u64: tag = i64(i); - case i64: tag = i64(i); - case: panic("Invalid union tag type"); + case u8: tag = i64(i) + case i8: tag = i64(i) + case u16: tag = i64(i) + case i16: tag = i64(i) + case u32: tag = i64(i) + case i32: tag = i64(i) + case u64: tag = i64(i) + case i64: tag = i64(i) + case: panic("Invalid union tag type") } if v.data == nil || tag == 0 { - strings.write_string(b, "null"); + strings.write_string(b, "null") } else { - id := info.variants[tag-1].id; - marshal_arg(b, any{v.data, id}); + id := info.variants[tag-1].id + marshal_arg(b, any{v.data, id}) } case runtime.Type_Info_Enum: - return marshal_arg(b, any{v.data, info.base.id}); + return marshal_arg(b, any{v.data, info.base.id}) case runtime.Type_Info_Bit_Set: is_bit_set_different_endian_to_platform :: proc(ti: ^runtime.Type_Info) -> bool { if ti == nil { - return false; + return false } - t := runtime.type_info_base(ti); + t := runtime.type_info_base(ti) #partial switch info in t.variant { case runtime.Type_Info_Integer: switch info.endianness { - case .Platform: return false; - case .Little: return ODIN_ENDIAN != "little"; - case .Big: return ODIN_ENDIAN != "big"; + case .Platform: return false + case .Little: return ODIN_ENDIAN != "little" + case .Big: return ODIN_ENDIAN != "big" } } - return false; + return false } - bit_data: u64; - bit_size := u64(8*ti.size); + bit_data: u64 + bit_size := u64(8*ti.size) - do_byte_swap := is_bit_set_different_endian_to_platform(info.underlying); + do_byte_swap := is_bit_set_different_endian_to_platform(info.underlying) switch bit_size { - case 0: bit_data = 0; + case 0: bit_data = 0 case 8: - x := (^u8)(v.data)^; - bit_data = u64(x); + x := (^u8)(v.data)^ + bit_data = u64(x) case 16: - x := (^u16)(v.data)^; + x := (^u16)(v.data)^ if do_byte_swap { - x = bits.byte_swap(x); + x = bits.byte_swap(x) } - bit_data = u64(x); + bit_data = u64(x) case 32: - x := (^u32)(v.data)^; + x := (^u32)(v.data)^ if do_byte_swap { - x = bits.byte_swap(x); + x = bits.byte_swap(x) } - bit_data = u64(x); + bit_data = u64(x) case 64: - x := (^u64)(v.data)^; + x := (^u64)(v.data)^ if do_byte_swap { - x = bits.byte_swap(x); + x = bits.byte_swap(x) } - bit_data = u64(x); - case: panic("unknown bit_size size"); + bit_data = u64(x) + case: panic("unknown bit_size size") } - strings.write_u64(b, bit_data); + strings.write_u64(b, bit_data) - return .Unsupported_Type; + return .Unsupported_Type } - return .None; + return .None } diff --git a/core/encoding/json/parser.odin b/core/encoding/json/parser.odin index 8fafdcda4..b71d90b96 100644 --- a/core/encoding/json/parser.odin +++ b/core/encoding/json/parser.odin @@ -15,235 +15,235 @@ Parser :: struct { } make_parser :: proc(data: []byte, spec := Specification.JSON, parse_integers := false, allocator := context.allocator) -> Parser { - p: Parser; - p.tok = make_tokenizer(data, spec, parse_integers); - p.spec = spec; - p.allocator = allocator; - assert(p.allocator.procedure != nil); - advance_token(&p); - return p; + p: Parser + p.tok = make_tokenizer(data, spec, parse_integers) + p.spec = spec + p.allocator = allocator + assert(p.allocator.procedure != nil) + advance_token(&p) + return p } parse :: proc(data: []byte, spec := Specification.JSON, parse_integers := false, allocator := context.allocator) -> (Value, Error) { - context.allocator = allocator; - p := make_parser(data, spec, parse_integers, allocator); + context.allocator = allocator + p := make_parser(data, spec, parse_integers, allocator) if p.spec == Specification.JSON5 { - return parse_value(&p); + return parse_value(&p) } - return parse_object(&p); + return parse_object(&p) } token_end_pos :: proc(tok: Token) -> Pos { - end := tok.pos; - end.offset += len(tok.text); - return end; + end := tok.pos + end.offset += len(tok.text) + return end } advance_token :: proc(p: ^Parser) -> (Token, Error) { - err: Error; - p.prev_token = p.curr_token; - p.curr_token, err = get_token(&p.tok); - return p.prev_token, err; + err: Error + p.prev_token = p.curr_token + p.curr_token, err = get_token(&p.tok) + return p.prev_token, err } allow_token :: proc(p: ^Parser, kind: Token_Kind) -> bool { if p.curr_token.kind == kind { - advance_token(p); - return true; + advance_token(p) + return true } - return false; + return false } expect_token :: proc(p: ^Parser, kind: Token_Kind) -> Error { - prev := p.curr_token; - advance_token(p); + prev := p.curr_token + advance_token(p) if prev.kind == kind { - return .None; + return .None } - return .Unexpected_Token; + return .Unexpected_Token } parse_value :: proc(p: ^Parser) -> (value: Value, err: Error) { - token := p.curr_token; + token := p.curr_token #partial switch token.kind { case .Null: - value = Null{}; - advance_token(p); - return; + value = Null{} + advance_token(p) + return case .False: - value = Boolean(false); - advance_token(p); - return; + value = Boolean(false) + advance_token(p) + return case .True: - value = Boolean(true); - advance_token(p); - return; + value = Boolean(true) + advance_token(p) + return case .Integer: - i, _ := strconv.parse_i64(token.text); - value = Integer(i); - advance_token(p); - return; + i, _ := strconv.parse_i64(token.text) + value = Integer(i) + advance_token(p) + return case .Float: - f, _ := strconv.parse_f64(token.text); - value = Float(f); - advance_token(p); - return; + f, _ := strconv.parse_f64(token.text) + value = Float(f) + advance_token(p) + return case .String: - value = String(unquote_string(token, p.spec, p.allocator)); - advance_token(p); - return; + value = String(unquote_string(token, p.spec, p.allocator)) + advance_token(p) + return case .Open_Brace: - return parse_object(p); + return parse_object(p) case .Open_Bracket: - return parse_array(p); + return parse_array(p) case: if p.spec == Specification.JSON5 { #partial switch token.kind { case .Infinity: - inf: u64 = 0x7ff0000000000000; + inf: u64 = 0x7ff0000000000000 if token.text[0] == '-' { - inf = 0xfff0000000000000; + inf = 0xfff0000000000000 } - value = transmute(f64)inf; - advance_token(p); - return; + value = transmute(f64)inf + advance_token(p) + return case .NaN: - nan: u64 = 0x7ff7ffffffffffff; + nan: u64 = 0x7ff7ffffffffffff if token.text[0] == '-' { - nan = 0xfff7ffffffffffff; + nan = 0xfff7ffffffffffff } - value = transmute(f64)nan; - advance_token(p); - return; + value = transmute(f64)nan + advance_token(p) + return } } } - err = .Unexpected_Token; - advance_token(p); - return; + err = .Unexpected_Token + advance_token(p) + return } parse_array :: proc(p: ^Parser) -> (value: Value, err: Error) { - expect_token(p, .Open_Bracket) or_return; + expect_token(p, .Open_Bracket) or_return - array: Array; - array.allocator = p.allocator; + array: Array + array.allocator = p.allocator defer if err != .None { for elem in array { - destroy_value(elem); + destroy_value(elem) } - delete(array); + delete(array) } for p.curr_token.kind != .Close_Bracket { - elem := parse_value(p) or_return; - append(&array, elem); + elem := parse_value(p) or_return + append(&array, elem) // Disallow trailing commas for the time being if allow_token(p, .Comma) { - continue; + continue } else { - break; + break } } - expect_token(p, .Close_Bracket) or_return; - value = array; - return; + expect_token(p, .Close_Bracket) or_return + value = array + return } clone_string :: proc(s: string, allocator: mem.Allocator) -> string { - n := len(s); - b := make([]byte, n+1, allocator); - copy(b, s); - b[n] = 0; - return string(b[:n]); + n := len(s) + b := make([]byte, n+1, allocator) + copy(b, s) + b[n] = 0 + return string(b[:n]) } parse_object_key :: proc(p: ^Parser) -> (key: string, err: Error) { - tok := p.curr_token; + tok := p.curr_token if p.spec == Specification.JSON5 { if tok.kind == .String { - expect_token(p, .String); - key = unquote_string(tok, p.spec, p.allocator); - return; + expect_token(p, .String) + key = unquote_string(tok, p.spec, p.allocator) + return } else if tok.kind == .Ident { - expect_token(p, .Ident); - key = clone_string(tok.text, p.allocator); - return; + expect_token(p, .Ident) + key = clone_string(tok.text, p.allocator) + return } } if tok_err := expect_token(p, .String); tok_err != .None { - err = .Expected_String_For_Object_Key; - return; + err = .Expected_String_For_Object_Key + return } - key = unquote_string(tok, p.spec, p.allocator); - return; + key = unquote_string(tok, p.spec, p.allocator) + return } parse_object :: proc(p: ^Parser) -> (value: Value, err: Error) { - expect_token(p, .Open_Brace) or_return; + expect_token(p, .Open_Brace) or_return - obj: Object; - obj.allocator = p.allocator; + obj: Object + obj.allocator = p.allocator defer if err != .None { for key, elem in obj { - delete(key, p.allocator); - destroy_value(elem); + delete(key, p.allocator) + destroy_value(elem) } - delete(obj); + delete(obj) } for p.curr_token.kind != .Close_Brace { - key: string; - key, err = parse_object_key(p); + key: string + key, err = parse_object_key(p) if err != .None { - delete(key, p.allocator); - return; + delete(key, p.allocator) + return } if colon_err := expect_token(p, .Colon); colon_err != .None { - err = .Expected_Colon_After_Key; - return; + err = .Expected_Colon_After_Key + return } - elem := parse_value(p) or_return; + elem := parse_value(p) or_return if key in obj { - err = .Duplicate_Object_Key; - delete(key, p.allocator); - return; + err = .Duplicate_Object_Key + delete(key, p.allocator) + return } - obj[key] = elem; + obj[key] = elem if p.spec == Specification.JSON5 { // Allow trailing commas if allow_token(p, .Comma) { - continue; + continue } } else { // Disallow trailing commas if allow_token(p, .Comma) { - continue; + continue } else { - break; + break } } } - expect_token(p, .Close_Brace) or_return; - value = obj; - return; + expect_token(p, .Close_Brace) or_return + value = obj + return } @@ -251,177 +251,177 @@ parse_object :: proc(p: ^Parser) -> (value: Value, err: Error) { unquote_string :: proc(token: Token, spec: Specification, allocator := context.allocator) -> string { get_u2_rune :: proc(s: string) -> rune { if len(s) < 4 || s[0] != '\\' || s[1] != 'x' { - return -1; + return -1 } - r: rune; + r: rune for c in s[2:4] { - x: rune; + x: rune switch c { - case '0'..='9': x = c - '0'; - case 'a'..='f': x = c - 'a' + 10; - case 'A'..='F': x = c - 'A' + 10; - case: return -1; + case '0'..='9': x = c - '0' + case 'a'..='f': x = c - 'a' + 10 + case 'A'..='F': x = c - 'A' + 10 + case: return -1 } - r = r*16 + x; + r = r*16 + x } - return r; + return r } get_u4_rune :: proc(s: string) -> rune { if len(s) < 6 || s[0] != '\\' || s[1] != 'u' { - return -1; + return -1 } - r: rune; + r: rune for c in s[2:6] { - x: rune; + x: rune switch c { - case '0'..='9': x = c - '0'; - case 'a'..='f': x = c - 'a' + 10; - case 'A'..='F': x = c - 'A' + 10; - case: return -1; + case '0'..='9': x = c - '0' + case 'a'..='f': x = c - 'a' + 10 + case 'A'..='F': x = c - 'A' + 10 + case: return -1 } - r = r*16 + x; + r = r*16 + x } - return r; + return r } if token.kind != .String { - return ""; + return "" } - s := token.text; + s := token.text if len(s) <= 2 { - return ""; + return "" } - quote := s[0]; + quote := s[0] if s[0] != s[len(s)-1] { // Invalid string - return ""; + return "" } - s = s[1:len(s)-1]; + s = s[1:len(s)-1] - i := 0; + i := 0 for i < len(s) { - c := s[i]; + c := s[i] if c == '\\' || c == quote || c < ' ' { - break; + break } if c < utf8.RUNE_SELF { - i += 1; - continue; + i += 1 + continue } - r, w := utf8.decode_rune_in_string(s); + r, w := utf8.decode_rune_in_string(s) if r == utf8.RUNE_ERROR && w == 1 { - break; + break } - i += w; + i += w } if i == len(s) { - return clone_string(s, allocator); + return clone_string(s, allocator) } - b := make([]byte, len(s) + 2*utf8.UTF_MAX, allocator); - w := copy(b, s[0:i]); + b := make([]byte, len(s) + 2*utf8.UTF_MAX, allocator) + w := copy(b, s[0:i]) loop: for i < len(s) { - c := s[i]; + c := s[i] switch { case c == '\\': - i += 1; + i += 1 if i >= len(s) { - break loop; + break loop } switch s[i] { - case: break loop; + case: break loop case '"', '\'', '\\', '/': - b[w] = s[i]; - i += 1; - w += 1; + b[w] = s[i] + i += 1 + w += 1 case 'b': - b[w] = '\b'; - i += 1; - w += 1; + b[w] = '\b' + i += 1 + w += 1 case 'f': - b[w] = '\f'; - i += 1; - w += 1; + b[w] = '\f' + i += 1 + w += 1 case 'r': - b[w] = '\r'; - i += 1; - w += 1; + b[w] = '\r' + i += 1 + w += 1 case 't': - b[w] = '\t'; - i += 1; - w += 1; + b[w] = '\t' + i += 1 + w += 1 case 'n': - b[w] = '\n'; - i += 1; - w += 1; + b[w] = '\n' + i += 1 + w += 1 case 'u': - i -= 1; // Include the \u in the check for sanity sake - r := get_u4_rune(s[i:]); + i -= 1 // Include the \u in the check for sanity sake + r := get_u4_rune(s[i:]) if r < 0 { - break loop; + break loop } - i += 6; + i += 6 - buf, buf_width := utf8.encode_rune(r); - copy(b[w:], buf[:buf_width]); - w += buf_width; + buf, buf_width := utf8.encode_rune(r) + copy(b[w:], buf[:buf_width]) + w += buf_width case '0': if spec == Specification.JSON5 { - b[w] = '\x00'; - i += 1; - w += 1; + b[w] = '\x00' + i += 1 + w += 1 } else { - break loop; + break loop } case 'v': if spec == Specification.JSON5 { - b[w] = '\v'; - i += 1; - w += 1; + b[w] = '\v' + i += 1 + w += 1 } else { - break loop; + break loop } case 'x': if spec == Specification.JSON5 { - i -= 1; // Include the \x in the check for sanity sake - r := get_u2_rune(s[i:]); + i -= 1 // Include the \x in the check for sanity sake + r := get_u2_rune(s[i:]) if r < 0 { - break loop; + break loop } - i += 4; + i += 4 - buf, buf_width := utf8.encode_rune(r); - copy(b[w:], buf[:buf_width]); - w += buf_width; + buf, buf_width := utf8.encode_rune(r) + copy(b[w:], buf[:buf_width]) + w += buf_width } else { - break loop; + break loop } } case c == quote, c < ' ': - break loop; + break loop case c < utf8.RUNE_SELF: - b[w] = c; - i += 1; - w += 1; + b[w] = c + i += 1 + w += 1 case: - r, width := utf8.decode_rune_in_string(s[i:]); - i += width; + r, width := utf8.decode_rune_in_string(s[i:]) + i += width - buf, buf_width := utf8.encode_rune(r); - assert(buf_width <= width); - copy(b[w:], buf[:buf_width]); - w += buf_width; + buf, buf_width := utf8.encode_rune(r) + assert(buf_width <= width) + copy(b[w:], buf[:buf_width]) + w += buf_width } } - return string(b[:w]); + return string(b[:w]) } diff --git a/core/encoding/json/tokenizer.odin b/core/encoding/json/tokenizer.odin index 7bd2c5283..69ae81bd1 100644 --- a/core/encoding/json/tokenizer.odin +++ b/core/encoding/json/tokenizer.odin @@ -54,22 +54,22 @@ Tokenizer :: struct { make_tokenizer :: proc(data: []byte, spec := Specification.JSON, parse_integers := false) -> Tokenizer { - t := Tokenizer{pos = {line=1}, data = data, spec = spec, parse_integers = parse_integers}; - next_rune(&t); + t := Tokenizer{pos = {line=1}, data = data, spec = spec, parse_integers = parse_integers} + next_rune(&t) if t.r == utf8.RUNE_BOM { - next_rune(&t); + next_rune(&t) } - return t; + return t } next_rune :: proc(t: ^Tokenizer) -> rune #no_bounds_check { if t.offset >= len(t.data) { - return utf8.RUNE_EOF; + return utf8.RUNE_EOF } - t.offset += t.w; - t.r, t.w = utf8.decode_rune(t.data[t.offset:]); - t.pos.column = t.offset - t.curr_line_offset; - return t.r; + t.offset += t.w + t.r, t.w = utf8.decode_rune(t.data[t.offset:]) + t.pos.column = t.offset - t.curr_line_offset + return t.r } @@ -79,19 +79,19 @@ get_token :: proc(t: ^Tokenizer) -> (token: Token, err: Error) { if '0' <= t.r && t.r <= '9' { // Okay } else { - return; + return } - next_rune(t); + next_rune(t) } } skip_hex_digits :: proc(t: ^Tokenizer) { for t.offset < len(t.data) { - next_rune(t); + next_rune(t) switch t.r { case '0'..='9', 'a'..='f', 'A'..='F': // Okay case: - return; + return } } } @@ -99,56 +99,56 @@ get_token :: proc(t: ^Tokenizer) -> (token: Token, err: Error) { scan_espace :: proc(t: ^Tokenizer) -> bool { switch t.r { case '"', '\'', '\\', '/', 'b', 'n', 'r', 't', 'f': - next_rune(t); - return true; + next_rune(t) + return true case 'u': // Expect 4 hexadecimal digits for i := 0; i < 4; i += 1 { - r := next_rune(t); + r := next_rune(t) switch r { case '0'..='9', 'a'..='f', 'A'..='F': // Okay case: - return false; + return false } } - return true; + return true case: // Ignore the next rune regardless - next_rune(t); + next_rune(t) } - return false; + return false } skip_whitespace :: proc(t: ^Tokenizer) -> rune { loop: for t.offset < len(t.data) { switch t.r { case ' ', '\t', '\v', '\f', '\r': - next_rune(t); + next_rune(t) case '\n': - t.line += 1; - t.curr_line_offset = t.offset; - t.pos.column = 1; - next_rune(t); + t.line += 1 + t.curr_line_offset = t.offset + t.pos.column = 1 + next_rune(t) case: if t.spec == .JSON5 { switch t.r { case 0x2028, 0x2029, 0xFEFF: - next_rune(t); - continue loop; + next_rune(t) + continue loop } } - break loop; + break loop } } - return t.r; + return t.r } skip_to_next_line :: proc(t: ^Tokenizer) { for t.offset < len(t.data) { - r := next_rune(t); + r := next_rune(t) if r == '\n' { - return; + return } } } @@ -157,53 +157,53 @@ get_token :: proc(t: ^Tokenizer) -> (token: Token, err: Error) { for t.offset < len(t.data) { switch next_rune(t) { case 'A'..='Z', 'a'..='z', '0'..='9', '_': - continue; + continue } - return; + return } } - skip_whitespace(t); + skip_whitespace(t) - token.pos = t.pos; + token.pos = t.pos - token.kind = .Invalid; + token.kind = .Invalid - curr_rune := t.r; - next_rune(t); + curr_rune := t.r + next_rune(t) block: switch curr_rune { case utf8.RUNE_ERROR: - err = .Illegal_Character; + err = .Illegal_Character case utf8.RUNE_EOF, '\x00': - token.kind = .EOF; - err = .EOF; + token.kind = .EOF + err = .EOF case 'A'..='Z', 'a'..='z', '_': - token.kind = .Ident; + token.kind = .Ident - skip_alphanum(t); + skip_alphanum(t) switch str := string(t.data[token.offset:t.offset]); str { - case "null": token.kind = .Null; - case "false": token.kind = .False; - case "true": token.kind = .True; + case "null": token.kind = .Null + case "false": token.kind = .False + case "true": token.kind = .True case: if t.spec == .JSON5 { switch str { - case "Infinity": token.kind = .Infinity; - case "NaN": token.kind = .NaN; + case "Infinity": token.kind = .Infinity + case "NaN": token.kind = .NaN } } } case '+': - err = .Illegal_Character; + err = .Illegal_Character if t.spec != .JSON5 { - break; + break } - fallthrough; + fallthrough case '-': switch t.r { @@ -211,281 +211,281 @@ get_token :: proc(t: ^Tokenizer) -> (token: Token, err: Error) { // Okay case: // Illegal use of +/- - err = .Illegal_Character; + err = .Illegal_Character if t.spec == .JSON5 { if t.r == 'I' || t.r == 'N' { - skip_alphanum(t); + skip_alphanum(t) } switch string(t.data[token.offset:t.offset]) { - case "-Infinity": token.kind = .Infinity; - case "-NaN": token.kind = .NaN; + case "-Infinity": token.kind = .Infinity + case "-NaN": token.kind = .NaN } } - break block; + break block } - fallthrough; + fallthrough case '0'..='9': - token.kind = t.parse_integers ? .Integer : .Float; + token.kind = t.parse_integers ? .Integer : .Float if t.spec == .JSON5 { // Hexadecimal Numbers if curr_rune == '0' && (t.r == 'x' || t.r == 'X') { - next_rune(t); - skip_hex_digits(t); - break; + next_rune(t) + skip_hex_digits(t) + break } } - skip_digits(t); + skip_digits(t) if t.r == '.' { - token.kind = .Float; - next_rune(t); - skip_digits(t); + token.kind = .Float + next_rune(t) + skip_digits(t) } if t.r == 'e' || t.r == 'E' { switch r := next_rune(t); r { case '+', '-': - next_rune(t); + next_rune(t) } - skip_digits(t); + skip_digits(t) } - str := string(t.data[token.offset:t.offset]); + str := string(t.data[token.offset:t.offset]) if !is_valid_number(str, t.spec) { - err = .Invalid_Number; + err = .Invalid_Number } case '.': - err = .Illegal_Character; + err = .Illegal_Character if t.spec == .JSON5 { // Allow leading decimal point - skip_digits(t); + skip_digits(t) if t.r == 'e' || t.r == 'E' { switch r := next_rune(t); r { case '+', '-': - next_rune(t); + next_rune(t) } - skip_digits(t); + skip_digits(t) } - str := string(t.data[token.offset:t.offset]); + str := string(t.data[token.offset:t.offset]) if !is_valid_number(str, t.spec) { - err = .Invalid_Number; + err = .Invalid_Number } } case '\'': - err = .Illegal_Character; + err = .Illegal_Character if t.spec != .JSON5 { - break; + break } - fallthrough; + fallthrough case '"': - token.kind = .String; - quote := curr_rune; + token.kind = .String + quote := curr_rune for t.offset < len(t.data) { - r := t.r; + r := t.r if r == '\n' || r < 0 { - err = .String_Not_Terminated; - break; + err = .String_Not_Terminated + break } - next_rune(t); + next_rune(t) if r == quote { - break; + break } if r == '\\' { - scan_espace(t); + scan_espace(t) } } - str := string(t.data[token.offset : t.offset]); + str := string(t.data[token.offset : t.offset]) if !is_valid_string_literal(str, t.spec) { - err = .Invalid_String; + err = .Invalid_String } - case ',': token.kind = .Comma; - case ':': token.kind = .Colon; - case '{': token.kind = .Open_Brace; - case '}': token.kind = .Close_Brace; - case '[': token.kind = .Open_Bracket; - case ']': token.kind = .Close_Bracket; + case ',': token.kind = .Comma + case ':': token.kind = .Colon + case '{': token.kind = .Open_Brace + case '}': token.kind = .Close_Brace + case '[': token.kind = .Open_Bracket + case ']': token.kind = .Close_Bracket case '/': - err = .Illegal_Character; + err = .Illegal_Character if t.spec == .JSON5 { switch t.r { case '/': // Single-line comments - skip_to_next_line(t); - return get_token(t); + skip_to_next_line(t) + return get_token(t) case '*': // None-nested multi-line comments for t.offset < len(t.data) { - next_rune(t); + next_rune(t) if t.r == '*' { - next_rune(t); + next_rune(t) if t.r == '/' { - next_rune(t); - return get_token(t); + next_rune(t) + return get_token(t) } } } - err = .EOF; + err = .EOF } } - case: err = .Illegal_Character; + case: err = .Illegal_Character } - token.text = string(t.data[token.offset : t.offset]); + token.text = string(t.data[token.offset : t.offset]) - return; + return } is_valid_number :: proc(str: string, spec: Specification) -> bool { - s := str; + s := str if s == "" { - return false; + return false } if s[0] == '-' { - s = s[1:]; + s = s[1:] if s == "" { - return false; + return false } } else if spec == .JSON5 { if s[0] == '+' { // Allow positive sign - s = s[1:]; + s = s[1:] if s == "" { - return false; + return false } } } switch s[0] { case '0': - s = s[1:]; + s = s[1:] case '1'..='9': - s = s[1:]; + s = s[1:] for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { - s = s[1:]; + s = s[1:] } case '.': if spec == .JSON5 { // Allow leading decimal point - s = s[1:]; + s = s[1:] } else { - return false; + return false } case: - return false; + return false } if spec == .JSON5 { if len(s) == 1 && s[0] == '.' { // Allow trailing decimal point - return true; + return true } } if len(s) >= 2 && s[0] == '.' && '0' <= s[1] && s[1] <= '9' { - s = s[2:]; + s = s[2:] for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { - s = s[1:]; + s = s[1:] } } if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') { - s = s[1:]; + s = s[1:] switch s[0] { case '+', '-': - s = s[1:]; + s = s[1:] if s == "" { - return false; + return false } } for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { - s = s[1:]; + s = s[1:] } } // The string should be empty now to be valid - return s == ""; + return s == "" } is_valid_string_literal :: proc(str: string, spec: Specification) -> bool { - s := str; + s := str if len(s) < 2 { - return false; + return false } - quote := s[0]; + quote := s[0] if s[0] != s[len(s)-1] { - return false; + return false } if s[0] != '"' || s[len(s)-1] != '"' { if spec == .JSON5 { if s[0] != '\'' || s[len(s)-1] != '\'' { - return false; + return false } } else { - return false; + return false } } - s = s[1 : len(s)-1]; + s = s[1 : len(s)-1] - i := 0; + i := 0 for i < len(s) { - c := s[i]; + c := s[i] switch { case c == '\\': - i += 1; + i += 1 if i >= len(s) { - return false; + return false } switch s[i] { case '"', '\'', '\\', '/', 'b', 'n', 'r', 't', 'f': - i += 1; + i += 1 case 'u': if i >= len(s) { - return false; + return false } - hex := s[i+1:]; + hex := s[i+1:] if len(hex) < 4 { - return false; + return false } - hex = hex[:4]; - i += 5; + hex = hex[:4] + i += 5 for j := 0; j < 4; j += 1 { - c2 := hex[j]; + c2 := hex[j] switch c2 { case '0'..='9', 'a'..='z', 'A'..='Z': // Okay case: - return false; + return false } } - case: return false; + case: return false } case c == quote, c < ' ': - return false; + return false case c < utf8.RUNE_SELF: - i += 1; + i += 1 case: - r, width := utf8.decode_rune_in_string(s[i:]); + r, width := utf8.decode_rune_in_string(s[i:]) if r == utf8.RUNE_ERROR && width == 1 { - return false; + return false } - i += width; + i += width } } if i == len(s) { - return true; + return true } - return true; + return true } diff --git a/core/encoding/json/types.odin b/core/encoding/json/types.odin index 10b88d87d..27bbae432 100644 --- a/core/encoding/json/types.odin +++ b/core/encoding/json/types.odin @@ -6,13 +6,13 @@ Specification :: enum { // MJSON, // http://bitsquid.blogspot.com/2009/09/json-configuration-data.html } -Null :: distinct rawptr; -Integer :: i64; -Float :: f64; -Boolean :: bool; -String :: string; -Array :: distinct [dynamic]Value; -Object :: distinct map[string]Value; +Null :: distinct rawptr +Integer :: i64 +Float :: f64 +Boolean :: bool +String :: string +Array :: distinct [dynamic]Value +Object :: distinct map[string]Value Value :: union { Null, @@ -50,17 +50,17 @@ destroy_value :: proc(value: Value) { #partial switch v in value { case Object: for key, elem in v { - delete(key); - destroy_value(elem); + delete(key) + destroy_value(elem) } - delete(v); + delete(v) case Array: for elem in v { - destroy_value(elem); + destroy_value(elem) } - delete(v); + delete(v) case String: - delete(v); + delete(v) } } diff --git a/core/encoding/json/validator.odin b/core/encoding/json/validator.odin index 1d2f7a3ed..3f180c722 100644 --- a/core/encoding/json/validator.odin +++ b/core/encoding/json/validator.odin @@ -4,119 +4,119 @@ import "core:mem" // NOTE(bill): is_valid will not check for duplicate keys is_valid :: proc(data: []byte, spec := Specification.JSON, parse_integers := false) -> bool { - p := make_parser(data, spec, parse_integers, mem.nil_allocator()); + p := make_parser(data, spec, parse_integers, mem.nil_allocator()) if p.spec == Specification.JSON5 { - return validate_value(&p); + return validate_value(&p) } - return validate_object(&p); + return validate_object(&p) } validate_object_key :: proc(p: ^Parser) -> bool { - tok := p.curr_token; + tok := p.curr_token if p.spec == Specification.JSON5 { if tok.kind == .String { - expect_token(p, .String); - return true; + expect_token(p, .String) + return true } else if tok.kind == .Ident { - expect_token(p, .Ident); - return true; + expect_token(p, .Ident) + return true } } - err := expect_token(p, .String); - return err == Error.None; + err := expect_token(p, .String) + return err == Error.None } validate_object :: proc(p: ^Parser) -> bool { if err := expect_token(p, .Open_Brace); err != Error.None { - return false; + return false } for p.curr_token.kind != .Close_Brace { if !validate_object_key(p) { - return false; + return false } if colon_err := expect_token(p, .Colon); colon_err != Error.None { - return false; + return false } if !validate_value(p) { - return false; + return false } if p.spec == Specification.JSON5 { // Allow trailing commas if allow_token(p, .Comma) { - continue; + continue } } else { // Disallow trailing commas if allow_token(p, .Comma) { - continue; + continue } else { - break; + break } } } if err := expect_token(p, .Close_Brace); err != Error.None { - return false; + return false } - return true; + return true } validate_array :: proc(p: ^Parser) -> bool { if err := expect_token(p, .Open_Bracket); err != Error.None { - return false; + return false } for p.curr_token.kind != .Close_Bracket { if !validate_value(p) { - return false; + return false } // Disallow trailing commas for the time being if allow_token(p, .Comma) { - continue; + continue } else { - break; + break } } if err := expect_token(p, .Close_Bracket); err != Error.None { - return false; + return false } - return true; + return true } validate_value :: proc(p: ^Parser) -> bool { - token := p.curr_token; + token := p.curr_token #partial switch token.kind { case .Null, .False, .True: - advance_token(p); - return true; + advance_token(p) + return true case .Integer, .Float: - advance_token(p); - return true; + advance_token(p) + return true case .String: - advance_token(p); - return is_valid_string_literal(token.text, p.spec); + advance_token(p) + return is_valid_string_literal(token.text, p.spec) case .Open_Brace: - return validate_object(p); + return validate_object(p) case .Open_Bracket: - return validate_array(p); + return validate_array(p) case: if p.spec == Specification.JSON5 { #partial switch token.kind { case .Infinity, .NaN: - advance_token(p); - return true; + advance_token(p) + return true } } } - return false; + return false } diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index 880707031..4b48ea8ad 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -35,7 +35,7 @@ Info :: struct { } // Custom formatter signature. It returns true if the formatting was successful and false when it could not be done -User_Formatter :: #type proc(fi: ^Info, arg: any, verb: rune) -> bool; +User_Formatter :: #type proc(fi: ^Info, arg: any, verb: rune) -> bool Register_User_Formatter_Error :: enum { None, @@ -45,43 +45,43 @@ Register_User_Formatter_Error :: enum { // NOTE(bill): This is a pointer to prevent accidental additions // it is prefixed with `_` rather than marked with a private attribute so that users can access it if necessary -_user_formatters: ^map[typeid]User_Formatter; +_user_formatters: ^map[typeid]User_Formatter set_user_formatters :: proc(m: ^map[typeid]User_Formatter) { - _user_formatters = m; + _user_formatters = m } register_user_formatter :: proc(id: typeid, formatter: User_Formatter) -> Register_User_Formatter_Error { if _user_formatters == nil { - return .No_User_Formatter; + return .No_User_Formatter } if prev, found := _user_formatters[id]; found && prev != nil { - return .Formatter_Previously_Found; + return .Formatter_Previously_Found } - _user_formatters[id] = formatter; - return .None; + _user_formatters[id] = formatter + return .None } fprint :: proc(fd: os.Handle, args: ..any, sep := " ") -> int { - w, _ := io.to_writer(os.stream_from_handle(fd)); - return wprint(w=w, args=args, sep=sep); + w, _ := io.to_writer(os.stream_from_handle(fd)) + return wprint(w=w, args=args, sep=sep) } fprintln :: proc(fd: os.Handle, args: ..any, sep := " ") -> int { - w, _ := io.to_writer(os.stream_from_handle(fd)); - return wprintln(w=w, args=args, sep=sep); + w, _ := io.to_writer(os.stream_from_handle(fd)) + return wprintln(w=w, args=args, sep=sep) } fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int { - w, _ := io.to_writer(os.stream_from_handle(fd)); - return wprintf(w, fmt, ..args); + w, _ := io.to_writer(os.stream_from_handle(fd)) + return wprintf(w, fmt, ..args) } fprint_type :: proc(fd: os.Handle, info: ^runtime.Type_Info) -> int { - w, _ := io.to_writer(os.stream_from_handle(fd)); - return wprint_type(w, info); + w, _ := io.to_writer(os.stream_from_handle(fd)) + return wprint_type(w, info) } fprint_typeid :: proc(fd: os.Handle, id: typeid) -> int { - w, _ := io.to_writer(os.stream_from_handle(fd)); - return wprint_typeid(w, id); + w, _ := io.to_writer(os.stream_from_handle(fd)) + return wprint_typeid(w, id) } // print* procedures return the number of bytes written @@ -97,80 +97,80 @@ eprintf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stderr, fm // aprint* procedures return a string that was allocated with the current context // They must be freed accordingly aprint :: proc(args: ..any, sep := " ") -> string { - str: strings.Builder; - strings.init_builder(&str); - sbprint(buf=&str, args=args, sep=sep); - return strings.to_string(str); + str: strings.Builder + strings.init_builder(&str) + sbprint(buf=&str, args=args, sep=sep) + return strings.to_string(str) } aprintln :: proc(args: ..any, sep := " ") -> string { - str: strings.Builder; - strings.init_builder(&str); - sbprintln(buf=&str, args=args, sep=sep); - return strings.to_string(str); + str: strings.Builder + strings.init_builder(&str) + sbprintln(buf=&str, args=args, sep=sep) + return strings.to_string(str) } aprintf :: proc(fmt: string, args: ..any) -> string { - str: strings.Builder; - strings.init_builder(&str); - sbprintf(&str, fmt, ..args); - return strings.to_string(str); + str: strings.Builder + strings.init_builder(&str) + sbprintf(&str, fmt, ..args) + return strings.to_string(str) } // tprint* procedures return a string that was allocated with the current context's temporary allocator tprint :: proc(args: ..any, sep := " ") -> string { - str: strings.Builder; - strings.init_builder(&str, context.temp_allocator); - sbprint(buf=&str, args=args, sep=sep); - return strings.to_string(str); + str: strings.Builder + strings.init_builder(&str, context.temp_allocator) + sbprint(buf=&str, args=args, sep=sep) + return strings.to_string(str) } tprintln :: proc(args: ..any, sep := " ") -> string { - str: strings.Builder; - strings.init_builder(&str, context.temp_allocator); - sbprintln(buf=&str, args=args, sep=sep); - return strings.to_string(str); + str: strings.Builder + strings.init_builder(&str, context.temp_allocator) + sbprintln(buf=&str, args=args, sep=sep) + return strings.to_string(str) } tprintf :: proc(fmt: string, args: ..any) -> string { - str: strings.Builder; - strings.init_builder(&str, context.temp_allocator); - sbprintf(&str, fmt, ..args); - return strings.to_string(str); + str: strings.Builder + strings.init_builder(&str, context.temp_allocator) + sbprintf(&str, fmt, ..args) + return strings.to_string(str) } // bprint* procedures return a string using a buffer from an array bprint :: proc(buf: []byte, args: ..any, sep := " ") -> string { - sb := strings.builder_from_slice(buf[0:len(buf)]); - return sbprint(buf=&sb, args=args, sep=sep); + sb := strings.builder_from_slice(buf[0:len(buf)]) + return sbprint(buf=&sb, args=args, sep=sep) } bprintln :: proc(buf: []byte, args: ..any, sep := " ") -> string { - sb := strings.builder_from_slice(buf[0:len(buf)]); - return sbprintln(buf=&sb, args=args, sep=sep); + sb := strings.builder_from_slice(buf[0:len(buf)]) + return sbprintln(buf=&sb, args=args, sep=sep) } bprintf :: proc(buf: []byte, fmt: string, args: ..any) -> string { - sb := strings.builder_from_slice(buf[0:len(buf)]); - return sbprintf(&sb, fmt, ..args); + sb := strings.builder_from_slice(buf[0:len(buf)]) + return sbprintf(&sb, fmt, ..args) } assertf :: proc(condition: bool, fmt: string, args: ..any, loc := #caller_location) -> bool { if !condition { - p := context.assertion_failure_proc; + p := context.assertion_failure_proc if p == nil { - p = runtime.default_assertion_failure_proc; + p = runtime.default_assertion_failure_proc } - message := tprintf(fmt, ..args); - p("Runtime assertion", message, loc); + message := tprintf(fmt, ..args) + p("Runtime assertion", message, loc) } - return condition; + return condition } panicf :: proc(fmt: string, args: ..any, loc := #caller_location) -> ! { - p := context.assertion_failure_proc; + p := context.assertion_failure_proc if p == nil { - p = runtime.default_assertion_failure_proc; + p = runtime.default_assertion_failure_proc } - message := tprintf(fmt, ..args); - p("Panic", message, loc); + message := tprintf(fmt, ..args) + p("Panic", message, loc) } @@ -178,24 +178,24 @@ panicf :: proc(fmt: string, args: ..any, loc := #caller_location) -> ! { sbprint :: proc(buf: ^strings.Builder, args: ..any, sep := " ") -> string { - wprint(w=strings.to_writer(buf), args=args, sep=sep); - return strings.to_string(buf^); + wprint(w=strings.to_writer(buf), args=args, sep=sep) + return strings.to_string(buf^) } sbprintln :: proc(buf: ^strings.Builder, args: ..any, sep := " ") -> string { - wprintln(w=strings.to_writer(buf), args=args, sep=sep); - return strings.to_string(buf^); + wprintln(w=strings.to_writer(buf), args=args, sep=sep) + return strings.to_string(buf^) } sbprintf :: proc(buf: ^strings.Builder, fmt: string, args: ..any) -> string { - wprintf(w=strings.to_writer(buf), fmt=fmt, args=args); - return strings.to_string(buf^); + wprintf(w=strings.to_writer(buf), fmt=fmt, args=args) + return strings.to_string(buf^) } wprint :: proc(w: io.Writer, args: ..any, sep := " ") -> int { - fi: Info; - fi.writer = w; + fi: Info + fi.writer = w // NOTE(bill): Old approach // prev_string := false; @@ -212,80 +212,80 @@ wprint :: proc(w: io.Writer, args: ..any, sep := " ") -> int { // so I am going to keep the same behaviour as `*println` for `*print` - size0 := io.size(auto_cast w); + size0 := io.size(auto_cast w) for _, i in args { if i > 0 { - io.write_string(fi.writer, sep); + io.write_string(fi.writer, sep) } - fmt_value(&fi, args[i], 'v'); + fmt_value(&fi, args[i], 'v') } - io.flush(auto_cast w); + io.flush(auto_cast w) - size1 := io.size(auto_cast w); - return int(size1 - size0); + size1 := io.size(auto_cast w) + return int(size1 - size0) } wprintln :: proc(w: io.Writer, args: ..any, sep := " ") -> int { - fi: Info; - fi.writer = w; + fi: Info + fi.writer = w - size0 := io.size(auto_cast w); + size0 := io.size(auto_cast w) for _, i in args { if i > 0 { - io.write_string(fi.writer, sep); + io.write_string(fi.writer, sep) } - fmt_value(&fi, args[i], 'v'); + fmt_value(&fi, args[i], 'v') } - io.write_byte(fi.writer, '\n'); - io.flush(auto_cast w); + io.write_byte(fi.writer, '\n') + io.flush(auto_cast w) - size1 := io.size(auto_cast w); - return int(size1 - size0); + size1 := io.size(auto_cast w) + return int(size1 - size0) } wprintf :: proc(w: io.Writer, fmt: string, args: ..any) -> int { - fi: Info; - arg_index: int = 0; - end := len(fmt); - was_prev_index := false; + fi: Info + arg_index: int = 0 + end := len(fmt) + was_prev_index := false - size0 := io.size(auto_cast w); + size0 := io.size(auto_cast w) loop: for i := 0; i < end; /**/ { - fi = Info{writer = w, good_arg_index = true, reordered = fi.reordered}; + fi = Info{writer = w, good_arg_index = true, reordered = fi.reordered} - prev_i := i; + prev_i := i for i < end && !(fmt[i] == '%' || fmt[i] == '{' || fmt[i] == '}') { - i += 1; + i += 1 } if i > prev_i { - io.write_string(fi.writer, fmt[prev_i:i]); + io.write_string(fi.writer, fmt[prev_i:i]) } if i >= end { - break loop; + break loop } - char := fmt[i]; + char := fmt[i] // Process a "char" - i += 1; + i += 1 if char == '}' { if i < end && fmt[i] == char { // Skip extra one - i += 1; + i += 1 } - io.write_byte(fi.writer, char); - continue loop; + io.write_byte(fi.writer, char) + continue loop } else if char == '{' { if i < end && fmt[i] == char { // Skip extra one - i += 1; - io.write_byte(fi.writer, char); - continue loop; + i += 1 + io.write_byte(fi.writer, char) + continue loop } } @@ -293,248 +293,248 @@ wprintf :: proc(w: io.Writer, fmt: string, args: ..any) -> int { prefix_loop: for ; i < end; i += 1 { switch fmt[i] { case '+': - fi.plus = true; + fi.plus = true case '-': - fi.minus = true; - fi.zero = false; + fi.minus = true + fi.zero = false case ' ': - fi.space = true; + fi.space = true case '#': - fi.hash = true; + fi.hash = true case '0': - fi.zero = !fi.minus; + fi.zero = !fi.minus case: - break prefix_loop; + break prefix_loop } } - arg_index, i, was_prev_index = _arg_number(&fi, arg_index, fmt, i, len(args)); + arg_index, i, was_prev_index = _arg_number(&fi, arg_index, fmt, i, len(args)) // Width if i < end && fmt[i] == '*' { - i += 1; - fi.width, arg_index, fi.width_set = int_from_arg(args, arg_index); + i += 1 + fi.width, arg_index, fi.width_set = int_from_arg(args, arg_index) if !fi.width_set { - io.write_string(w, "%!(BAD WIDTH)"); + io.write_string(w, "%!(BAD WIDTH)") } if fi.width < 0 { - fi.width = -fi.width; - fi.minus = true; - fi.zero = false; + fi.width = -fi.width + fi.minus = true + fi.zero = false } - was_prev_index = false; + was_prev_index = false } else { - fi.width, i, fi.width_set = _parse_int(fmt, i); + fi.width, i, fi.width_set = _parse_int(fmt, i) if was_prev_index && fi.width_set { // %[6]2d - fi.good_arg_index = false; + fi.good_arg_index = false } } // Precision if i < end && fmt[i] == '.' { - i += 1; + i += 1 if was_prev_index { // %[6].2d - fi.good_arg_index = false; + fi.good_arg_index = false } if i < end && fmt[i] == '*' { - arg_index, i, was_prev_index = _arg_number(&fi, arg_index, fmt, i, len(args)); - i += 1; - fi.prec, arg_index, fi.prec_set = int_from_arg(args, arg_index); + arg_index, i, was_prev_index = _arg_number(&fi, arg_index, fmt, i, len(args)) + i += 1 + fi.prec, arg_index, fi.prec_set = int_from_arg(args, arg_index) if fi.prec < 0 { - fi.prec = 0; - fi.prec_set = false; + fi.prec = 0 + fi.prec_set = false } if !fi.prec_set { - io.write_string(fi.writer, "%!(BAD PRECISION)"); + io.write_string(fi.writer, "%!(BAD PRECISION)") } - was_prev_index = false; + was_prev_index = false } else { - fi.prec, i, fi.prec_set = _parse_int(fmt, i); + fi.prec, i, fi.prec_set = _parse_int(fmt, i) } } if !was_prev_index { - arg_index, i, was_prev_index = _arg_number(&fi, arg_index, fmt, i, len(args)); + arg_index, i, was_prev_index = _arg_number(&fi, arg_index, fmt, i, len(args)) } if i >= end { - io.write_string(fi.writer, "%!(NO VERB)"); - break loop; + io.write_string(fi.writer, "%!(NO VERB)") + break loop } - verb, w := utf8.decode_rune_in_string(fmt[i:]); - i += w; + verb, w := utf8.decode_rune_in_string(fmt[i:]) + i += w switch { case verb == '%': - io.write_byte(fi.writer, '%'); + io.write_byte(fi.writer, '%') case !fi.good_arg_index: - io.write_string(fi.writer, "%!(BAD ARGUMENT NUMBER)"); + io.write_string(fi.writer, "%!(BAD ARGUMENT NUMBER)") case arg_index >= len(args): - io.write_string(fi.writer, "%!(MISSING ARGUMENT)"); + io.write_string(fi.writer, "%!(MISSING ARGUMENT)") case: - fmt_arg(&fi, args[arg_index], verb); - arg_index += 1; + fmt_arg(&fi, args[arg_index], verb) + arg_index += 1 } } else if char == '{' { if i < end && fmt[i] != '}' && fmt[i] != ':' { - new_arg_index, new_i, ok := _parse_int(fmt, i); + new_arg_index, new_i, ok := _parse_int(fmt, i) if ok { - fi.reordered = true; - was_prev_index = true; - arg_index = new_arg_index; - i = new_i; + fi.reordered = true + was_prev_index = true + arg_index = new_arg_index + i = new_i } else { - io.write_string(fi.writer, "%!(BAD ARGUMENT NUMBER "); + io.write_string(fi.writer, "%!(BAD ARGUMENT NUMBER ") // Skip over the bad argument - start_index := i; + start_index := i for i < end && fmt[i] != '}' && fmt[i] != ':' { - i += 1; + i += 1 } - fmt_arg(&fi, fmt[start_index:i], 'v'); - io.write_string(fi.writer, ")"); + fmt_arg(&fi, fmt[start_index:i], 'v') + io.write_string(fi.writer, ")") } } - verb: rune = 'v'; + verb: rune = 'v' if i < end && fmt[i] == ':' { - i += 1; + i += 1 prefix_loop_percent: for ; i < end; i += 1 { switch fmt[i] { case '+': - fi.plus = true; + fi.plus = true case '-': - fi.minus = true; - fi.zero = false; + fi.minus = true + fi.zero = false case ' ': - fi.space = true; + fi.space = true case '#': - fi.hash = true; + fi.hash = true case '0': - fi.zero = !fi.minus; + fi.zero = !fi.minus case: - break prefix_loop_percent; + break prefix_loop_percent } } - arg_index, i, was_prev_index = _arg_number(&fi, arg_index, fmt, i, len(args)); + arg_index, i, was_prev_index = _arg_number(&fi, arg_index, fmt, i, len(args)) // Width if i < end && fmt[i] == '*' { - i += 1; - fi.width, arg_index, fi.width_set = int_from_arg(args, arg_index); + i += 1 + fi.width, arg_index, fi.width_set = int_from_arg(args, arg_index) if !fi.width_set { - io.write_string(fi.writer, "%!(BAD WIDTH)"); + io.write_string(fi.writer, "%!(BAD WIDTH)") } if fi.width < 0 { - fi.width = -fi.width; - fi.minus = true; - fi.zero = false; + fi.width = -fi.width + fi.minus = true + fi.zero = false } - was_prev_index = false; + was_prev_index = false } else { - fi.width, i, fi.width_set = _parse_int(fmt, i); + fi.width, i, fi.width_set = _parse_int(fmt, i) if was_prev_index && fi.width_set { // %[6]2d - fi.good_arg_index = false; + fi.good_arg_index = false } } // Precision if i < end && fmt[i] == '.' { - i += 1; + i += 1 if was_prev_index { // %[6].2d - fi.good_arg_index = false; + fi.good_arg_index = false } if i < end && fmt[i] == '*' { - arg_index, i, was_prev_index = _arg_number(&fi, arg_index, fmt, i, len(args)); - i += 1; - fi.prec, arg_index, fi.prec_set = int_from_arg(args, arg_index); + arg_index, i, was_prev_index = _arg_number(&fi, arg_index, fmt, i, len(args)) + i += 1 + fi.prec, arg_index, fi.prec_set = int_from_arg(args, arg_index) if fi.prec < 0 { - fi.prec = 0; - fi.prec_set = false; + fi.prec = 0 + fi.prec_set = false } if !fi.prec_set { - io.write_string(fi.writer, "%!(BAD PRECISION)"); + io.write_string(fi.writer, "%!(BAD PRECISION)") } - was_prev_index = false; + was_prev_index = false } else { - fi.prec, i, fi.prec_set = _parse_int(fmt, i); + fi.prec, i, fi.prec_set = _parse_int(fmt, i) } } if !was_prev_index { - arg_index, i, was_prev_index = _arg_number(&fi, arg_index, fmt, i, len(args)); + arg_index, i, was_prev_index = _arg_number(&fi, arg_index, fmt, i, len(args)) } if i >= end { - io.write_string(fi.writer, "%!(NO VERB)"); - break loop; + io.write_string(fi.writer, "%!(NO VERB)") + break loop } - w: int = 1; - verb, w = utf8.decode_rune_in_string(fmt[i:]); - i += w; + w: int = 1 + verb, w = utf8.decode_rune_in_string(fmt[i:]) + i += w } if i >= end { - io.write_string(fi.writer, "%!(MISSING CLOSE BRACE)"); - break loop; + io.write_string(fi.writer, "%!(MISSING CLOSE BRACE)") + break loop } - brace, w := utf8.decode_rune_in_string(fmt[i:]); - i += w; + brace, w := utf8.decode_rune_in_string(fmt[i:]) + i += w switch { case brace != '}': - io.write_string(fi.writer, "%!(MISSING CLOSE BRACE)"); + io.write_string(fi.writer, "%!(MISSING CLOSE BRACE)") case !fi.good_arg_index: - io.write_string(fi.writer, "%!(BAD ARGUMENT NUMBER)"); + io.write_string(fi.writer, "%!(BAD ARGUMENT NUMBER)") case arg_index >= len(args): - io.write_string(fi.writer, "%!(MISSING ARGUMENT)"); + io.write_string(fi.writer, "%!(MISSING ARGUMENT)") case: - fmt_arg(&fi, args[arg_index], verb); - arg_index += 1; + fmt_arg(&fi, args[arg_index], verb) + arg_index += 1 } } } if !fi.reordered && arg_index < len(args) { - io.write_string(fi.writer, "%!(EXTRA "); + io.write_string(fi.writer, "%!(EXTRA ") for arg, index in args[arg_index:] { if index > 0 { - io.write_string(fi.writer, ", "); + io.write_string(fi.writer, ", ") } if arg == nil { - io.write_string(fi.writer, "<nil>"); + io.write_string(fi.writer, "<nil>") } else { - fmt_arg(&fi, args[index], 'v'); + fmt_arg(&fi, args[index], 'v') } } - io.write_string(fi.writer, ")"); + io.write_string(fi.writer, ")") } - io.flush(auto_cast w); + io.flush(auto_cast w) - size1 := io.size(auto_cast w); - return int(size1 - size0); + size1 := io.size(auto_cast w) + return int(size1 - size0) } wprint_type :: proc(w: io.Writer, info: ^runtime.Type_Info) -> int { - n := reflect.write_type(w, info); - io.flush(auto_cast w); - return n; + n := reflect.write_type(w, info) + io.flush(auto_cast w) + return n } wprint_typeid :: proc(w: io.Writer, id: typeid) -> int { - n := reflect.write_type(w, type_info_of(id)); - io.flush(auto_cast w); - return n; + n := reflect.write_type(w, type_info_of(id)) + io.flush(auto_cast w) + return n } @@ -543,419 +543,419 @@ wprint_typeid :: proc(w: io.Writer, id: typeid) -> int { _parse_int :: proc(s: string, offset: int) -> (result: int, new_offset: int, ok: bool) { is_digit :: #force_inline proc(r: byte) -> bool { return '0' <= r && r <= '9' } - new_offset = offset; + new_offset = offset for new_offset <= len(s) { - c := s[new_offset]; + c := s[new_offset] if !is_digit(c) { - break; + break } - new_offset += 1; + new_offset += 1 - result *= 10; - result += int(c)-'0'; + result *= 10 + result += int(c)-'0' } - ok = new_offset > offset; - return; + ok = new_offset > offset + return } _arg_number :: proc(fi: ^Info, arg_index: int, format: string, offset, arg_count: int) -> (index, new_offset: int, ok: bool) { parse_arg_number :: proc(format: string) -> (int, int, bool) { if len(format) < 3 { - return 0, 1, false; + return 0, 1, false } for i in 1..<len(format) { if format[i] == ']' { - width, new_index, ok := _parse_int(format, 1); + width, new_index, ok := _parse_int(format, 1) if !ok || new_index != i { - return 0, i+1, false; + return 0, i+1, false } - return width-1, i+1, true; + return width-1, i+1, true } } - return 0, 1, false; + return 0, 1, false } if len(format) <= offset || format[offset] != '[' { - return arg_index, offset, false; + return arg_index, offset, false } - fi.reordered = true; + fi.reordered = true - width: int; - index, width, ok = parse_arg_number(format[offset:]); + width: int + index, width, ok = parse_arg_number(format[offset:]) if ok && 0 <= index && index < arg_count { - return index, offset+width, true; + return index, offset+width, true } - fi.good_arg_index = false; - return arg_index, offset+width, false; + fi.good_arg_index = false + return arg_index, offset+width, false } int_from_arg :: proc(args: []any, arg_index: int) -> (int, int, bool) { - num := 0; - new_arg_index := arg_index; - ok := true; + num := 0 + new_arg_index := arg_index + ok := true if arg_index < len(args) { - num, ok = reflect.as_int(args[arg_index]); + num, ok = reflect.as_int(args[arg_index]) } if ok { - new_arg_index += 1; + new_arg_index += 1 } - return num, new_arg_index, ok; + return num, new_arg_index, ok } fmt_bad_verb :: proc(using fi: ^Info, verb: rune) { - io.write_string(writer, "%!"); - io.write_rune(writer, verb); - io.write_byte(writer, '('); + io.write_string(writer, "%!") + io.write_rune(writer, verb) + io.write_byte(writer, '(') if arg.id != nil { - reflect.write_typeid(writer, arg.id); - io.write_byte(writer, '='); - fmt_value(fi, arg, 'v'); + reflect.write_typeid(writer, arg.id) + io.write_byte(writer, '=') + fmt_value(fi, arg, 'v') } else { - io.write_string(writer, "<nil>"); + io.write_string(writer, "<nil>") } - io.write_byte(writer, ')'); + io.write_byte(writer, ')') } fmt_bool :: proc(using fi: ^Info, b: bool, verb: rune) { switch verb { case 't', 'v': - io.write_string(writer, b ? "true" : "false"); + io.write_string(writer, b ? "true" : "false") case: - fmt_bad_verb(fi, verb); + fmt_bad_verb(fi, verb) } } fmt_write_padding :: proc(fi: ^Info, width: int) { if width <= 0 { - return; + return } - pad_byte: byte = ' '; + pad_byte: byte = ' ' if !fi.space { - pad_byte = '0'; + pad_byte = '0' } for i := 0; i < width; i += 1 { - io.write_byte(fi.writer, pad_byte); + io.write_byte(fi.writer, pad_byte) } } _fmt_int :: proc(fi: ^Info, u: u64, base: int, is_signed: bool, bit_size: int, digits: string) { - _, neg := strconv.is_integer_negative(u, is_signed, bit_size); + _, neg := strconv.is_integer_negative(u, is_signed, bit_size) - BUF_SIZE :: 256; + BUF_SIZE :: 256 if fi.width_set || fi.prec_set { - width := fi.width + fi.prec + 3; // 3 extra bytes for sign and prefix + width := fi.width + fi.prec + 3 // 3 extra bytes for sign and prefix if width > BUF_SIZE { // TODO(bill):???? - panic("_fmt_int: buffer overrun. Width and precision too big"); + panic("_fmt_int: buffer overrun. Width and precision too big") } } - prec := 0; + prec := 0 if fi.prec_set { - prec = fi.prec; + prec = fi.prec if prec == 0 && u == 0 { - prev_zero := fi.zero; - fi.zero = false; - fmt_write_padding(fi, fi.width); - fi.zero = prev_zero; - return; + prev_zero := fi.zero + fi.zero = false + fmt_write_padding(fi, fi.width) + fi.zero = prev_zero + return } } else if fi.zero && fi.width_set { - prec = fi.width; + prec = fi.width if neg || fi.plus || fi.space { // There needs to be space for the "sign" - prec -= 1; + prec -= 1 } } switch base { case 2, 8, 10, 12, 16: - break; + break case: - panic("_fmt_int: unknown base, whoops"); + panic("_fmt_int: unknown base, whoops") } - buf: [256]byte; - start := 0; + buf: [256]byte + start := 0 - flags: strconv.Int_Flags; + flags: strconv.Int_Flags if fi.hash && !fi.zero { flags |= {.Prefix}; } if fi.plus { flags |= {.Plus}; } if fi.space { flags |= {.Space}; } - s := strconv.append_bits(buf[start:], u, base, is_signed, bit_size, digits, flags); + s := strconv.append_bits(buf[start:], u, base, is_signed, bit_size, digits, flags) if fi.hash && fi.zero && fi.indent == 0 { - c: byte = 0; + c: byte = 0 switch base { - case 2: c = 'b'; - case 8: c = 'o'; - case 12: c = 'z'; - case 16: c = 'x'; + case 2: c = 'b' + case 8: c = 'o' + case 12: c = 'z' + case 16: c = 'x' } if c != 0 { - io.write_byte(fi.writer, '0'); - io.write_byte(fi.writer, c); + io.write_byte(fi.writer, '0') + io.write_byte(fi.writer, c) } } - prev_zero := fi.zero; - defer fi.zero = prev_zero; - fi.zero = false; - _pad(fi, s); + prev_zero := fi.zero + defer fi.zero = prev_zero + fi.zero = false + _pad(fi, s) } _fmt_int_128 :: proc(fi: ^Info, u: u128, base: int, is_signed: bool, bit_size: int, digits: string) { - _, neg := strconv.is_integer_negative_128(u, is_signed, bit_size); + _, neg := strconv.is_integer_negative_128(u, is_signed, bit_size) - BUF_SIZE :: 256; + BUF_SIZE :: 256 if fi.width_set || fi.prec_set { - width := fi.width + fi.prec + 3; // 3 extra bytes for sign and prefix + width := fi.width + fi.prec + 3 // 3 extra bytes for sign and prefix if width > BUF_SIZE { // TODO(bill):???? - panic("_fmt_int: buffer overrun. Width and precision too big"); + panic("_fmt_int: buffer overrun. Width and precision too big") } } - prec := 0; + prec := 0 if fi.prec_set { - prec = fi.prec; + prec = fi.prec if prec == 0 && u == 0 { - prev_zero := fi.zero; - fi.zero = false; - fmt_write_padding(fi, fi.width); - fi.zero = prev_zero; - return; + prev_zero := fi.zero + fi.zero = false + fmt_write_padding(fi, fi.width) + fi.zero = prev_zero + return } } else if fi.zero && fi.width_set { - prec = fi.width; + prec = fi.width if neg || fi.plus || fi.space { // There needs to be space for the "sign" - prec -= 1; + prec -= 1 } } switch base { case 2, 8, 10, 12, 16: - break; + break case: - panic("_fmt_int: unknown base, whoops"); + panic("_fmt_int: unknown base, whoops") } - buf: [256]byte; - start := 0; + buf: [256]byte + start := 0 - flags: strconv.Int_Flags; + flags: strconv.Int_Flags if fi.hash && !fi.zero { flags |= {.Prefix}; } if fi.plus { flags |= {.Plus}; } if fi.space { flags |= {.Space}; } - s := strconv.append_bits_128(buf[start:], u, base, is_signed, bit_size, digits, flags); + s := strconv.append_bits_128(buf[start:], u, base, is_signed, bit_size, digits, flags) if fi.hash && fi.zero && fi.indent == 0 { - c: byte = 0; + c: byte = 0 switch base { - case 2: c = 'b'; - case 8: c = 'o'; - case 12: c = 'z'; - case 16: c = 'x'; + case 2: c = 'b' + case 8: c = 'o' + case 12: c = 'z' + case 16: c = 'x' } if c != 0 { - io.write_byte(fi.writer, '0'); - io.write_byte(fi.writer, c); + io.write_byte(fi.writer, '0') + io.write_byte(fi.writer, c) } } - prev_zero := fi.zero; - defer fi.zero = prev_zero; - fi.zero = false; - _pad(fi, s); + prev_zero := fi.zero + defer fi.zero = prev_zero + fi.zero = false + _pad(fi, s) } -__DIGITS_LOWER := "0123456789abcdefx"; -__DIGITS_UPPER := "0123456789ABCDEFX"; +__DIGITS_LOWER := "0123456789abcdefx" +__DIGITS_UPPER := "0123456789ABCDEFX" fmt_rune :: proc(fi: ^Info, r: rune, verb: rune) { switch verb { case 'c', 'r', 'v': - io.write_rune(fi.writer, r); + io.write_rune(fi.writer, r) case 'q': - strings.write_quoted_rune(fi.writer, r); + strings.write_quoted_rune(fi.writer, r) case: - fmt_int(fi, u64(r), false, 32, verb); + fmt_int(fi, u64(r), false, 32, verb) } } fmt_int :: proc(fi: ^Info, u: u64, is_signed: bool, bit_size: int, verb: rune) { switch verb { - case 'v': _fmt_int(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER); - case 'b': _fmt_int(fi, u, 2, is_signed, bit_size, __DIGITS_LOWER); - case 'o': _fmt_int(fi, u, 8, is_signed, bit_size, __DIGITS_LOWER); - case 'i', 'd': _fmt_int(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER); - case 'z': _fmt_int(fi, u, 12, is_signed, bit_size, __DIGITS_LOWER); - case 'x': _fmt_int(fi, u, 16, is_signed, bit_size, __DIGITS_LOWER); - case 'X': _fmt_int(fi, u, 16, is_signed, bit_size, __DIGITS_UPPER); + case 'v': _fmt_int(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER) + case 'b': _fmt_int(fi, u, 2, is_signed, bit_size, __DIGITS_LOWER) + case 'o': _fmt_int(fi, u, 8, is_signed, bit_size, __DIGITS_LOWER) + case 'i', 'd': _fmt_int(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER) + case 'z': _fmt_int(fi, u, 12, is_signed, bit_size, __DIGITS_LOWER) + case 'x': _fmt_int(fi, u, 16, is_signed, bit_size, __DIGITS_LOWER) + case 'X': _fmt_int(fi, u, 16, is_signed, bit_size, __DIGITS_UPPER) case 'c', 'r': - fmt_rune(fi, rune(u), verb); + fmt_rune(fi, rune(u), verb) case 'U': - r := rune(u); + r := rune(u) if r < 0 || r > utf8.MAX_RUNE { - fmt_bad_verb(fi, verb); + fmt_bad_verb(fi, verb) } else { - io.write_string(fi.writer, "U+"); - _fmt_int(fi, u, 16, false, bit_size, __DIGITS_UPPER); + io.write_string(fi.writer, "U+") + _fmt_int(fi, u, 16, false, bit_size, __DIGITS_UPPER) } case: - fmt_bad_verb(fi, verb); + fmt_bad_verb(fi, verb) } } fmt_int_128 :: proc(fi: ^Info, u: u128, is_signed: bool, bit_size: int, verb: rune) { switch verb { - case 'v': _fmt_int_128(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER); - case 'b': _fmt_int_128(fi, u, 2, is_signed, bit_size, __DIGITS_LOWER); - case 'o': _fmt_int_128(fi, u, 8, is_signed, bit_size, __DIGITS_LOWER); - case 'i', 'd': _fmt_int_128(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER); - case 'z': _fmt_int_128(fi, u, 12, is_signed, bit_size, __DIGITS_LOWER); - case 'x': _fmt_int_128(fi, u, 16, is_signed, bit_size, __DIGITS_LOWER); - case 'X': _fmt_int_128(fi, u, 16, is_signed, bit_size, __DIGITS_UPPER); + case 'v': _fmt_int_128(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER) + case 'b': _fmt_int_128(fi, u, 2, is_signed, bit_size, __DIGITS_LOWER) + case 'o': _fmt_int_128(fi, u, 8, is_signed, bit_size, __DIGITS_LOWER) + case 'i', 'd': _fmt_int_128(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER) + case 'z': _fmt_int_128(fi, u, 12, is_signed, bit_size, __DIGITS_LOWER) + case 'x': _fmt_int_128(fi, u, 16, is_signed, bit_size, __DIGITS_LOWER) + case 'X': _fmt_int_128(fi, u, 16, is_signed, bit_size, __DIGITS_UPPER) case 'c', 'r': - fmt_rune(fi, rune(u), verb); + fmt_rune(fi, rune(u), verb) case 'U': - r := rune(u); + r := rune(u) if r < 0 || r > utf8.MAX_RUNE { - fmt_bad_verb(fi, verb); + fmt_bad_verb(fi, verb) } else { - io.write_string(fi.writer, "U+"); - _fmt_int_128(fi, u, 16, false, bit_size, __DIGITS_UPPER); + io.write_string(fi.writer, "U+") + _fmt_int_128(fi, u, 16, false, bit_size, __DIGITS_UPPER) } case: - fmt_bad_verb(fi, verb); + fmt_bad_verb(fi, verb) } } _pad :: proc(fi: ^Info, s: string) { if !fi.width_set { - io.write_string(fi.writer, s); - return; + io.write_string(fi.writer, s) + return } - width := fi.width - utf8.rune_count_in_string(s); + width := fi.width - utf8.rune_count_in_string(s) if fi.minus { // right pad - io.write_string(fi.writer, s); - fmt_write_padding(fi, width); + io.write_string(fi.writer, s) + fmt_write_padding(fi, width) } else { // left pad - fmt_write_padding(fi, width); - io.write_string(fi.writer, s); + fmt_write_padding(fi, width) + io.write_string(fi.writer, s) } } fmt_float :: proc(fi: ^Info, v: f64, bit_size: int, verb: rune) { switch verb { case 'f', 'F', 'v': - prec: int = 3; + prec: int = 3 if fi.prec_set { - prec = fi.prec; + prec = fi.prec } - buf: [386]byte; + buf: [386]byte - str := strconv.append_float(buf[1:], v, 'f', prec, bit_size); - b := buf[:len(str)+1]; + str := strconv.append_float(buf[1:], v, 'f', prec, bit_size) + b := buf[:len(str)+1] if b[1] == '+' || b[1] == '-' { - b = b[1:]; + b = b[1:] } else { - b[0] = '+'; + b[0] = '+' } if fi.space && !fi.plus && b[0] == '+' { - b[0] = ' '; + b[0] = ' ' } if len(b) > 1 && (b[1] == 'N' || b[1] == 'I') { - io.write_string(fi.writer, string(b)); - return; + io.write_string(fi.writer, string(b)) + return } if fi.plus || b[0] != '+' { if fi.zero && fi.width_set && fi.width > len(b) { - io.write_byte(fi.writer, b[0]); - fmt_write_padding(fi, fi.width - len(b)); - io.write_string(fi.writer, string(b[1:])); + io.write_byte(fi.writer, b[0]) + fmt_write_padding(fi, fi.width - len(b)) + io.write_string(fi.writer, string(b[1:])) } else { - _pad(fi, string(b)); + _pad(fi, string(b)) } } else { - _pad(fi, string(b[1:])); + _pad(fi, string(b[1:])) } case 'e', 'E': - prec: int = 3; + prec: int = 3 if fi.prec_set { - prec = fi.prec; + prec = fi.prec } - buf: [386]byte; + buf: [386]byte - str := strconv.append_float(buf[1:], v, 'e', prec, bit_size); - b := buf[:len(str)+1]; + str := strconv.append_float(buf[1:], v, 'e', prec, bit_size) + b := buf[:len(str)+1] if b[1] == '+' || b[1] == '-' { - b = b[1:]; + b = b[1:] } else { - b[0] = '+'; + b[0] = '+' } if fi.space && !fi.plus && b[0] == '+' { - b[0] = ' '; + b[0] = ' ' } if len(b) > 1 && (b[1] == 'N' || b[1] == 'I') { - io.write_string(fi.writer, string(b)); - return; + io.write_string(fi.writer, string(b)) + return } if fi.plus || str[0] != '+' { if fi.zero && fi.width_set && fi.width > len(b) { - io.write_byte(fi.writer, b[0]); - fmt_write_padding(fi, fi.width - len(b)); - io.write_string(fi.writer, string(b[1:])); + io.write_byte(fi.writer, b[0]) + fmt_write_padding(fi, fi.width - len(b)) + io.write_string(fi.writer, string(b[1:])) } else { - _pad(fi, string(b)); + _pad(fi, string(b)) } } else { - _pad(fi, string(b[1:])); + _pad(fi, string(b[1:])) } case 'h', 'H': - prev_fi := fi^; - defer fi^ = prev_fi; - fi.hash = false; - fi.width = bit_size; - fi.zero = true; - fi.plus = false; - - u: u64; + prev_fi := fi^ + defer fi^ = prev_fi + fi.hash = false + fi.width = bit_size + fi.zero = true + fi.plus = false + + u: u64 switch bit_size { - case 16: u = u64(transmute(u16)f16(v)); - case 32: u = u64(transmute(u32)f32(v)); - case 64: u = transmute(u64)v; - case: panic("Unhandled float size"); + case 16: u = u64(transmute(u16)f16(v)) + case 32: u = u64(transmute(u32)f32(v)) + case 64: u = transmute(u64)v + case: panic("Unhandled float size") } - io.write_string(fi.writer, "0h"); - _fmt_int(fi, u, 16, false, bit_size, __DIGITS_LOWER if verb == 'h' else __DIGITS_UPPER); + io.write_string(fi.writer, "0h") + _fmt_int(fi, u, 16, false, bit_size, __DIGITS_LOWER if verb == 'h' else __DIGITS_UPPER) case: - fmt_bad_verb(fi, verb); + fmt_bad_verb(fi, verb) } } @@ -963,320 +963,320 @@ fmt_float :: proc(fi: ^Info, v: f64, bit_size: int, verb: rune) { fmt_string :: proc(fi: ^Info, s: string, verb: rune) { switch verb { case 's', 'v': - io.write_string(fi.writer, s); + io.write_string(fi.writer, s) if fi.width_set && len(s) < fi.width { for _ in 0..<fi.width - len(s) { - io.write_byte(fi.writer, ' '); + io.write_byte(fi.writer, ' ') } } case 'q': // quoted string - strings.write_quoted_string(fi.writer, s, '"'); + strings.write_quoted_string(fi.writer, s, '"') case 'x', 'X': - space := fi.space; - fi.space = false; - defer fi.space = space; + space := fi.space + fi.space = false + defer fi.space = space for i in 0..<len(s) { if i > 0 && space { - io.write_byte(fi.writer, ' '); + io.write_byte(fi.writer, ' ') } - char_set := __DIGITS_UPPER; + char_set := __DIGITS_UPPER if verb == 'x' { - char_set = __DIGITS_LOWER; + char_set = __DIGITS_LOWER } - _fmt_int(fi, u64(s[i]), 16, false, 8, char_set); + _fmt_int(fi, u64(s[i]), 16, false, 8, char_set) } case: - fmt_bad_verb(fi, verb); + fmt_bad_verb(fi, verb) } } fmt_cstring :: proc(fi: ^Info, s: cstring, verb: rune) { - fmt_string(fi, string(s), verb); + fmt_string(fi, string(s), verb) } fmt_pointer :: proc(fi: ^Info, p: rawptr, verb: rune) { - u := u64(uintptr(p)); + u := u64(uintptr(p)) switch verb { case 'p', 'v': if !fi.hash || verb == 'v' { - io.write_string(fi.writer, "0x"); + io.write_string(fi.writer, "0x") } - _fmt_int(fi, u, 16, false, 8*size_of(rawptr), __DIGITS_UPPER); + _fmt_int(fi, u, 16, false, 8*size_of(rawptr), __DIGITS_UPPER) - case 'b': _fmt_int(fi, u, 2, false, 8*size_of(rawptr), __DIGITS_UPPER); - case 'o': _fmt_int(fi, u, 8, false, 8*size_of(rawptr), __DIGITS_UPPER); - case 'i', 'd': _fmt_int(fi, u, 10, false, 8*size_of(rawptr), __DIGITS_UPPER); - case 'z': _fmt_int(fi, u, 12, false, 8*size_of(rawptr), __DIGITS_UPPER); - case 'x': _fmt_int(fi, u, 16, false, 8*size_of(rawptr), __DIGITS_UPPER); - case 'X': _fmt_int(fi, u, 16, false, 8*size_of(rawptr), __DIGITS_UPPER); + case 'b': _fmt_int(fi, u, 2, false, 8*size_of(rawptr), __DIGITS_UPPER) + case 'o': _fmt_int(fi, u, 8, false, 8*size_of(rawptr), __DIGITS_UPPER) + case 'i', 'd': _fmt_int(fi, u, 10, false, 8*size_of(rawptr), __DIGITS_UPPER) + case 'z': _fmt_int(fi, u, 12, false, 8*size_of(rawptr), __DIGITS_UPPER) + case 'x': _fmt_int(fi, u, 16, false, 8*size_of(rawptr), __DIGITS_UPPER) + case 'X': _fmt_int(fi, u, 16, false, 8*size_of(rawptr), __DIGITS_UPPER) case: - fmt_bad_verb(fi, verb); + fmt_bad_verb(fi, verb) } } enum_value_to_string :: proc(val: any) -> (string, bool) { - v := val; - v.id = runtime.typeid_base(v.id); - type_info := type_info_of(v.id); + v := val + v.id = runtime.typeid_base(v.id) + type_info := type_info_of(v.id) #partial switch e in type_info.variant { - case: return "", false; + case: return "", false case runtime.Type_Info_Enum: - Enum_Value :: runtime.Type_Info_Enum_Value; + Enum_Value :: runtime.Type_Info_Enum_Value - ev_, ok := reflect.as_i64(val); - ev := Enum_Value(ev_); + ev_, ok := reflect.as_i64(val) + ev := Enum_Value(ev_) if ok { if len(e.values) == 0 { - return "", true; + return "", true } else { for val, idx in e.values { if val == ev { - return e.names[idx], true; + return e.names[idx], true } } } - return "", false; + return "", false } } - return "", false; + return "", false } string_to_enum_value :: proc($T: typeid, s: string) -> (T, bool) { - ti := runtime.type_info_base(type_info_of(T)); + ti := runtime.type_info_base(type_info_of(T)) if e, ok := ti.variant.(runtime.Type_Info_Enum); ok { for str, idx in e.names { if s == str { // NOTE(bill): Unsafe cast - ptr := cast(^T)&e.values[idx]; - return ptr^, true; + ptr := cast(^T)&e.values[idx] + return ptr^, true } } } - return T{}, false; + return T{}, false } fmt_enum :: proc(fi: ^Info, v: any, verb: rune) { if v.id == nil || v.data == nil { - io.write_string(fi.writer, "<nil>"); - return; + io.write_string(fi.writer, "<nil>") + return } - type_info := type_info_of(v.id); + type_info := type_info_of(v.id) #partial switch e in type_info.variant { - case: fmt_bad_verb(fi, verb); + case: fmt_bad_verb(fi, verb) case runtime.Type_Info_Enum: switch verb { - case: fmt_bad_verb(fi, verb); + case: fmt_bad_verb(fi, verb) case 'i', 'd', 'f': - fmt_arg(fi, any{v.data, runtime.type_info_base(e.base).id}, verb); + fmt_arg(fi, any{v.data, runtime.type_info_base(e.base).id}, verb) case 's', 'v': - str, ok := enum_value_to_string(v); + str, ok := enum_value_to_string(v) if !ok { - str = "%!(BAD ENUM VALUE)"; + str = "%!(BAD ENUM VALUE)" } - io.write_string(fi.writer, str); + io.write_string(fi.writer, str) } } } stored_enum_value_to_string :: proc(enum_type: ^runtime.Type_Info, ev: runtime.Type_Info_Enum_Value, offset: int = 0) -> (string, bool) { - et := runtime.type_info_base(enum_type); - ev := ev; - ev += runtime.Type_Info_Enum_Value(offset); + et := runtime.type_info_base(enum_type) + ev := ev + ev += runtime.Type_Info_Enum_Value(offset) #partial switch e in et.variant { - case: return "", false; + case: return "", false case runtime.Type_Info_Enum: if reflect.is_string(e.base) { for val, idx in e.values { if val == ev { - return e.names[idx], true; + return e.names[idx], true } } } else if len(e.values) == 0 { - return "", true; + return "", true } else { for val, idx in e.values { if val == ev { - return e.names[idx], true; + return e.names[idx], true } } } - return "", false; + return "", false } - return "", false; + return "", false } fmt_bit_set :: proc(fi: ^Info, v: any, name: string = "") { is_bit_set_different_endian_to_platform :: proc(ti: ^runtime.Type_Info) -> bool { if ti == nil { - return false; + return false } - t := runtime.type_info_base(ti); + t := runtime.type_info_base(ti) #partial switch info in t.variant { case runtime.Type_Info_Integer: switch info.endianness { - case .Platform: return false; - case .Little: return ODIN_ENDIAN != "little"; - case .Big: return ODIN_ENDIAN != "big"; + case .Platform: return false + case .Little: return ODIN_ENDIAN != "little" + case .Big: return ODIN_ENDIAN != "big" } } - return false; + return false } - byte_swap :: bits.byte_swap; + byte_swap :: bits.byte_swap - type_info := type_info_of(v.id); + type_info := type_info_of(v.id) #partial switch info in type_info.variant { case runtime.Type_Info_Named: - val := v; - val.id = info.base.id; - fmt_bit_set(fi, val, info.name); + val := v + val.id = info.base.id + fmt_bit_set(fi, val, info.name) case runtime.Type_Info_Bit_Set: - bits: u128; - bit_size := u128(8*type_info.size); + bits: u128 + bit_size := u128(8*type_info.size) - do_byte_swap := is_bit_set_different_endian_to_platform(info.underlying); + do_byte_swap := is_bit_set_different_endian_to_platform(info.underlying) switch bit_size { - case 0: bits = 0; + case 0: bits = 0 case 8: - x := (^u8)(v.data)^; - bits = u128(x); + x := (^u8)(v.data)^ + bits = u128(x) case 16: - x := (^u16)(v.data)^; + x := (^u16)(v.data)^ if do_byte_swap { x = byte_swap(x); } - bits = u128(x); + bits = u128(x) case 32: - x := (^u32)(v.data)^; + x := (^u32)(v.data)^ if do_byte_swap { x = byte_swap(x); } - bits = u128(x); + bits = u128(x) case 64: - x := (^u64)(v.data)^; + x := (^u64)(v.data)^ if do_byte_swap { x = byte_swap(x); } - bits = u128(x); + bits = u128(x) case 128: - x := (^u128)(v.data)^; + x := (^u128)(v.data)^ if do_byte_swap { x = byte_swap(x); } - bits = x; - case: panic("unknown bit_size size"); + bits = x + case: panic("unknown bit_size size") } - et := runtime.type_info_base(info.elem); + et := runtime.type_info_base(info.elem) if name != "" { - io.write_string(fi.writer, name); + io.write_string(fi.writer, name) } else { - reflect.write_type(fi.writer, type_info); + reflect.write_type(fi.writer, type_info) } - io.write_byte(fi.writer, '{'); - defer io.write_byte(fi.writer, '}'); + io.write_byte(fi.writer, '{') + defer io.write_byte(fi.writer, '}') - e, is_enum := et.variant.(runtime.Type_Info_Enum); - commas := 0; + e, is_enum := et.variant.(runtime.Type_Info_Enum) + commas := 0 loop: for i in 0 ..< bit_size { if bits & (1<<i) == 0 { - continue loop; + continue loop } if commas > 0 { - io.write_string(fi.writer, ", "); + io.write_string(fi.writer, ", ") } if is_enum { for ev, evi in e.values { - v := u64(ev); + v := u64(ev) if v == u64(i) { - io.write_string(fi.writer, e.names[evi]); - commas += 1; - continue loop; + io.write_string(fi.writer, e.names[evi]) + commas += 1 + continue loop } } } - v := i64(i) + info.lower; - io.write_i64(fi.writer, v, 10); - commas += 1; + v := i64(i) + info.lower + io.write_i64(fi.writer, v, 10) + commas += 1 } } } fmt_write_indent :: proc(fi: ^Info) { for in 0..<fi.indent { - io.write_byte(fi.writer, '\t'); + io.write_byte(fi.writer, '\t') } } fmt_write_array :: proc(fi: ^Info, array_data: rawptr, count: int, elem_size: int, elem_id: typeid, verb: rune) { - io.write_byte(fi.writer, '['); - defer io.write_byte(fi.writer, ']'); + io.write_byte(fi.writer, '[') + defer io.write_byte(fi.writer, ']') if fi.hash { - io.write_byte(fi.writer, '\n'); - defer fmt_write_indent(fi); + io.write_byte(fi.writer, '\n') + defer fmt_write_indent(fi) - indent := fi.indent; - fi.indent += 1; - defer fi.indent = indent; + indent := fi.indent + fi.indent += 1 + defer fi.indent = indent for i in 0..<count { - fmt_write_indent(fi); + fmt_write_indent(fi) - data := uintptr(array_data) + uintptr(i*elem_size); - fmt_arg(fi, any{rawptr(data), elem_id}, verb); + data := uintptr(array_data) + uintptr(i*elem_size) + fmt_arg(fi, any{rawptr(data), elem_id}, verb) - io.write_string(fi.writer, ",\n"); + io.write_string(fi.writer, ",\n") } } else { for i in 0..<count { if i > 0 { io.write_string(fi.writer, ", "); } - data := uintptr(array_data) + uintptr(i*elem_size); - fmt_arg(fi, any{rawptr(data), elem_id}, verb); + data := uintptr(array_data) + uintptr(i*elem_size) + fmt_arg(fi, any{rawptr(data), elem_id}, verb) } } } fmt_value :: proc(fi: ^Info, v: any, verb: rune) { write_padded_number :: proc(fi: ^Info, i: i64, width: int) { - n := width-1; + n := width-1 for x := i; x >= 10; x /= 10 { - n -= 1; + n -= 1 } for in 0..<n { - io.write_byte(fi.writer, '0'); + io.write_byte(fi.writer, '0') } - io.write_i64(fi.writer, i, 10); + io.write_i64(fi.writer, i, 10) } if v.data == nil || v.id == nil { - io.write_string(fi.writer, "<nil>"); - return; + io.write_string(fi.writer, "<nil>") + return } if _user_formatters != nil && !fi.ignore_user_formatters { - formatter := _user_formatters[v.id]; + formatter := _user_formatters[v.id] if formatter != nil { - fi.ignore_user_formatters = false; + fi.ignore_user_formatters = false if ok := formatter(fi, v, verb); !ok { - fi.ignore_user_formatters = true; - fmt_bad_verb(fi, verb); + fi.ignore_user_formatters = true + fmt_bad_verb(fi, verb) } - return; + return } } - fi.ignore_user_formatters = false; + fi.ignore_user_formatters = false - type_info := type_info_of(v.id); + type_info := type_info_of(v.id) switch info in type_info.variant { case runtime.Type_Info_Any: // Ignore case runtime.Type_Info_Tuple: // Ignore @@ -1285,224 +1285,224 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { // Built-in Custom Formatters for core library types switch a in v { case runtime.Source_Code_Location: - io.write_string(fi.writer, a.file_path); - io.write_byte(fi.writer, '('); - io.write_int(fi.writer, int(a.line)); - io.write_byte(fi.writer, ':'); - io.write_int(fi.writer, int(a.column)); - io.write_byte(fi.writer, ')'); - return; + io.write_string(fi.writer, a.file_path) + io.write_byte(fi.writer, '(') + io.write_int(fi.writer, int(a.line)) + io.write_byte(fi.writer, ':') + io.write_int(fi.writer, int(a.column)) + io.write_byte(fi.writer, ')') + return case time.Duration: ffrac :: proc(buf: []byte, v: u64, prec: int) -> (nw: int, nv: u64) { - v := v; - w := len(buf); - print := false; + v := v + w := len(buf) + print := false for in 0..<prec { - digit := v % 10; - print = print || digit != 0; + digit := v % 10 + print = print || digit != 0 if print { - w -= 1; - buf[w] = byte(digit) + '0'; + w -= 1 + buf[w] = byte(digit) + '0' } - v /= 10; + v /= 10 } if print { - w -= 1; - buf[w] = '.'; + w -= 1 + buf[w] = '.' } - return w, v; + return w, v } fint :: proc(buf: []byte, v: u64) -> int { - v := v; - w := len(buf); + v := v + w := len(buf) if v == 0 { - w -= 1; - buf[w] = '0'; + w -= 1 + buf[w] = '0' } else { for v > 0 { - w -= 1; - buf[w] = byte(v%10) + '0'; - v /= 10; + w -= 1 + buf[w] = byte(v%10) + '0' + v /= 10 } } - return w; + return w } - buf: [32]byte; - w := len(buf); - u := u64(a); - neg := a < 0; + buf: [32]byte + w := len(buf) + u := u64(a) + neg := a < 0 if neg { - u = -u; + u = -u } if u < u64(time.Second) { - prec: int; - w -= 1; - buf[w] = 's'; - w -= 1; + prec: int + w -= 1 + buf[w] = 's' + w -= 1 switch { case u == 0: - io.write_string(fi.writer, "0s"); - return; + io.write_string(fi.writer, "0s") + return case u < u64(time.Microsecond): - prec = 0; - buf[w] = 'n'; + prec = 0 + buf[w] = 'n' case u < u64(time.Millisecond): - prec = 3; + prec = 3 // U+00B5 'µ' micro sign == 0xC2 0xB5 - w -= 1; // Need room for two bytes - copy(buf[w:], "µ"); + w -= 1 // Need room for two bytes + copy(buf[w:], "µ") case: - prec = 6; - buf[w] = 'm'; + prec = 6 + buf[w] = 'm' } - w, u = ffrac(buf[:w], u, prec); - w = fint(buf[:w], u); + w, u = ffrac(buf[:w], u, prec) + w = fint(buf[:w], u) } else { - w -= 1; - buf[w] = 's'; - w, u = ffrac(buf[:w], u, 9); - w = fint(buf[:w], u%60); - u /= 60; + w -= 1 + buf[w] = 's' + w, u = ffrac(buf[:w], u, 9) + w = fint(buf[:w], u%60) + u /= 60 if u > 0 { - w -= 1; - buf[w] = 'm'; - w = fint(buf[:w], u%60); - u /= 60; + w -= 1 + buf[w] = 'm' + w = fint(buf[:w], u%60) + u /= 60 if u > 0 { - w -= 1; - buf[w] = 'h'; - w = fint(buf[:w], u); + w -= 1 + buf[w] = 'h' + w = fint(buf[:w], u) } } } if neg { - w -= 1; - buf[w] = '-'; + w -= 1 + buf[w] = '-' } - io.write_string(fi.writer, string(buf[w:])); - return; + io.write_string(fi.writer, string(buf[w:])) + return case time.Time: - t := a; - y, mon, d := time.date(t); - h, min, s := time.clock(t); - ns := (t._nsec - (t._nsec/1e9 + time.UNIX_TO_ABSOLUTE)*1e9) % 1e9; - write_padded_number(fi, i64(y), 4); - io.write_byte(fi.writer, '-'); - write_padded_number(fi, i64(mon), 2); - io.write_byte(fi.writer, '-'); - write_padded_number(fi, i64(d), 2); - io.write_byte(fi.writer, ' '); - - write_padded_number(fi, i64(h), 2); - io.write_byte(fi.writer, ':'); - write_padded_number(fi, i64(min), 2); - io.write_byte(fi.writer, ':'); - write_padded_number(fi, i64(s), 2); - io.write_byte(fi.writer, '.'); - write_padded_number(fi, (ns), 9); - io.write_string(fi.writer, " +0000 UTC"); - return; + t := a + y, mon, d := time.date(t) + h, min, s := time.clock(t) + ns := (t._nsec - (t._nsec/1e9 + time.UNIX_TO_ABSOLUTE)*1e9) % 1e9 + write_padded_number(fi, i64(y), 4) + io.write_byte(fi.writer, '-') + write_padded_number(fi, i64(mon), 2) + io.write_byte(fi.writer, '-') + write_padded_number(fi, i64(d), 2) + io.write_byte(fi.writer, ' ') + + write_padded_number(fi, i64(h), 2) + io.write_byte(fi.writer, ':') + write_padded_number(fi, i64(min), 2) + io.write_byte(fi.writer, ':') + write_padded_number(fi, i64(s), 2) + io.write_byte(fi.writer, '.') + write_padded_number(fi, (ns), 9) + io.write_string(fi.writer, " +0000 UTC") + return } #partial switch b in info.base.variant { case runtime.Type_Info_Struct: if verb != 'v' { - fmt_bad_verb(fi, verb); - return; + fmt_bad_verb(fi, verb) + return } if b.is_raw_union { - io.write_string(fi.writer, info.name); - io.write_string(fi.writer, "{}"); - return; + io.write_string(fi.writer, info.name) + io.write_string(fi.writer, "{}") + return }; - is_soa := b.soa_kind != .None; + is_soa := b.soa_kind != .None - io.write_string(fi.writer, info.name); - io.write_byte(fi.writer, '[' if is_soa else '{'); + io.write_string(fi.writer, info.name) + io.write_byte(fi.writer, '[' if is_soa else '{') - hash := fi.hash; defer fi.hash = hash; - indent := fi.indent; defer fi.indent -= 1; + hash := fi.hash; defer fi.hash = hash + indent := fi.indent; defer fi.indent -= 1 // fi.hash = false; - fi.indent += 1; + fi.indent += 1 if hash { - io.write_byte(fi.writer, '\n'); + io.write_byte(fi.writer, '\n') } defer { if hash { for in 0..<indent { io.write_byte(fi.writer, '\t'); } } - io.write_byte(fi.writer, ']' if is_soa else '}'); + io.write_byte(fi.writer, ']' if is_soa else '}') } if is_soa { - fi.indent += 1; - defer fi.indent -= 1; + fi.indent += 1 + defer fi.indent -= 1 - base_type_name: string; + base_type_name: string if v, ok := b.soa_base_type.variant.(runtime.Type_Info_Named); ok { - base_type_name = v.name; + base_type_name = v.name } for index in 0..<uintptr(b.soa_len) { if !hash && index > 0 { io.write_string(fi.writer, ", "); } - field_count := -1; + field_count := -1 if !hash && field_count > 0 { io.write_string(fi.writer, ", "); } - io.write_string(fi.writer, base_type_name); - io.write_byte(fi.writer, '{'); - defer io.write_byte(fi.writer, '}'); + io.write_string(fi.writer, base_type_name) + io.write_byte(fi.writer, '{') + defer io.write_byte(fi.writer, '}') for name, i in b.names { - field_count += 1; + field_count += 1 if !hash && field_count > 0 { io.write_string(fi.writer, ", "); } if hash { - fmt_write_indent(fi); + fmt_write_indent(fi) } - io.write_string(fi.writer, name); - io.write_string(fi.writer, " = "); + io.write_string(fi.writer, name) + io.write_string(fi.writer, " = ") - t := b.types[i].variant.(runtime.Type_Info_Array).elem; - t_size := uintptr(t.size); + t := b.types[i].variant.(runtime.Type_Info_Array).elem + t_size := uintptr(t.size) if reflect.is_any(t) { - io.write_string(fi.writer, "any{}"); + io.write_string(fi.writer, "any{}") } else { - data := rawptr(uintptr(v.data) + b.offsets[i] + index*t_size); - fmt_arg(fi, any{data, t.id}, 'v'); + data := rawptr(uintptr(v.data) + b.offsets[i] + index*t_size) + fmt_arg(fi, any{data, t.id}, 'v') } if hash { io.write_string(fi.writer, ",\n"); } } } } else { - field_count := -1; + field_count := -1 for name, i in b.names { - field_count += 1; + field_count += 1 if !hash && field_count > 0 { io.write_string(fi.writer, ", "); } if hash { - fmt_write_indent(fi); + fmt_write_indent(fi) } - io.write_string(fi.writer, name); - io.write_string(fi.writer, " = "); + io.write_string(fi.writer, name) + io.write_string(fi.writer, " = ") if t := b.types[i]; reflect.is_any(t) { - io.write_string(fi.writer, "any{}"); + io.write_string(fi.writer, "any{}") } else { - data := rawptr(uintptr(v.data) + b.offsets[i]); - fmt_arg(fi, any{data, t.id}, 'v'); + data := rawptr(uintptr(v.data) + b.offsets[i]) + fmt_arg(fi, any{data, t.id}, 'v') } if hash { io.write_string(fi.writer, ",\n"); } @@ -1510,28 +1510,28 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { } case runtime.Type_Info_Bit_Set: - fmt_bit_set(fi, v); + fmt_bit_set(fi, v) case: - fmt_value(fi, any{v.data, info.base.id}, verb); + fmt_value(fi, any{v.data, info.base.id}, verb) } - case runtime.Type_Info_Boolean: fmt_arg(fi, v, verb); - case runtime.Type_Info_Integer: fmt_arg(fi, v, verb); - case runtime.Type_Info_Rune: fmt_arg(fi, v, verb); - case runtime.Type_Info_Float: fmt_arg(fi, v, verb); - case runtime.Type_Info_Complex: fmt_arg(fi, v, verb); - case runtime.Type_Info_Quaternion: fmt_arg(fi, v, verb); - case runtime.Type_Info_String: fmt_arg(fi, v, verb); + case runtime.Type_Info_Boolean: fmt_arg(fi, v, verb) + case runtime.Type_Info_Integer: fmt_arg(fi, v, verb) + case runtime.Type_Info_Rune: fmt_arg(fi, v, verb) + case runtime.Type_Info_Float: fmt_arg(fi, v, verb) + case runtime.Type_Info_Complex: fmt_arg(fi, v, verb) + case runtime.Type_Info_Quaternion: fmt_arg(fi, v, verb) + case runtime.Type_Info_String: fmt_arg(fi, v, verb) case runtime.Type_Info_Pointer: if v.id == typeid_of(^runtime.Type_Info) { - reflect.write_type(fi.writer, (^^runtime.Type_Info)(v.data)^); + reflect.write_type(fi.writer, (^^runtime.Type_Info)(v.data)^) } else { - ptr := (^rawptr)(v.data)^; + ptr := (^rawptr)(v.data)^ if verb != 'p' && info.elem != nil { - a := any{ptr, info.elem.id}; + a := any{ptr, info.elem.id} - elem := runtime.type_info_base(info.elem); + elem := runtime.type_info_base(info.elem) if elem != nil { #partial switch e in elem.variant { case runtime.Type_Info_Array, @@ -1539,42 +1539,42 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { runtime.Type_Info_Dynamic_Array, runtime.Type_Info_Map: if ptr == nil { - io.write_string(fi.writer, "<nil>"); - return; + io.write_string(fi.writer, "<nil>") + return } if fi.record_level < 1 { - fi.record_level += 1; - defer fi.record_level -= 1; - io.write_byte(fi.writer, '&'); - fmt_value(fi, a, verb); - return; + fi.record_level += 1 + defer fi.record_level -= 1 + io.write_byte(fi.writer, '&') + fmt_value(fi, a, verb) + return } case runtime.Type_Info_Struct, runtime.Type_Info_Union: if ptr == nil { - io.write_string(fi.writer, "<nil>"); - return; + io.write_string(fi.writer, "<nil>") + return } if fi.record_level < 1 { - fi.record_level += 1; - defer fi.record_level -= 1; - io.write_byte(fi.writer, '&'); - fmt_value(fi, a, verb); - return; + fi.record_level += 1 + defer fi.record_level -= 1 + io.write_byte(fi.writer, '&') + fmt_value(fi, a, verb) + return } } } } - fmt_pointer(fi, ptr, verb); + fmt_pointer(fi, ptr, verb) } case runtime.Type_Info_Multi_Pointer: - ptr := (^rawptr)(v.data)^; + ptr := (^rawptr)(v.data)^ if verb != 'p' && info.elem != nil { - a := any{ptr, info.elem.id}; + a := any{ptr, info.elem.id} - elem := runtime.type_info_base(info.elem); + elem := runtime.type_info_base(info.elem) if elem != nil { #partial switch e in elem.variant { case runtime.Type_Info_Array, @@ -1582,199 +1582,199 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { runtime.Type_Info_Dynamic_Array, runtime.Type_Info_Map: if ptr == nil { - io.write_string(fi.writer, "<nil>"); - return; + io.write_string(fi.writer, "<nil>") + return } if fi.record_level < 1 { - fi.record_level += 1; - defer fi.record_level -= 1; - io.write_byte(fi.writer, '&'); - fmt_value(fi, a, verb); - return; + fi.record_level += 1 + defer fi.record_level -= 1 + io.write_byte(fi.writer, '&') + fmt_value(fi, a, verb) + return } case runtime.Type_Info_Struct, runtime.Type_Info_Union: if ptr == nil { - io.write_string(fi.writer, "<nil>"); - return; + io.write_string(fi.writer, "<nil>") + return } if fi.record_level < 1 { - fi.record_level += 1; - defer fi.record_level -= 1; - io.write_byte(fi.writer, '&'); - fmt_value(fi, a, verb); - return; + fi.record_level += 1 + defer fi.record_level -= 1 + io.write_byte(fi.writer, '&') + fmt_value(fi, a, verb) + return } } } } - fmt_pointer(fi, ptr, verb); + fmt_pointer(fi, ptr, verb) case runtime.Type_Info_Array: if (verb == 's' || verb == 'q') && reflect.is_byte(info.elem) { - s := strings.string_from_ptr((^byte)(v.data), info.count); - fmt_string(fi, s, verb); + s := strings.string_from_ptr((^byte)(v.data), info.count) + fmt_string(fi, s, verb) } else { - fmt_write_array(fi, v.data, info.count, info.elem_size, info.elem.id, verb); + fmt_write_array(fi, v.data, info.count, info.elem_size, info.elem.id, verb) } case runtime.Type_Info_Enumerated_Array: if fi.hash { - io.write_string(fi.writer, "[\n"); + io.write_string(fi.writer, "[\n") defer { - io.write_byte(fi.writer, '\n'); - fmt_write_indent(fi); - io.write_byte(fi.writer, ']'); + io.write_byte(fi.writer, '\n') + fmt_write_indent(fi) + io.write_byte(fi.writer, ']') } - indent := fi.indent; - fi.indent += 1; - defer fi.indent = indent; + indent := fi.indent + fi.indent += 1 + defer fi.indent = indent for i in 0..<info.count { - fmt_write_indent(fi); + fmt_write_indent(fi) - idx, ok := stored_enum_value_to_string(info.index, info.min_value, i); + idx, ok := stored_enum_value_to_string(info.index, info.min_value, i) if ok { - io.write_byte(fi.writer, '.'); - io.write_string(fi.writer, idx); + io.write_byte(fi.writer, '.') + io.write_string(fi.writer, idx) } else { - io.write_i64(fi.writer, i64(info.min_value)+i64(i)); + io.write_i64(fi.writer, i64(info.min_value)+i64(i)) } - io.write_string(fi.writer, " = "); + io.write_string(fi.writer, " = ") - data := uintptr(v.data) + uintptr(i*info.elem_size); - fmt_arg(fi, any{rawptr(data), info.elem.id}, verb); + data := uintptr(v.data) + uintptr(i*info.elem_size) + fmt_arg(fi, any{rawptr(data), info.elem.id}, verb) - io.write_string(fi.writer, ",\n"); + io.write_string(fi.writer, ",\n") } } else { - io.write_byte(fi.writer, '['); - defer io.write_byte(fi.writer, ']'); + io.write_byte(fi.writer, '[') + defer io.write_byte(fi.writer, ']') for i in 0..<info.count { if i > 0 { io.write_string(fi.writer, ", "); } - idx, ok := stored_enum_value_to_string(info.index, info.min_value, i); + idx, ok := stored_enum_value_to_string(info.index, info.min_value, i) if ok { - io.write_byte(fi.writer, '.'); - io.write_string(fi.writer, idx); + io.write_byte(fi.writer, '.') + io.write_string(fi.writer, idx) } else { - io.write_i64(fi.writer, i64(info.min_value)+i64(i)); + io.write_i64(fi.writer, i64(info.min_value)+i64(i)) } - io.write_string(fi.writer, " = "); + io.write_string(fi.writer, " = ") - data := uintptr(v.data) + uintptr(i*info.elem_size); - fmt_arg(fi, any{rawptr(data), info.elem.id}, verb); + data := uintptr(v.data) + uintptr(i*info.elem_size) + fmt_arg(fi, any{rawptr(data), info.elem.id}, verb) } } case runtime.Type_Info_Dynamic_Array: - array := cast(^mem.Raw_Dynamic_Array)v.data; + array := cast(^mem.Raw_Dynamic_Array)v.data if (verb == 's' || verb == 'q') && reflect.is_byte(info.elem) { - s := strings.string_from_ptr((^byte)(array.data), array.len); - fmt_string(fi, s, verb); + s := strings.string_from_ptr((^byte)(array.data), array.len) + fmt_string(fi, s, verb) } else if verb == 'p' { - fmt_pointer(fi, array.data, 'p'); + fmt_pointer(fi, array.data, 'p') } else { - fmt_write_array(fi, array.data, array.len, info.elem_size, info.elem.id, verb); + fmt_write_array(fi, array.data, array.len, info.elem_size, info.elem.id, verb) } case runtime.Type_Info_Simd_Vector: - io.write_byte(fi.writer, '<'); - defer io.write_byte(fi.writer, '>'); + io.write_byte(fi.writer, '<') + defer io.write_byte(fi.writer, '>') for i in 0..<info.count { if i > 0 { io.write_string(fi.writer, ", "); } - data := uintptr(v.data) + uintptr(i*info.elem_size); - fmt_arg(fi, any{rawptr(data), info.elem.id}, verb); + data := uintptr(v.data) + uintptr(i*info.elem_size) + fmt_arg(fi, any{rawptr(data), info.elem.id}, verb) } case runtime.Type_Info_Slice: - slice := cast(^mem.Raw_Slice)v.data; + slice := cast(^mem.Raw_Slice)v.data if (verb == 's' || verb == 'q') && reflect.is_byte(info.elem) { - s := strings.string_from_ptr((^byte)(slice.data), slice.len); - fmt_string(fi, s, verb); + s := strings.string_from_ptr((^byte)(slice.data), slice.len) + fmt_string(fi, s, verb) } else if verb == 'p' { - fmt_pointer(fi, slice.data, 'p'); + fmt_pointer(fi, slice.data, 'p') } else { - fmt_write_array(fi, slice.data, slice.len, info.elem_size, info.elem.id, verb); + fmt_write_array(fi, slice.data, slice.len, info.elem_size, info.elem.id, verb) } case runtime.Type_Info_Map: if verb != 'v' { - fmt_bad_verb(fi, verb); - return; + fmt_bad_verb(fi, verb) + return } - io.write_string(fi.writer, "map["); - defer io.write_byte(fi.writer, ']'); + io.write_string(fi.writer, "map[") + defer io.write_byte(fi.writer, ']') - m := (^mem.Raw_Map)(v.data); + m := (^mem.Raw_Map)(v.data) if m != nil { if info.generated_struct == nil { - return; + return } - entries := &m.entries; - gs := runtime.type_info_base(info.generated_struct).variant.(runtime.Type_Info_Struct); - ed := runtime.type_info_base(gs.types[1]).variant.(runtime.Type_Info_Dynamic_Array); - entry_type := ed.elem.variant.(runtime.Type_Info_Struct); - entry_size := ed.elem_size; + entries := &m.entries + gs := runtime.type_info_base(info.generated_struct).variant.(runtime.Type_Info_Struct) + ed := runtime.type_info_base(gs.types[1]).variant.(runtime.Type_Info_Dynamic_Array) + entry_type := ed.elem.variant.(runtime.Type_Info_Struct) + entry_size := ed.elem_size for i in 0..<entries.len { if i > 0 { io.write_string(fi.writer, ", "); } - data := uintptr(entries.data) + uintptr(i*entry_size); + data := uintptr(entries.data) + uintptr(i*entry_size) - key := data + entry_type.offsets[2]; - fmt_arg(&Info{writer = fi.writer}, any{rawptr(key), info.key.id}, 'v'); + key := data + entry_type.offsets[2] + fmt_arg(&Info{writer = fi.writer}, any{rawptr(key), info.key.id}, 'v') - io.write_string(fi.writer, "="); + io.write_string(fi.writer, "=") - value := data + entry_type.offsets[3]; - fmt_arg(fi, any{rawptr(value), info.value.id}, 'v'); + value := data + entry_type.offsets[3] + fmt_arg(fi, any{rawptr(value), info.value.id}, 'v') } } case runtime.Type_Info_Struct: if info.is_raw_union { - io.write_string(fi.writer, "(raw_union)"); - return; + io.write_string(fi.writer, "(raw_union)") + return } - is_soa := info.soa_kind != .None; + is_soa := info.soa_kind != .None - io.write_byte(fi.writer, '[' if is_soa else '{'); - defer io.write_byte(fi.writer, ']' if is_soa else '}'); + io.write_byte(fi.writer, '[' if is_soa else '{') + defer io.write_byte(fi.writer, ']' if is_soa else '}') - fi.indent += 1; defer fi.indent -= 1; - hash := fi.hash; defer fi.hash = hash; + fi.indent += 1; defer fi.indent -= 1 + hash := fi.hash; defer fi.hash = hash // fi.hash = false; if hash { io.write_byte(fi.writer, '\n'); } if is_soa { - fi.indent += 1; - defer fi.indent -= 1; + fi.indent += 1 + defer fi.indent -= 1 - base_type_name: string; + base_type_name: string if v, ok := info.soa_base_type.variant.(runtime.Type_Info_Named); ok { - base_type_name = v.name; + base_type_name = v.name } - actual_field_count := len(info.names); + actual_field_count := len(info.names) - n := uintptr(info.soa_len); + n := uintptr(info.soa_len) if info.soa_kind == .Slice { - actual_field_count = len(info.names)-1; // len + actual_field_count = len(info.names)-1 // len - n = uintptr((^int)(uintptr(v.data) + info.offsets[actual_field_count])^); + n = uintptr((^int)(uintptr(v.data) + info.offsets[actual_field_count])^) } else if info.soa_kind == .Dynamic { - actual_field_count = len(info.names)-3; // len, cap, allocator + actual_field_count = len(info.names)-3 // len, cap, allocator - n = uintptr((^int)(uintptr(v.data) + info.offsets[actual_field_count])^); + n = uintptr((^int)(uintptr(v.data) + info.offsets[actual_field_count])^) } @@ -1782,44 +1782,44 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { for index in 0..<n { if !hash && index > 0 { io.write_string(fi.writer, ", "); } - field_count := -1; + field_count := -1 if !hash && field_count > 0 { io.write_string(fi.writer, ", "); } - io.write_string(fi.writer, base_type_name); - io.write_byte(fi.writer, '{'); - defer io.write_byte(fi.writer, '}'); + io.write_string(fi.writer, base_type_name) + io.write_byte(fi.writer, '{') + defer io.write_byte(fi.writer, '}') for i in 0..<actual_field_count { - name := info.names[i]; - field_count += 1; + name := info.names[i] + field_count += 1 if !hash && field_count > 0 { io.write_string(fi.writer, ", "); } if hash { - fmt_write_indent(fi); + fmt_write_indent(fi) } - io.write_string(fi.writer, name); - io.write_string(fi.writer, " = "); + io.write_string(fi.writer, name) + io.write_string(fi.writer, " = ") if info.soa_kind == .Fixed { - t := info.types[i].variant.(runtime.Type_Info_Array).elem; - t_size := uintptr(t.size); + t := info.types[i].variant.(runtime.Type_Info_Array).elem + t_size := uintptr(t.size) if reflect.is_any(t) { - io.write_string(fi.writer, "any{}"); + io.write_string(fi.writer, "any{}") } else { - data := rawptr(uintptr(v.data) + info.offsets[i] + index*t_size); - fmt_arg(fi, any{data, t.id}, 'v'); + data := rawptr(uintptr(v.data) + info.offsets[i] + index*t_size) + fmt_arg(fi, any{data, t.id}, 'v') } } else { - t := info.types[i].variant.(runtime.Type_Info_Pointer).elem; - t_size := uintptr(t.size); + t := info.types[i].variant.(runtime.Type_Info_Pointer).elem + t_size := uintptr(t.size) if reflect.is_any(t) { - io.write_string(fi.writer, "any{}"); + io.write_string(fi.writer, "any{}") } else { - field_ptr := (^^byte)(uintptr(v.data) + info.offsets[i])^; - data := rawptr(uintptr(field_ptr) + index*t_size); - fmt_arg(fi, any{data, t.id}, 'v'); + field_ptr := (^^byte)(uintptr(v.data) + info.offsets[i])^ + data := rawptr(uintptr(field_ptr) + index*t_size) + fmt_arg(fi, any{data, t.id}, 'v') } } @@ -1827,27 +1827,27 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { } } } else { - field_count := -1; + field_count := -1 for name, i in info.names { - field_count += 1; + field_count += 1 if !hash && field_count > 0 { io.write_string(fi.writer, ", "); } if hash { - fmt_write_indent(fi); + fmt_write_indent(fi) } - io.write_string(fi.writer, name); - io.write_string(fi.writer, " = "); + io.write_string(fi.writer, name) + io.write_string(fi.writer, " = ") if t := info.types[i]; reflect.is_any(t) { - io.write_string(fi.writer, "any{}"); + io.write_string(fi.writer, "any{}") } else { - data := rawptr(uintptr(v.data) + info.offsets[i]); - fmt_arg(fi, any{data, t.id}, 'v'); + data := rawptr(uintptr(v.data) + info.offsets[i]) + fmt_arg(fi, any{data, t.id}, 'v') } if hash { - io.write_string(fi.writer, ",\n"); + io.write_string(fi.writer, ",\n") } } } @@ -1855,97 +1855,97 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { case runtime.Type_Info_Union: if type_info.size == 0 { - io.write_string(fi.writer, "nil"); - return; + io.write_string(fi.writer, "nil") + return } if reflect.type_info_union_is_pure_maybe(info) { if v.data == nil { - io.write_string(fi.writer, "nil"); + io.write_string(fi.writer, "nil") } else { - id := info.variants[0].id; - fmt_arg(fi, any{v.data, id}, verb); + id := info.variants[0].id + fmt_arg(fi, any{v.data, id}, verb) } - return; + return } - tag: i64 = -1; - tag_ptr := uintptr(v.data) + info.tag_offset; - tag_any := any{rawptr(tag_ptr), info.tag_type.id}; + tag: i64 = -1 + tag_ptr := uintptr(v.data) + info.tag_offset + tag_any := any{rawptr(tag_ptr), info.tag_type.id} switch i in tag_any { - case u8: tag = i64(i); - case i8: tag = i64(i); - case u16: tag = i64(i); - case i16: tag = i64(i); - case u32: tag = i64(i); - case i32: tag = i64(i); - case u64: tag = i64(i); - case i64: tag = i; - case: panic("Invalid union tag type"); - } - assert(tag >= 0); + case u8: tag = i64(i) + case i8: tag = i64(i) + case u16: tag = i64(i) + case i16: tag = i64(i) + case u32: tag = i64(i) + case i32: tag = i64(i) + case u64: tag = i64(i) + case i64: tag = i + case: panic("Invalid union tag type") + } + assert(tag >= 0) if v.data == nil { - io.write_string(fi.writer, "nil"); + io.write_string(fi.writer, "nil") } else if info.no_nil { - id := info.variants[tag].id; - fmt_arg(fi, any{v.data, id}, verb); + id := info.variants[tag].id + fmt_arg(fi, any{v.data, id}, verb) } else if tag == 0 { - io.write_string(fi.writer, "nil"); + io.write_string(fi.writer, "nil") } else { - id := info.variants[tag-1].id; - fmt_arg(fi, any{v.data, id}, verb); + id := info.variants[tag-1].id + fmt_arg(fi, any{v.data, id}, verb) } case runtime.Type_Info_Enum: - fmt_enum(fi, v, verb); + fmt_enum(fi, v, verb) case runtime.Type_Info_Procedure: - ptr := (^rawptr)(v.data)^; + ptr := (^rawptr)(v.data)^ if ptr == nil { - io.write_string(fi.writer, "nil"); + io.write_string(fi.writer, "nil") } else { - reflect.write_typeid(fi.writer, v.id); - io.write_string(fi.writer, " @ "); - fmt_pointer(fi, ptr, 'p'); + reflect.write_typeid(fi.writer, v.id) + io.write_string(fi.writer, " @ ") + fmt_pointer(fi, ptr, 'p') } case runtime.Type_Info_Type_Id: - id := (^typeid)(v.data)^; - reflect.write_typeid(fi.writer, id); + id := (^typeid)(v.data)^ + reflect.write_typeid(fi.writer, id) case runtime.Type_Info_Bit_Set: - fmt_bit_set(fi, v); + fmt_bit_set(fi, v) case runtime.Type_Info_Relative_Pointer: - ptr := reflect.relative_pointer_to_absolute_raw(v.data, info.base_integer.id); - absolute_ptr := any{ptr, info.pointer.id}; + ptr := reflect.relative_pointer_to_absolute_raw(v.data, info.base_integer.id) + absolute_ptr := any{ptr, info.pointer.id} - fmt_value(fi, absolute_ptr, verb); + fmt_value(fi, absolute_ptr, verb) case runtime.Type_Info_Relative_Slice: - ptr := reflect.relative_pointer_to_absolute_raw(v.data, info.base_integer.id); + ptr := reflect.relative_pointer_to_absolute_raw(v.data, info.base_integer.id) if verb == 'p' { - fmt_pointer(fi, ptr, 'p'); + fmt_pointer(fi, ptr, 'p') } else if ptr == nil { - io.write_string(fi.writer, "[]"); + io.write_string(fi.writer, "[]") } else { - len_ptr := uintptr(v.data) + uintptr(info.base_integer.size); - len_any := any{rawptr(len_ptr), info.base_integer.id}; - len, _ := reflect.as_int(len_any); - slice_type := reflect.type_info_base(info.slice).variant.(runtime.Type_Info_Slice); + len_ptr := uintptr(v.data) + uintptr(info.base_integer.size) + len_any := any{rawptr(len_ptr), info.base_integer.id} + len, _ := reflect.as_int(len_any) + slice_type := reflect.type_info_base(info.slice).variant.(runtime.Type_Info_Slice) - io.write_byte(fi.writer, '['); - defer io.write_byte(fi.writer, ']'); + io.write_byte(fi.writer, '[') + defer io.write_byte(fi.writer, ']') for i in 0..<len { if i > 0 { io.write_string(fi.writer, ", "); } - data := uintptr(ptr) + uintptr(i*slice_type.elem_size); - fmt_arg(fi, any{rawptr(data), slice_type.elem.id}, verb); + data := uintptr(ptr) + uintptr(i*slice_type.elem_size) + fmt_arg(fi, any{rawptr(data), slice_type.elem.id}, verb) } } @@ -1955,74 +1955,74 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { fmt_complex :: proc(fi: ^Info, c: complex128, bits: int, verb: rune) { switch verb { case 'f', 'F', 'v', 'h', 'H': - r, i := real(c), imag(c); - fmt_float(fi, r, bits/2, verb); + r, i := real(c), imag(c) + fmt_float(fi, r, bits/2, verb) if !fi.plus && i >= 0 { - io.write_rune(fi.writer, '+'); + io.write_rune(fi.writer, '+') } - fmt_float(fi, i, bits/2, verb); - io.write_rune(fi.writer, 'i'); + fmt_float(fi, i, bits/2, verb) + io.write_rune(fi.writer, 'i') case: - fmt_bad_verb(fi, verb); - return; + fmt_bad_verb(fi, verb) + return } } fmt_quaternion :: proc(fi: ^Info, q: quaternion256, bits: int, verb: rune) { switch verb { case 'f', 'F', 'v', 'h', 'H': - r, i, j, k := real(q), imag(q), jmag(q), kmag(q); + r, i, j, k := real(q), imag(q), jmag(q), kmag(q) - fmt_float(fi, r, bits/4, verb); + fmt_float(fi, r, bits/4, verb) if !fi.plus && i >= 0 { - io.write_rune(fi.writer, '+'); + io.write_rune(fi.writer, '+') } - fmt_float(fi, i, bits/4, verb); - io.write_rune(fi.writer, 'i'); + fmt_float(fi, i, bits/4, verb) + io.write_rune(fi.writer, 'i') if !fi.plus && j >= 0 { - io.write_rune(fi.writer, '+'); + io.write_rune(fi.writer, '+') } - fmt_float(fi, j, bits/4, verb); - io.write_rune(fi.writer, 'j'); + fmt_float(fi, j, bits/4, verb) + io.write_rune(fi.writer, 'j') if !fi.plus && k >= 0 { - io.write_rune(fi.writer, '+'); + io.write_rune(fi.writer, '+') } - fmt_float(fi, k, bits/4, verb); - io.write_rune(fi.writer, 'k'); + fmt_float(fi, k, bits/4, verb) + io.write_rune(fi.writer, 'k') case: - fmt_bad_verb(fi, verb); - return; + fmt_bad_verb(fi, verb) + return } } fmt_arg :: proc(fi: ^Info, arg: any, verb: rune) { if arg == nil { - io.write_string(fi.writer, "<nil>"); - return; + io.write_string(fi.writer, "<nil>") + return } - fi.arg = arg; + fi.arg = arg if verb == 'T' { - ti := type_info_of(arg.id); + ti := type_info_of(arg.id) switch a in arg { - case ^runtime.Type_Info: ti = a; + case ^runtime.Type_Info: ti = a } - reflect.write_type(fi.writer, ti); - return; + reflect.write_type(fi.writer, ti) + return } if _user_formatters != nil { - formatter := _user_formatters[arg.id]; + formatter := _user_formatters[arg.id] if formatter != nil { if ok := formatter(fi, arg, verb); !ok { - fmt_bad_verb(fi, verb); + fmt_bad_verb(fi, verb) } - return; + return } } @@ -2030,87 +2030,87 @@ fmt_arg :: proc(fi: ^Info, arg: any, verb: rune) { custom_types: switch a in arg { case runtime.Source_Code_Location: if fi.hash && verb == 'v' { - io.write_string(fi.writer, a.file_path); - io.write_byte(fi.writer, '('); - io.write_i64(fi.writer, i64(a.line), 10); - io.write_byte(fi.writer, ':'); - io.write_i64(fi.writer, i64(a.column), 10); - io.write_byte(fi.writer, ')'); - return; + io.write_string(fi.writer, a.file_path) + io.write_byte(fi.writer, '(') + io.write_i64(fi.writer, i64(a.line), 10) + io.write_byte(fi.writer, ':') + io.write_i64(fi.writer, i64(a.column), 10) + io.write_byte(fi.writer, ')') + return } } - base_arg := arg; - base_arg.id = runtime.typeid_base(base_arg.id); + base_arg := arg + base_arg.id = runtime.typeid_base(base_arg.id) switch a in base_arg { - case bool: fmt_bool(fi, a, verb); - case b8: fmt_bool(fi, bool(a), verb); - case b16: fmt_bool(fi, bool(a), verb); - case b32: fmt_bool(fi, bool(a), verb); - case b64: fmt_bool(fi, bool(a), verb); - - case any: fmt_arg(fi, a, verb); - case rune: fmt_rune(fi, a, verb); - - case f16: fmt_float(fi, f64(a), 16, verb); - case f32: fmt_float(fi, f64(a), 32, verb); - case f64: fmt_float(fi, a, 64, verb); - - case f16le: fmt_float(fi, f64(a), 16, verb); - case f32le: fmt_float(fi, f64(a), 32, verb); - case f64le: fmt_float(fi, f64(a), 64, verb); - - case f16be: fmt_float(fi, f64(a), 16, verb); - case f32be: fmt_float(fi, f64(a), 32, verb); - case f64be: fmt_float(fi, f64(a), 64, verb); - - case complex64: fmt_complex(fi, complex128(a), 64, verb); - case complex128: fmt_complex(fi, a, 128, verb); - - case quaternion128: fmt_quaternion(fi, quaternion256(a), 128, verb); - case quaternion256: fmt_quaternion(fi, a, 256, verb); - - case i8: fmt_int(fi, u64(a), true, 8, verb); - case u8: fmt_int(fi, u64(a), false, 8, verb); - case i16: fmt_int(fi, u64(a), true, 16, verb); - case u16: fmt_int(fi, u64(a), false, 16, verb); - case i32: fmt_int(fi, u64(a), true, 32, verb); - case u32: fmt_int(fi, u64(a), false, 32, verb); - case i64: fmt_int(fi, u64(a), true, 64, verb); - case u64: fmt_int(fi, a, false, 64, verb); - case int: fmt_int(fi, u64(a), true, 8*size_of(int), verb); - case uint: fmt_int(fi, u64(a), false, 8*size_of(uint), verb); - case uintptr: fmt_int(fi, u64(a), false, 8*size_of(uintptr), verb); - - case string: fmt_string(fi, a, verb); - case cstring: fmt_cstring(fi, a, verb); - - case typeid: reflect.write_typeid(fi.writer, a); - - case i16le: fmt_int(fi, u64(a), true, 16, verb); - case u16le: fmt_int(fi, u64(a), false, 16, verb); - case i32le: fmt_int(fi, u64(a), true, 32, verb); - case u32le: fmt_int(fi, u64(a), false, 32, verb); - case i64le: fmt_int(fi, u64(a), true, 64, verb); - case u64le: fmt_int(fi, u64(a), false, 64, verb); - - case i16be: fmt_int(fi, u64(a), true, 16, verb); - case u16be: fmt_int(fi, u64(a), false, 16, verb); - case i32be: fmt_int(fi, u64(a), true, 32, verb); - case u32be: fmt_int(fi, u64(a), false, 32, verb); - case i64be: fmt_int(fi, u64(a), true, 64, verb); - case u64be: fmt_int(fi, u64(a), false, 64, verb); - - case i128: fmt_int_128(fi, u128(a), true, 128, verb); - case u128: fmt_int_128(fi, a, false, 128, verb); - - case i128le: fmt_int_128(fi, u128(a), true, 128, verb); - case u128le: fmt_int_128(fi, u128(a), false, 128, verb); - - case i128be: fmt_int_128(fi, u128(a), true, 128, verb); - case u128be: fmt_int_128(fi, u128(a), false, 128, verb); - - case: fmt_value(fi, arg, verb); + case bool: fmt_bool(fi, a, verb) + case b8: fmt_bool(fi, bool(a), verb) + case b16: fmt_bool(fi, bool(a), verb) + case b32: fmt_bool(fi, bool(a), verb) + case b64: fmt_bool(fi, bool(a), verb) + + case any: fmt_arg(fi, a, verb) + case rune: fmt_rune(fi, a, verb) + + case f16: fmt_float(fi, f64(a), 16, verb) + case f32: fmt_float(fi, f64(a), 32, verb) + case f64: fmt_float(fi, a, 64, verb) + + case f16le: fmt_float(fi, f64(a), 16, verb) + case f32le: fmt_float(fi, f64(a), 32, verb) + case f64le: fmt_float(fi, f64(a), 64, verb) + + case f16be: fmt_float(fi, f64(a), 16, verb) + case f32be: fmt_float(fi, f64(a), 32, verb) + case f64be: fmt_float(fi, f64(a), 64, verb) + + case complex64: fmt_complex(fi, complex128(a), 64, verb) + case complex128: fmt_complex(fi, a, 128, verb) + + case quaternion128: fmt_quaternion(fi, quaternion256(a), 128, verb) + case quaternion256: fmt_quaternion(fi, a, 256, verb) + + case i8: fmt_int(fi, u64(a), true, 8, verb) + case u8: fmt_int(fi, u64(a), false, 8, verb) + case i16: fmt_int(fi, u64(a), true, 16, verb) + case u16: fmt_int(fi, u64(a), false, 16, verb) + case i32: fmt_int(fi, u64(a), true, 32, verb) + case u32: fmt_int(fi, u64(a), false, 32, verb) + case i64: fmt_int(fi, u64(a), true, 64, verb) + case u64: fmt_int(fi, a, false, 64, verb) + case int: fmt_int(fi, u64(a), true, 8*size_of(int), verb) + case uint: fmt_int(fi, u64(a), false, 8*size_of(uint), verb) + case uintptr: fmt_int(fi, u64(a), false, 8*size_of(uintptr), verb) + + case string: fmt_string(fi, a, verb) + case cstring: fmt_cstring(fi, a, verb) + + case typeid: reflect.write_typeid(fi.writer, a) + + case i16le: fmt_int(fi, u64(a), true, 16, verb) + case u16le: fmt_int(fi, u64(a), false, 16, verb) + case i32le: fmt_int(fi, u64(a), true, 32, verb) + case u32le: fmt_int(fi, u64(a), false, 32, verb) + case i64le: fmt_int(fi, u64(a), true, 64, verb) + case u64le: fmt_int(fi, u64(a), false, 64, verb) + + case i16be: fmt_int(fi, u64(a), true, 16, verb) + case u16be: fmt_int(fi, u64(a), false, 16, verb) + case i32be: fmt_int(fi, u64(a), true, 32, verb) + case u32be: fmt_int(fi, u64(a), false, 32, verb) + case i64be: fmt_int(fi, u64(a), true, 64, verb) + case u64be: fmt_int(fi, u64(a), false, 64, verb) + + case i128: fmt_int_128(fi, u128(a), true, 128, verb) + case u128: fmt_int_128(fi, a, false, 128, verb) + + case i128le: fmt_int_128(fi, u128(a), true, 128, verb) + case u128le: fmt_int_128(fi, u128(a), false, 128, verb) + + case i128be: fmt_int_128(fi, u128(a), true, 128, verb) + case u128be: fmt_int_128(fi, u128(a), false, 128, verb) + + case: fmt_value(fi, arg, verb) } } diff --git a/core/hash/crc.odin b/core/hash/crc.odin index 7523a176d..b0e4ef5ff 100644 --- a/core/hash/crc.odin +++ b/core/hash/crc.odin @@ -3,11 +3,11 @@ package hash @(optimization_mode="speed") crc64 :: proc(data: []byte, seed := u32(0)) -> u64 #no_bounds_check { - result := ~u64(seed); + result := ~u64(seed) #no_bounds_check for b in data { - result = result>>8 ~ _crc64_table[(result ~ u64(b)) & 0xff]; + result = result>>8 ~ _crc64_table[(result ~ u64(b)) & 0xff] } - return ~result; + return ~result } @private _crc64_table := [256]u64{ @@ -75,4 +75,4 @@ crc64 :: proc(data: []byte, seed := u32(0)) -> u64 #no_bounds_check { 0xcf8b0890283e370c, 0x8d7be97b81d4019f, 0x4a6acb477bea5a2a, 0x089a2aacd2006cb9, 0x14dea25f3af9026d, 0x562e43b4931334fe, 0x913f6188692d6f4b, 0xd3cf8063c0c759d8, 0x5dedc41a34bbeeb2, 0x1f1d25f19d51d821, 0xd80c07cd676f8394, 0x9afce626ce85b507, -}; +} diff --git a/core/hash/crc32.odin b/core/hash/crc32.odin index 41a04880f..ccb304472 100644 --- a/core/hash/crc32.odin +++ b/core/hash/crc32.odin @@ -4,20 +4,20 @@ import "core:intrinsics" @(optimization_mode="speed") crc32 :: proc(data: []byte, seed := u32(0)) -> u32 #no_bounds_check { - crc := ~seed; - buffer := raw_data(data); - length := len(data); + crc := ~seed + buffer := raw_data(data) + length := len(data) for length != 0 && uintptr(buffer) & 7 != 0 { - crc = crc32_table[0][byte(crc) ~ buffer^] ~ (crc >> 8); - buffer = intrinsics.ptr_offset(buffer, 1); - length -= 1; + crc = crc32_table[0][byte(crc) ~ buffer^] ~ (crc >> 8) + buffer = intrinsics.ptr_offset(buffer, 1) + length -= 1 } for length >= 8 { - buf := (^[8]byte)(buffer); - word := u32((^u32le)(buffer)^); - crc ~= word; + buf := (^[8]byte)(buffer) + word := u32((^u32le)(buffer)^) + crc ~= word crc = crc32_table[7][crc & 0xff] ~ crc32_table[6][(crc >> 8) & 0xff] ~ @@ -26,21 +26,21 @@ crc32 :: proc(data: []byte, seed := u32(0)) -> u32 #no_bounds_check { crc32_table[3][buf[4]] ~ crc32_table[2][buf[5]] ~ crc32_table[1][buf[6]] ~ - crc32_table[0][buf[7]]; + crc32_table[0][buf[7]] - buffer = intrinsics.ptr_offset(buffer, 8); - length -= 8; + buffer = intrinsics.ptr_offset(buffer, 8) + length -= 8 } for length != 0 { - crc = crc32_table[0][byte(crc) ~ buffer^] ~ (crc >> 8); - buffer = intrinsics.ptr_offset(buffer, 1); - length -= 1; + crc = crc32_table[0][byte(crc) ~ buffer^] ~ (crc >> 8) + buffer = intrinsics.ptr_offset(buffer, 1) + length -= 1 } - return ~crc; + return ~crc } @(private) @@ -317,7 +317,7 @@ crc32_table := [8][256]u32{ 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0, 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61, 0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678, 0x264b06e6, }, -}; +} diff --git a/core/hash/hash.odin b/core/hash/hash.odin index 91f0268d3..64c7ad5c4 100644 --- a/core/hash/hash.odin +++ b/core/hash/hash.odin @@ -6,266 +6,266 @@ import "core:intrinsics" @(optimization_mode="speed") adler32 :: proc(data: []byte, seed := u32(1)) -> u32 #no_bounds_check { - ADLER_CONST :: 65521; + ADLER_CONST :: 65521 - buffer := raw_data(data); - a, b: u64 = u64(seed) & 0xFFFF, u64(seed) >> 16; - buf := data[:]; + buffer := raw_data(data) + a, b: u64 = u64(seed) & 0xFFFF, u64(seed) >> 16 + buf := data[:] for len(buf) != 0 && uintptr(buffer) & 7 != 0 { - a = (a + u64(buf[0])); - b = (b + a); - buffer = intrinsics.ptr_offset(buffer, 1); - buf = buf[1:]; + a = (a + u64(buf[0])) + b = (b + a) + buffer = intrinsics.ptr_offset(buffer, 1) + buf = buf[1:] } for len(buf) > 7 { - count := min(len(buf), 5552); + count := min(len(buf), 5552) for count > 7 { - a += u64(buf[0]); b += a; - a += u64(buf[1]); b += a; - a += u64(buf[2]); b += a; - a += u64(buf[3]); b += a; - a += u64(buf[4]); b += a; - a += u64(buf[5]); b += a; - a += u64(buf[6]); b += a; - a += u64(buf[7]); b += a; - - buf = buf[8:]; - count -= 8; + a += u64(buf[0]); b += a + a += u64(buf[1]); b += a + a += u64(buf[2]); b += a + a += u64(buf[3]); b += a + a += u64(buf[4]); b += a + a += u64(buf[5]); b += a + a += u64(buf[6]); b += a + a += u64(buf[7]); b += a + + buf = buf[8:] + count -= 8 } - a %= ADLER_CONST; - b %= ADLER_CONST; + a %= ADLER_CONST + b %= ADLER_CONST } for len(buf) != 0 { - a = (a + u64(buf[0])) % ADLER_CONST; - b = (b + a) % ADLER_CONST; - buf = buf[1:]; + a = (a + u64(buf[0])) % ADLER_CONST + b = (b + a) % ADLER_CONST + buf = buf[1:] } - return (u32(b) << 16) | u32(a); + return (u32(b) << 16) | u32(a) } @(optimization_mode="speed") djb2 :: proc(data: []byte) -> u32 { - hash: u32 = 5381; + hash: u32 = 5381 for b in data { - hash = (hash << 5) + hash + u32(b); // hash * 33 + u32(b) + hash = (hash << 5) + hash + u32(b) // hash * 33 + u32(b) } - return hash; + return hash } @(optimization_mode="speed") fnv32 :: proc(data: []byte) -> u32 { - h: u32 = 0x811c9dc5; + h: u32 = 0x811c9dc5 for b in data { - h = (h * 0x01000193) ~ u32(b); + h = (h * 0x01000193) ~ u32(b) } - return h; + return h } @(optimization_mode="speed") fnv64 :: proc(data: []byte) -> u64 { - h: u64 = 0xcbf29ce484222325; + h: u64 = 0xcbf29ce484222325 for b in data { - h = (h * 0x100000001b3) ~ u64(b); + h = (h * 0x100000001b3) ~ u64(b) } - return h; + return h } @(optimization_mode="speed") fnv32a :: proc(data: []byte) -> u32 { - h: u32 = 0x811c9dc5; + h: u32 = 0x811c9dc5 for b in data { - h = (h ~ u32(b)) * 0x01000193; + h = (h ~ u32(b)) * 0x01000193 } - return h; + return h } @(optimization_mode="speed") fnv64a :: proc(data: []byte) -> u64 { - h: u64 = 0xcbf29ce484222325; + h: u64 = 0xcbf29ce484222325 for b in data { - h = (h ~ u64(b)) * 0x100000001b3; + h = (h ~ u64(b)) * 0x100000001b3 } - return h; + return h } @(optimization_mode="speed") jenkins :: proc(data: []byte) -> u32 { - hash: u32 = 0; + hash: u32 = 0 for b in data { - hash += u32(b); - hash += hash << 10; - hash ~= hash >> 6; + hash += u32(b) + hash += hash << 10 + hash ~= hash >> 6 } - hash += hash << 3; - hash ~= hash >> 11; - hash += hash << 15; - return hash; + hash += hash << 3 + hash ~= hash >> 11 + hash += hash << 15 + return hash } @(optimization_mode="speed") murmur32 :: proc(data: []byte) -> u32 { - c1_32: u32 : 0xcc9e2d51; - c2_32: u32 : 0x1b873593; + c1_32: u32 : 0xcc9e2d51 + c2_32: u32 : 0x1b873593 - h1: u32 = 0; - nblocks := len(data)/4; - p := raw_data(data); - p1 := mem.ptr_offset(p, 4*nblocks); + h1: u32 = 0 + nblocks := len(data)/4 + p := raw_data(data) + p1 := mem.ptr_offset(p, 4*nblocks) for ; p < p1; p = mem.ptr_offset(p, 4) { - k1 := (cast(^u32)p)^; + k1 := (cast(^u32)p)^ - k1 *= c1_32; - k1 = (k1 << 15) | (k1 >> 17); - k1 *= c2_32; + k1 *= c1_32 + k1 = (k1 << 15) | (k1 >> 17) + k1 *= c2_32 - h1 ~= k1; - h1 = (h1 << 13) | (h1 >> 19); - h1 = h1*5 + 0xe6546b64; + h1 ~= k1 + h1 = (h1 << 13) | (h1 >> 19) + h1 = h1*5 + 0xe6546b64 } - tail := data[nblocks*4:]; - k1: u32; + tail := data[nblocks*4:] + k1: u32 switch len(tail)&3 { case 3: - k1 ~= u32(tail[2]) << 16; - fallthrough; + k1 ~= u32(tail[2]) << 16 + fallthrough case 2: - k1 ~= u32(tail[2]) << 8; - fallthrough; + k1 ~= u32(tail[2]) << 8 + fallthrough case 1: - k1 ~= u32(tail[0]); - k1 *= c1_32; - k1 = (k1 << 15) | (k1 >> 17) ; - k1 *= c2_32; - h1 ~= k1; + k1 ~= u32(tail[0]) + k1 *= c1_32 + k1 = (k1 << 15) | (k1 >> 17) + k1 *= c2_32 + h1 ~= k1 } - h1 ~= u32(len(data)); + h1 ~= u32(len(data)) - h1 ~= h1 >> 16; - h1 *= 0x85ebca6b; - h1 ~= h1 >> 13; - h1 *= 0xc2b2ae35; - h1 ~= h1 >> 16; + h1 ~= h1 >> 16 + h1 *= 0x85ebca6b + h1 ~= h1 >> 13 + h1 *= 0xc2b2ae35 + h1 ~= h1 >> 16 - return h1; + return h1 } @(optimization_mode="speed") murmur64 :: proc(data: []byte) -> u64 { - SEED :: 0x9747b28c; + SEED :: 0x9747b28c when size_of(int) == 8 { - m :: 0xc6a4a7935bd1e995; - r :: 47; + m :: 0xc6a4a7935bd1e995 + r :: 47 - h: u64 = SEED ~ (u64(len(data)) * m); - data64 := mem.slice_ptr(cast(^u64)raw_data(data), len(data)/size_of(u64)); + h: u64 = SEED ~ (u64(len(data)) * m) + data64 := mem.slice_ptr(cast(^u64)raw_data(data), len(data)/size_of(u64)) for _, i in data64 { - k := data64[i]; + k := data64[i] - k *= m; - k ~= k>>r; - k *= m; + k *= m + k ~= k>>r + k *= m - h ~= k; - h *= m; + h ~= k + h *= m } switch len(data)&7 { - case 7: h ~= u64(data[6]) << 48; fallthrough; - case 6: h ~= u64(data[5]) << 40; fallthrough; - case 5: h ~= u64(data[4]) << 32; fallthrough; - case 4: h ~= u64(data[3]) << 24; fallthrough; - case 3: h ~= u64(data[2]) << 16; fallthrough; - case 2: h ~= u64(data[1]) << 8; fallthrough; + case 7: h ~= u64(data[6]) << 48; fallthrough + case 6: h ~= u64(data[5]) << 40; fallthrough + case 5: h ~= u64(data[4]) << 32; fallthrough + case 4: h ~= u64(data[3]) << 24; fallthrough + case 3: h ~= u64(data[2]) << 16; fallthrough + case 2: h ~= u64(data[1]) << 8; fallthrough case 1: - h ~= u64(data[0]); - h *= m; + h ~= u64(data[0]) + h *= m } - h ~= h>>r; - h *= m; - h ~= h>>r; + h ~= h>>r + h *= m + h ~= h>>r - return h; + return h } else { - m :: 0x5bd1e995; - r :: 24; + m :: 0x5bd1e995 + r :: 24 - h1 := u32(SEED) ~ u32(len(data)); - h2 := u32(SEED) >> 32; - data32 := mem.slice_ptr(cast(^u32)raw_data(data), len(data)/size_of(u32)); - len := len(data); - i := 0; + h1 := u32(SEED) ~ u32(len(data)) + h2 := u32(SEED) >> 32 + data32 := mem.slice_ptr(cast(^u32)raw_data(data), len(data)/size_of(u32)) + len := len(data) + i := 0 for len >= 8 { - k1, k2: u32; - k1 = data32[i]; i += 1; - k1 *= m; - k1 ~= k1>>r; - k1 *= m; - h1 *= m; - h1 ~= k1; - len -= 4; - - k2 = data32[i]; i += 1; - k2 *= m; - k2 ~= k2>>r; - k2 *= m; - h2 *= m; - h2 ~= k2; - len -= 4; + k1, k2: u32 + k1 = data32[i]; i += 1 + k1 *= m + k1 ~= k1>>r + k1 *= m + h1 *= m + h1 ~= k1 + len -= 4 + + k2 = data32[i]; i += 1 + k2 *= m + k2 ~= k2>>r + k2 *= m + h2 *= m + h2 ~= k2 + len -= 4 } if len >= 4 { - k1: u32; - k1 = data32[i]; i += 1; - k1 *= m; - k1 ~= k1>>r; - k1 *= m; - h1 *= m; - h1 ~= k1; - len -= 4; + k1: u32 + k1 = data32[i]; i += 1 + k1 *= m + k1 ~= k1>>r + k1 *= m + h1 *= m + h1 ~= k1 + len -= 4 } // TODO(bill): Fix this - #no_bounds_check data8 := mem.slice_to_bytes(data32[i:])[:3]; + #no_bounds_check data8 := mem.slice_to_bytes(data32[i:])[:3] switch len { case 3: - h2 ~= u32(data8[2]) << 16; - fallthrough; + h2 ~= u32(data8[2]) << 16 + fallthrough case 2: - h2 ~= u32(data8[1]) << 8; - fallthrough; + h2 ~= u32(data8[1]) << 8 + fallthrough case 1: - h2 ~= u32(data8[0]); - h2 *= m; + h2 ~= u32(data8[0]) + h2 *= m } - h1 ~= h2>>18; - h1 *= m; - h2 ~= h1>>22; - h2 *= m; - h1 ~= h2>>17; - h1 *= m; - h2 ~= h1>>19; - h2 *= m; + h1 ~= h2>>18 + h1 *= m + h2 ~= h1>>22 + h2 *= m + h1 ~= h2>>17 + h1 *= m + h2 ~= h1>>19 + h2 *= m - return u64(h1)<<32 | u64(h2); + return u64(h1)<<32 | u64(h2) } } @(optimization_mode="speed") sdbm :: proc(data: []byte) -> u32 { - hash: u32 = 0; + hash: u32 = 0 for b in data { - hash = u32(b) + (hash<<6) + (hash<<16) - hash; + hash = u32(b) + (hash<<6) + (hash<<16) - hash } - return hash; + return hash } diff --git a/core/hash/mini.odin b/core/hash/mini.odin index 024e88abc..98b1b4ba3 100644 --- a/core/hash/mini.odin +++ b/core/hash/mini.odin @@ -1,40 +1,40 @@ package hash ginger_hash8 :: proc(x: u8) -> u8 { - h := x * 251; - h += ~(x << 3); - h ~= (x >> 1); - h += ~(x << 7); - h ~= (x >> 6); - h += (x << 2); - return h; + h := x * 251 + h += ~(x << 3) + h ~= (x >> 1) + h += ~(x << 7) + h ~= (x >> 6) + h += (x << 2) + return h } ginger_hash16 :: proc(x: u16) -> u16 { - z := (x << 8) | (x >> 8); - h := z; - h += ~(z << 5); - h ~= (z >> 2); - h += ~(z << 13); - h ~= (z >> 10); - h += ~(z << 4); - h = (h << 10) | (h >> 10); - return h; + z := (x << 8) | (x >> 8) + h := z + h += ~(z << 5) + h ~= (z >> 2) + h += ~(z << 13) + h ~= (z >> 10) + h += ~(z << 4) + h = (h << 10) | (h >> 10) + return h } ginger8 :: proc(data: []byte) -> u8 { - h := ginger_hash8(0); + h := ginger_hash8(0) for b in data { - h ~= ginger_hash8(b); + h ~= ginger_hash8(b) } - return h; + return h } ginger16 :: proc(data: []byte) -> u16 { - h := ginger_hash16(0); + h := ginger_hash16(0) for b in data { - h ~= ginger_hash16(u16(b)); + h ~= ginger_hash16(u16(b)) } - return h; + return h } diff --git a/core/image/common.odin b/core/image/common.odin index 7a678f5b0..f30febc26 100644 --- a/core/image/common.odin +++ b/core/image/common.odin @@ -110,7 +110,7 @@ Option :: enum { do_not_expand_indexed, do_not_expand_channels, } -Options :: distinct bit_set[Option]; +Options :: distinct bit_set[Option] Error :: enum { Invalid_PNG_Signature, @@ -138,8 +138,8 @@ Error :: enum { */ compute_buffer_size :: proc(width, height, channels, depth: int, extra_row_bytes := int(0)) -> (size: int) { - size = ((((channels * width * depth) + 7) >> 3) + extra_row_bytes) * height; - return; + size = ((((channels * width * depth) + 7) >> 3) + extra_row_bytes) * height + return } /* @@ -154,61 +154,61 @@ Channel :: enum u8 { } return_single_channel :: proc(img: ^Image, channel: Channel) -> (res: ^Image, ok: bool) { - ok = false; - t: bytes.Buffer; + ok = false + t: bytes.Buffer - idx := int(channel); + idx := int(channel) if img.channels == 2 && idx == 4 { // Alpha requested, which in a two channel image is index 2: G. - idx = 2; + idx = 2 } if idx > img.channels { - return {}, false; + return {}, false } switch img.depth { case 8: - buffer_size := compute_buffer_size(img.width, img.height, 1, 8); - t = bytes.Buffer{}; - resize(&t.buf, buffer_size); + buffer_size := compute_buffer_size(img.width, img.height, 1, 8) + t = bytes.Buffer{} + resize(&t.buf, buffer_size) - i := bytes.buffer_to_bytes(&img.pixels); - o := bytes.buffer_to_bytes(&t); + i := bytes.buffer_to_bytes(&img.pixels) + o := bytes.buffer_to_bytes(&t) for len(i) > 0 { - o[0] = i[idx]; - i = i[img.channels:]; - o = o[1:]; + o[0] = i[idx] + i = i[img.channels:] + o = o[1:] } case 16: - buffer_size := compute_buffer_size(img.width, img.height, 2, 8); - t = bytes.Buffer{}; - resize(&t.buf, buffer_size); + buffer_size := compute_buffer_size(img.width, img.height, 2, 8) + t = bytes.Buffer{} + resize(&t.buf, buffer_size) - i := mem.slice_data_cast([]u16, img.pixels.buf[:]); - o := mem.slice_data_cast([]u16, t.buf[:]); + i := mem.slice_data_cast([]u16, img.pixels.buf[:]) + o := mem.slice_data_cast([]u16, t.buf[:]) for len(i) > 0 { - o[0] = i[idx]; - i = i[img.channels:]; - o = o[1:]; + o[0] = i[idx] + i = i[img.channels:] + o = o[1:] } case 1, 2, 4: // We shouldn't see this case, as the loader already turns these into 8-bit. - return {}, false; + return {}, false } - res = new(Image); - res.width = img.width; - res.height = img.height; - res.channels = 1; - res.depth = img.depth; - res.pixels = t; - res.background = img.background; - res.metadata_ptr = img.metadata_ptr; - res.metadata_type = img.metadata_type; - - return res, true; + res = new(Image) + res.width = img.width + res.height = img.height + res.channels = 1 + res.depth = img.depth + res.pixels = t + res.background = img.background + res.metadata_ptr = img.metadata_ptr + res.metadata_type = img.metadata_type + + return res, true } diff --git a/core/image/png/example.odin b/core/image/png/example.odin index b84876ac8..e27ea9671 100644 --- a/core/image/png/example.odin +++ b/core/image/png/example.odin @@ -23,125 +23,125 @@ import "core:mem" import "core:os" main :: proc() { - track := mem.Tracking_Allocator{}; - mem.tracking_allocator_init(&track, context.allocator); + track := mem.Tracking_Allocator{} + mem.tracking_allocator_init(&track, context.allocator) - context.allocator = mem.tracking_allocator(&track); + context.allocator = mem.tracking_allocator(&track) - demo(); + demo() if len(track.allocation_map) > 0 { - fmt.println("Leaks:"); + fmt.println("Leaks:") for _, v in track.allocation_map { - fmt.printf("\t%v\n\n", v); + fmt.printf("\t%v\n\n", v) } } } demo :: proc() { - file: string; + file: string - options := image.Options{}; // {.return_metadata}; - err: compress.Error; - img: ^image.Image; + options := image.Options{} // {.return_metadata}; + err: compress.Error + img: ^image.Image - file = "../../../misc/logo-slim.png"; + file = "../../../misc/logo-slim.png" - img, err = load(file, options); - defer destroy(img); + img, err = load(file, options) + defer destroy(img) if err != nil { - fmt.printf("Trying to read PNG file %v returned %v\n", file, err); + fmt.printf("Trying to read PNG file %v returned %v\n", file, err) } else { - v: ^Info; + v: ^Info - fmt.printf("Image: %vx%vx%v, %v-bit.\n", img.width, img.height, img.channels, img.depth); + fmt.printf("Image: %vx%vx%v, %v-bit.\n", img.width, img.height, img.channels, img.depth) if img.metadata_ptr != nil && img.metadata_type == Info { - v = (^Info)(img.metadata_ptr); + v = (^Info)(img.metadata_ptr) // Handle ancillary chunks as you wish. // We provide helper functions for a few types. for c in v.chunks { #partial switch c.header.type { case .tIME: - t, _ := core_time(c); - fmt.printf("[tIME]: %v\n", t); + t, _ := core_time(c) + fmt.printf("[tIME]: %v\n", t) case .gAMA: - fmt.printf("[gAMA]: %v\n", gamma(c)); + fmt.printf("[gAMA]: %v\n", gamma(c)) case .pHYs: - phys := phys(c); + phys := phys(c) if phys.unit == .Meter { - xm := f32(img.width) / f32(phys.ppu_x); - ym := f32(img.height) / f32(phys.ppu_y); - dpi_x, dpi_y := phys_to_dpi(phys); - fmt.printf("[pHYs] Image resolution is %v x %v pixels per meter.\n", phys.ppu_x, phys.ppu_y); - fmt.printf("[pHYs] Image resolution is %v x %v DPI.\n", dpi_x, dpi_y); - fmt.printf("[pHYs] Image dimensions are %v x %v meters.\n", xm, ym); + xm := f32(img.width) / f32(phys.ppu_x) + ym := f32(img.height) / f32(phys.ppu_y) + dpi_x, dpi_y := phys_to_dpi(phys) + fmt.printf("[pHYs] Image resolution is %v x %v pixels per meter.\n", phys.ppu_x, phys.ppu_y) + fmt.printf("[pHYs] Image resolution is %v x %v DPI.\n", dpi_x, dpi_y) + fmt.printf("[pHYs] Image dimensions are %v x %v meters.\n", xm, ym) } else { - fmt.printf("[pHYs] x: %v, y: %v pixels per unknown unit.\n", phys.ppu_x, phys.ppu_y); + fmt.printf("[pHYs] x: %v, y: %v pixels per unknown unit.\n", phys.ppu_x, phys.ppu_y) } case .iTXt, .zTXt, .tEXt: - res, ok_text := text(c); + res, ok_text := text(c) if ok_text { if c.header.type == .iTXt { - fmt.printf("[iTXt] %v (%v:%v): %v\n", res.keyword, res.language, res.keyword_localized, res.text); + fmt.printf("[iTXt] %v (%v:%v): %v\n", res.keyword, res.language, res.keyword_localized, res.text) } else { - fmt.printf("[tEXt/zTXt] %v: %v\n", res.keyword, res.text); + fmt.printf("[tEXt/zTXt] %v: %v\n", res.keyword, res.text) } } - defer text_destroy(res); + defer text_destroy(res) case .bKGD: - fmt.printf("[bKGD] %v\n", img.background); + fmt.printf("[bKGD] %v\n", img.background) case .eXIf: - res, ok_exif := exif(c); + res, ok_exif := exif(c) if ok_exif { /* Other than checking the signature and byte order, we don't handle Exif data. If you wish to interpret it, pass it to an Exif parser. */ - fmt.printf("[eXIf] %v\n", res); + fmt.printf("[eXIf] %v\n", res) } case .PLTE: - plte, plte_ok := plte(c); + plte, plte_ok := plte(c) if plte_ok { - fmt.printf("[PLTE] %v\n", plte); + fmt.printf("[PLTE] %v\n", plte) } else { - fmt.printf("[PLTE] Error\n"); + fmt.printf("[PLTE] Error\n") } case .hIST: - res, ok_hist := hist(c); + res, ok_hist := hist(c) if ok_hist { - fmt.printf("[hIST] %v\n", res); + fmt.printf("[hIST] %v\n", res) } case .cHRM: - res, ok_chrm := chrm(c); + res, ok_chrm := chrm(c) if ok_chrm { - fmt.printf("[cHRM] %v\n", res); + fmt.printf("[cHRM] %v\n", res) } case .sPLT: - res, ok_splt := splt(c); + res, ok_splt := splt(c) if ok_splt { - fmt.printf("[sPLT] %v\n", res); + fmt.printf("[sPLT] %v\n", res) } - splt_destroy(res); + splt_destroy(res) case .sBIT: if res, ok_sbit := sbit(c); ok_sbit { - fmt.printf("[sBIT] %v\n", res); + fmt.printf("[sBIT] %v\n", res) } case .iCCP: - res, ok_iccp := iccp(c); + res, ok_iccp := iccp(c) if ok_iccp { - fmt.printf("[iCCP] %v\n", res); + fmt.printf("[iCCP] %v\n", res) } - iccp_destroy(res); + iccp_destroy(res) case .sRGB: if res, ok_srgb := srgb(c); ok_srgb { - fmt.printf("[sRGB] Rendering intent: %v\n", res); + fmt.printf("[sRGB] Rendering intent: %v\n", res) } case: - type := c.header.type; - name := chunk_type_to_name(&type); - fmt.printf("[%v]: %v\n", name, c.data); + type := c.header.type + name := chunk_type_to_name(&type) + fmt.printf("[%v]: %v\n", name, c.data) } } } @@ -149,10 +149,10 @@ demo :: proc() { if err == nil && .do_not_decompress_image not_in options && .info not_in options { if ok := write_image_as_ppm("out.ppm", img); ok { - fmt.println("Saved decoded image."); + fmt.println("Saved decoded image.") } else { - fmt.println("Error saving out.ppm."); - fmt.println(img); + fmt.println("Error saving out.ppm.") + fmt.println(img) } } } @@ -162,193 +162,193 @@ write_image_as_ppm :: proc(filename: string, image: ^image.Image) -> (success: b _bg :: proc(bg: Maybe([3]u16), x, y: int, high := true) -> (res: [3]u16) { if v, ok := bg.?; ok { - res = v; + res = v } else { if high { - l := u16(30 * 256 + 30); + l := u16(30 * 256 + 30) if (x & 4 == 0) ~ (y & 4 == 0) { - res = [3]u16{l, 0, l}; + res = [3]u16{l, 0, l} } else { - res = [3]u16{l >> 1, 0, l >> 1}; + res = [3]u16{l >> 1, 0, l >> 1} } } else { if (x & 4 == 0) ~ (y & 4 == 0) { - res = [3]u16{30, 30, 30}; + res = [3]u16{30, 30, 30} } else { - res = [3]u16{15, 15, 15}; + res = [3]u16{15, 15, 15} } } } - return; + return } // profiler.timed_proc(); - using image; - using os; + using image + using os - flags: int = O_WRONLY|O_CREATE|O_TRUNC; + flags: int = O_WRONLY|O_CREATE|O_TRUNC - img := image; + img := image // PBM 16-bit images are big endian when ODIN_ENDIAN == "little" { if img.depth == 16 { // The pixel components are in Big Endian. Let's byteswap back. - input := mem.slice_data_cast([]u16, img.pixels.buf[:]); - output := mem.slice_data_cast([]u16be, img.pixels.buf[:]); + input := mem.slice_data_cast([]u16, img.pixels.buf[:]) + output := mem.slice_data_cast([]u16be, img.pixels.buf[:]) #no_bounds_check for v, i in input { - output[i] = u16be(v); + output[i] = u16be(v) } } } - pix := bytes.buffer_to_bytes(&img.pixels); + pix := bytes.buffer_to_bytes(&img.pixels) if len(pix) == 0 || len(pix) < image.width * image.height * int(image.channels) { - return false; + return false } - mode: int = 0; + mode: int = 0 when ODIN_OS == "linux" || ODIN_OS == "darwin" { // NOTE(justasd): 644 (owner read, write; group read; others read) - mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; + mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH } - fd, err := open(filename, flags, mode); + fd, err := open(filename, flags, mode) if err != 0 { - return false; + return false } - defer close(fd); + defer close(fd) write_string(fd, fmt.tprintf("P6\n%v %v\n%v\n", width, height, (1 << uint(depth) - 1)), - ); + ) if channels == 3 { // We don't handle transparency here... - write_ptr(fd, raw_data(pix), len(pix)); + write_ptr(fd, raw_data(pix), len(pix)) } else { - bpp := depth == 16 ? 2 : 1; - bytes_needed := width * height * 3 * bpp; + bpp := depth == 16 ? 2 : 1 + bytes_needed := width * height * 3 * bpp - op := bytes.Buffer{}; - bytes.buffer_init_allocator(&op, bytes_needed, bytes_needed); - defer bytes.buffer_destroy(&op); + op := bytes.Buffer{} + bytes.buffer_init_allocator(&op, bytes_needed, bytes_needed) + defer bytes.buffer_destroy(&op) if channels == 1 { if depth == 16 { - assert(len(pix) == width * height * 2); - p16 := mem.slice_data_cast([]u16, pix); - o16 := mem.slice_data_cast([]u16, op.buf[:]); + assert(len(pix) == width * height * 2) + p16 := mem.slice_data_cast([]u16, pix) + o16 := mem.slice_data_cast([]u16, op.buf[:]) #no_bounds_check for len(p16) != 0 { - r := u16(p16[0]); - o16[0] = r; - o16[1] = r; - o16[2] = r; - p16 = p16[1:]; - o16 = o16[3:]; + r := u16(p16[0]) + o16[0] = r + o16[1] = r + o16[2] = r + p16 = p16[1:] + o16 = o16[3:] } } else { - o := 0; + o := 0 for i := 0; i < len(pix); i += 1 { - r := pix[i]; - op.buf[o ] = r; - op.buf[o+1] = r; - op.buf[o+2] = r; - o += 3; + r := pix[i] + op.buf[o ] = r + op.buf[o+1] = r + op.buf[o+2] = r + o += 3 } } - write_ptr(fd, raw_data(op.buf), len(op.buf)); + write_ptr(fd, raw_data(op.buf), len(op.buf)) } else if channels == 2 { if depth == 16 { - p16 := mem.slice_data_cast([]u16, pix); - o16 := mem.slice_data_cast([]u16, op.buf[:]); + p16 := mem.slice_data_cast([]u16, pix) + o16 := mem.slice_data_cast([]u16, op.buf[:]) - bgcol := img.background; + bgcol := img.background #no_bounds_check for len(p16) != 0 { - r := f64(u16(p16[0])); - bg: f64; + r := f64(u16(p16[0])) + bg: f64 if bgcol != nil { - v := bgcol.([3]u16)[0]; - bg = f64(v); + v := bgcol.([3]u16)[0] + bg = f64(v) } - a := f64(u16(p16[1])) / 65535.0; - l := (a * r) + (1 - a) * bg; + a := f64(u16(p16[1])) / 65535.0 + l := (a * r) + (1 - a) * bg - o16[0] = u16(l); - o16[1] = u16(l); - o16[2] = u16(l); + o16[0] = u16(l) + o16[1] = u16(l) + o16[2] = u16(l) - p16 = p16[2:]; - o16 = o16[3:]; + p16 = p16[2:] + o16 = o16[3:] } } else { - o := 0; + o := 0 for i := 0; i < len(pix); i += 2 { - r := pix[i]; a := pix[i+1]; a1 := f32(a) / 255.0; - c := u8(f32(r) * a1); - op.buf[o ] = c; - op.buf[o+1] = c; - op.buf[o+2] = c; - o += 3; + r := pix[i]; a := pix[i+1]; a1 := f32(a) / 255.0 + c := u8(f32(r) * a1) + op.buf[o ] = c + op.buf[o+1] = c + op.buf[o+2] = c + o += 3 } } - write_ptr(fd, raw_data(op.buf), len(op.buf)); + write_ptr(fd, raw_data(op.buf), len(op.buf)) } else if channels == 4 { if depth == 16 { - p16 := mem.slice_data_cast([]u16be, pix); - o16 := mem.slice_data_cast([]u16be, op.buf[:]); + p16 := mem.slice_data_cast([]u16be, pix) + o16 := mem.slice_data_cast([]u16be, op.buf[:]) #no_bounds_check for len(p16) != 0 { - bg := _bg(img.background, 0, 0); - r := f32(p16[0]); - g := f32(p16[1]); - b := f32(p16[2]); - a := f32(p16[3]) / 65535.0; + bg := _bg(img.background, 0, 0) + r := f32(p16[0]) + g := f32(p16[1]) + b := f32(p16[2]) + a := f32(p16[3]) / 65535.0 - lr := (a * r) + (1 - a) * f32(bg[0]); - lg := (a * g) + (1 - a) * f32(bg[1]); - lb := (a * b) + (1 - a) * f32(bg[2]); + lr := (a * r) + (1 - a) * f32(bg[0]) + lg := (a * g) + (1 - a) * f32(bg[1]) + lb := (a * b) + (1 - a) * f32(bg[2]) - o16[0] = u16be(lr); - o16[1] = u16be(lg); - o16[2] = u16be(lb); + o16[0] = u16be(lr) + o16[1] = u16be(lg) + o16[2] = u16be(lb) - p16 = p16[4:]; - o16 = o16[3:]; + p16 = p16[4:] + o16 = o16[3:] } } else { - o := 0; + o := 0 for i := 0; i < len(pix); i += 4 { - x := (i / 4) % width; - y := i / width / 4; + x := (i / 4) % width + y := i / width / 4 - _b := _bg(img.background, x, y, false); - bgcol := [3]u8{u8(_b[0]), u8(_b[1]), u8(_b[2])}; + _b := _bg(img.background, x, y, false) + bgcol := [3]u8{u8(_b[0]), u8(_b[1]), u8(_b[2])} - r := f32(pix[i]); - g := f32(pix[i+1]); - b := f32(pix[i+2]); - a := f32(pix[i+3]) / 255.0; + r := f32(pix[i]) + g := f32(pix[i+1]) + b := f32(pix[i+2]) + a := f32(pix[i+3]) / 255.0 - lr := u8(f32(r) * a + (1 - a) * f32(bgcol[0])); - lg := u8(f32(g) * a + (1 - a) * f32(bgcol[1])); - lb := u8(f32(b) * a + (1 - a) * f32(bgcol[2])); - op.buf[o ] = lr; - op.buf[o+1] = lg; - op.buf[o+2] = lb; - o += 3; + lr := u8(f32(r) * a + (1 - a) * f32(bgcol[0])) + lg := u8(f32(g) * a + (1 - a) * f32(bgcol[1])) + lb := u8(f32(b) * a + (1 - a) * f32(bgcol[2])) + op.buf[o ] = lr + op.buf[o+1] = lg + op.buf[o+2] = lb + o += 3 } } - write_ptr(fd, raw_data(op.buf), len(op.buf)); + write_ptr(fd, raw_data(op.buf), len(op.buf)) } else { - return false; + return false } } - return true; + return true } diff --git a/core/image/png/helpers.odin b/core/image/png/helpers.odin index 4de6da947..4d8cebedf 100644 --- a/core/image/png/helpers.odin +++ b/core/image/png/helpers.odin @@ -30,12 +30,12 @@ destroy :: proc(img: ^Image) { Nothing to do. Load must've returned with an error. */ - return; + return } - bytes.buffer_destroy(&img.pixels); + bytes.buffer_destroy(&img.pixels) // Clean up Info. - free(img.metadata_ptr); + free(img.metadata_ptr) /* We don't need to do anything for the individual chunks. @@ -43,7 +43,7 @@ destroy :: proc(img: ^Image) { See read_chunk. */ - free(img); + free(img) } /* @@ -51,259 +51,259 @@ destroy :: proc(img: ^Image) { */ gamma :: proc(c: Chunk) -> f32 { - assert(c.header.type == .gAMA); - res := (^gAMA)(raw_data(c.data))^; + assert(c.header.type == .gAMA) + res := (^gAMA)(raw_data(c.data))^ when true { // Returns the wrong result on old backend // Fixed for -llvm-api - return f32(res.gamma_100k) / 100_000.0; + return f32(res.gamma_100k) / 100_000.0 } else { - return f32(u32(res.gamma_100k)) / 100_000.0; + return f32(u32(res.gamma_100k)) / 100_000.0 } } -INCHES_PER_METER :: 1000.0 / 25.4; +INCHES_PER_METER :: 1000.0 / 25.4 phys :: proc(c: Chunk) -> pHYs { - assert(c.header.type == .pHYs); - res := (^pHYs)(raw_data(c.data))^; - return res; + assert(c.header.type == .pHYs) + res := (^pHYs)(raw_data(c.data))^ + return res } phys_to_dpi :: proc(p: pHYs) -> (x_dpi, y_dpi: f32) { - return f32(p.ppu_x) / INCHES_PER_METER, f32(p.ppu_y) / INCHES_PER_METER; + return f32(p.ppu_x) / INCHES_PER_METER, f32(p.ppu_y) / INCHES_PER_METER } time :: proc(c: Chunk) -> tIME { - assert(c.header.type == .tIME); - res := (^tIME)(raw_data(c.data))^; - return res; + assert(c.header.type == .tIME) + res := (^tIME)(raw_data(c.data))^ + return res } core_time :: proc(c: Chunk) -> (t: coretime.Time, ok: bool) { - png_time := time(c); - using png_time; + png_time := time(c) + using png_time return coretime.datetime_to_time( int(year), int(month), int(day), int(hour), int(minute), int(second), - ); + ) } text :: proc(c: Chunk) -> (res: Text, ok: bool) { #partial switch c.header.type { case .tEXt: - ok = true; + ok = true - fields := bytes.split(s=c.data, sep=[]u8{0}, allocator=context.temp_allocator); + fields := bytes.split(s=c.data, sep=[]u8{0}, allocator=context.temp_allocator) if len(fields) == 2 { - res.keyword = strings.clone(string(fields[0])); - res.text = strings.clone(string(fields[1])); + res.keyword = strings.clone(string(fields[0])) + res.text = strings.clone(string(fields[1])) } else { - ok = false; + ok = false } - return; + return case .zTXt: - ok = true; + ok = true - fields := bytes.split_n(s=c.data, sep=[]u8{0}, n=3, allocator=context.temp_allocator); + fields := bytes.split_n(s=c.data, sep=[]u8{0}, n=3, allocator=context.temp_allocator) if len(fields) != 3 || len(fields[1]) != 0 { // Compression method must be 0=Deflate, which thanks to the split above turns // into an empty slice - ok = false; return; + ok = false; return } // Set up ZLIB context and decompress text payload. - buf: bytes.Buffer; - zlib_error := zlib.inflate_from_byte_array(fields[2], &buf); - defer bytes.buffer_destroy(&buf); + buf: bytes.Buffer + zlib_error := zlib.inflate_from_byte_array(fields[2], &buf) + defer bytes.buffer_destroy(&buf) if zlib_error != nil { - ok = false; return; + ok = false; return } - res.keyword = strings.clone(string(fields[0])); - res.text = strings.clone(bytes.buffer_to_string(&buf)); - return; + res.keyword = strings.clone(string(fields[0])) + res.text = strings.clone(bytes.buffer_to_string(&buf)) + return case .iTXt: - ok = true; + ok = true - s := string(c.data); - null := strings.index_byte(s, 0); + s := string(c.data) + null := strings.index_byte(s, 0) if null == -1 { - ok = false; return; + ok = false; return } if len(c.data) < null + 4 { // At a minimum, including the \0 following the keyword, we require 5 more bytes. - ok = false; return; + ok = false; return } - res.keyword = strings.clone(string(c.data[:null])); - rest := c.data[null+1:]; + res.keyword = strings.clone(string(c.data[:null])) + rest := c.data[null+1:] - compression_flag := rest[:1][0]; + compression_flag := rest[:1][0] if compression_flag > 1 { - ok = false; return; + ok = false; return } - compression_method := rest[1:2][0]; + compression_method := rest[1:2][0] if compression_flag == 1 && compression_method > 0 { // Only Deflate is supported - ok = false; return; + ok = false; return } - rest = rest[2:]; + rest = rest[2:] // We now expect an optional language keyword and translated keyword, both followed by a \0 - null = strings.index_byte(string(rest), 0); + null = strings.index_byte(string(rest), 0) if null == -1 { - ok = false; return; + ok = false; return } - res.language = strings.clone(string(rest[:null])); - rest = rest[null+1:]; + res.language = strings.clone(string(rest[:null])) + rest = rest[null+1:] - null = strings.index_byte(string(rest), 0); + null = strings.index_byte(string(rest), 0) if null == -1 { - ok = false; return; + ok = false; return } - res.keyword_localized = strings.clone(string(rest[:null])); - rest = rest[null+1:]; + res.keyword_localized = strings.clone(string(rest[:null])) + rest = rest[null+1:] if compression_flag == 0 { - res.text = strings.clone(string(rest)); + res.text = strings.clone(string(rest)) } else { // Set up ZLIB context and decompress text payload. - buf: bytes.Buffer; - zlib_error := zlib.inflate_from_byte_array(rest, &buf); - defer bytes.buffer_destroy(&buf); + buf: bytes.Buffer + zlib_error := zlib.inflate_from_byte_array(rest, &buf) + defer bytes.buffer_destroy(&buf) if zlib_error != nil { - ok = false; return; + ok = false; return } - res.text = strings.clone(bytes.buffer_to_string(&buf)); + res.text = strings.clone(bytes.buffer_to_string(&buf)) } - return; + return case: // PNG text helper called with an unrecognized chunk type. - ok = false; return; + ok = false; return } } text_destroy :: proc(text: Text) { - delete(text.keyword); - delete(text.keyword_localized); - delete(text.language); - delete(text.text); + delete(text.keyword) + delete(text.keyword_localized) + delete(text.language) + delete(text.text) } iccp :: proc(c: Chunk) -> (res: iCCP, ok: bool) { - ok = true; + ok = true - fields := bytes.split_n(s=c.data, sep=[]u8{0}, n=3, allocator=context.temp_allocator); + fields := bytes.split_n(s=c.data, sep=[]u8{0}, n=3, allocator=context.temp_allocator) if len(fields[0]) < 1 || len(fields[0]) > 79 { // Invalid profile name - ok = false; return; + ok = false; return } if len(fields[1]) != 0 { // Compression method should be a zero, which the split turned into an empty slice. - ok = false; return; + ok = false; return } // Set up ZLIB context and decompress iCCP payload - buf: bytes.Buffer; - zlib_error := zlib.inflate_from_byte_array(fields[2], &buf); + buf: bytes.Buffer + zlib_error := zlib.inflate_from_byte_array(fields[2], &buf) if zlib_error != nil { - bytes.buffer_destroy(&buf); - ok = false; return; + bytes.buffer_destroy(&buf) + ok = false; return } - res.name = strings.clone(string(fields[0])); - res.profile = bytes.buffer_to_bytes(&buf); + res.name = strings.clone(string(fields[0])) + res.profile = bytes.buffer_to_bytes(&buf) - return; + return } iccp_destroy :: proc(i: iCCP) { - delete(i.name); + delete(i.name) - delete(i.profile); + delete(i.profile) } srgb :: proc(c: Chunk) -> (res: sRGB, ok: bool) { - ok = true; + ok = true if c.header.type != .sRGB || len(c.data) != 1 { - return {}, false; + return {}, false } - res.intent = sRGB_Rendering_Intent(c.data[0]); + res.intent = sRGB_Rendering_Intent(c.data[0]) if res.intent > max(sRGB_Rendering_Intent) { - ok = false; return; + ok = false; return } - return; + return } plte :: proc(c: Chunk) -> (res: PLTE, ok: bool) { if c.header.type != .PLTE { - return {}, false; + return {}, false } - i := 0; j := 0; ok = true; + i := 0; j := 0; ok = true for j < int(c.header.length) { - res.entries[i] = {c.data[j], c.data[j+1], c.data[j+2]}; - i += 1; j += 3; + res.entries[i] = {c.data[j], c.data[j+1], c.data[j+2]} + i += 1; j += 3 } - res.used = u16(i); - return; + res.used = u16(i) + return } splt :: proc(c: Chunk) -> (res: sPLT, ok: bool) { if c.header.type != .sPLT { - return {}, false; + return {}, false } - ok = true; + ok = true - fields := bytes.split_n(s=c.data, sep=[]u8{0}, n=2, allocator=context.temp_allocator); + fields := bytes.split_n(s=c.data, sep=[]u8{0}, n=2, allocator=context.temp_allocator) if len(fields) != 2 { - return {}, false; + return {}, false } - res.depth = fields[1][0]; + res.depth = fields[1][0] if res.depth != 8 && res.depth != 16 { - return {}, false; + return {}, false } - data := fields[1][1:]; - count: int; + data := fields[1][1:] + count: int if res.depth == 8 { if len(data) % 6 != 0 { - return {}, false; + return {}, false } - count = len(data) / 6; + count = len(data) / 6 if count > 256 { - return {}, false; + return {}, false } - res.entries = mem.slice_data_cast([][4]u8, data); + res.entries = mem.slice_data_cast([][4]u8, data) } else { // res.depth == 16 if len(data) % 10 != 0 { - return {}, false; + return {}, false } - count = len(data) / 10; + count = len(data) / 10 if count > 256 { - return {}, false; + return {}, false } - res.entries = mem.slice_data_cast([][4]u16, data); + res.entries = mem.slice_data_cast([][4]u16, data) } - res.name = strings.clone(string(fields[0])); - res.used = u16(count); + res.name = strings.clone(string(fields[0])) + res.used = u16(count) - return; + return } splt_destroy :: proc(s: sPLT) { - delete(s.name); + delete(s.name) } sbit :: proc(c: Chunk) -> (res: [4]u8, ok: bool) { @@ -313,88 +313,88 @@ sbit :: proc(c: Chunk) -> (res: [4]u8, ok: bool) { */ if len(c.data) < 1 || len(c.data) > 4 { - ok = false; return; + ok = false; return } - ok = true; + ok = true for i := 0; i < len(c.data); i += 1 { - res[i] = c.data[i]; + res[i] = c.data[i] } - return; + return } hist :: proc(c: Chunk) -> (res: hIST, ok: bool) { if c.header.type != .hIST { - return {}, false; + return {}, false } if c.header.length & 1 == 1 || c.header.length > 512 { // The entries are u16be, so the length must be even. // At most 256 entries must be present - return {}, false; + return {}, false } - ok = true; - data := mem.slice_data_cast([]u16be, c.data); - i := 0; + ok = true + data := mem.slice_data_cast([]u16be, c.data) + i := 0 for len(data) > 0 { // HIST entries are u16be, we unpack them to machine format - res.entries[i] = u16(data[0]); - i += 1; data = data[1:]; + res.entries[i] = u16(data[0]) + i += 1; data = data[1:] } - res.used = u16(i); - return; + res.used = u16(i) + return } chrm :: proc(c: Chunk) -> (res: cHRM, ok: bool) { - ok = true; + ok = true if c.header.length != size_of(cHRM_Raw) { - return {}, false; + return {}, false } - chrm := (^cHRM_Raw)(raw_data(c.data))^; - - res.w.x = f32(chrm.w.x) / 100_000.0; - res.w.y = f32(chrm.w.y) / 100_000.0; - res.r.x = f32(chrm.r.x) / 100_000.0; - res.r.y = f32(chrm.r.y) / 100_000.0; - res.g.x = f32(chrm.g.x) / 100_000.0; - res.g.y = f32(chrm.g.y) / 100_000.0; - res.b.x = f32(chrm.b.x) / 100_000.0; - res.b.y = f32(chrm.b.y) / 100_000.0; - return; + chrm := (^cHRM_Raw)(raw_data(c.data))^ + + res.w.x = f32(chrm.w.x) / 100_000.0 + res.w.y = f32(chrm.w.y) / 100_000.0 + res.r.x = f32(chrm.r.x) / 100_000.0 + res.r.y = f32(chrm.r.y) / 100_000.0 + res.g.x = f32(chrm.g.x) / 100_000.0 + res.g.y = f32(chrm.g.y) / 100_000.0 + res.b.x = f32(chrm.b.x) / 100_000.0 + res.b.y = f32(chrm.b.y) / 100_000.0 + return } exif :: proc(c: Chunk) -> (res: Exif, ok: bool) { - ok = true; + ok = true if len(c.data) < 4 { - ok = false; return; + ok = false; return } if c.data[0] == 'M' && c.data[1] == 'M' { - res.byte_order = .big_endian; + res.byte_order = .big_endian if c.data[2] != 0 || c.data[3] != 42 { - ok = false; return; + ok = false; return } } else if c.data[0] == 'I' && c.data[1] == 'I' { - res.byte_order = .little_endian; + res.byte_order = .little_endian if c.data[2] != 42 || c.data[3] != 0 { - ok = false; return; + ok = false; return } } else { - ok = false; return; + ok = false; return } - res.data = c.data; - return; + res.data = c.data + return } /* General helper functions */ -compute_buffer_size :: image.compute_buffer_size; +compute_buffer_size :: image.compute_buffer_size /* PNG save helpers @@ -404,59 +404,59 @@ when false { make_chunk :: proc(c: any, t: Chunk_Type) -> (res: Chunk) { - data: []u8; + data: []u8 if v, ok := c.([]u8); ok { - data = v; + data = v } else { - data = mem.any_to_bytes(c); + data = mem.any_to_bytes(c) } - res.header.length = u32be(len(data)); - res.header.type = t; - res.data = data; + res.header.length = u32be(len(data)) + res.header.type = t + res.data = data // CRC the type - crc := hash.crc32(mem.any_to_bytes(res.header.type)); + crc := hash.crc32(mem.any_to_bytes(res.header.type)) // Extend the CRC with the data - res.crc = u32be(hash.crc32(data, crc)); - return; + res.crc = u32be(hash.crc32(data, crc)) + return } write_chunk :: proc(fd: os.Handle, chunk: Chunk) { - c := chunk; + c := chunk // Write length + type - os.write_ptr(fd, &c.header, 8); + os.write_ptr(fd, &c.header, 8) // Write data - os.write_ptr(fd, mem.raw_data(c.data), int(c.header.length)); + os.write_ptr(fd, mem.raw_data(c.data), int(c.header.length)) // Write CRC32 - os.write_ptr(fd, &c.crc, 4); + os.write_ptr(fd, &c.crc, 4) } write_image_as_png :: proc(filename: string, image: Image) -> (err: Error) { - profiler.timed_proc(); - using image; - using os; - flags: int = O_WRONLY|O_CREATE|O_TRUNC; + profiler.timed_proc() + using image + using os + flags: int = O_WRONLY|O_CREATE|O_TRUNC if len(image.pixels) == 0 || len(image.pixels) < image.width * image.height * int(image.channels) { - return E_PNG.Invalid_Image_Dimensions; + return E_PNG.Invalid_Image_Dimensions } - mode: int = 0; + mode: int = 0 when ODIN_OS == "linux" || ODIN_OS == "darwin" { // NOTE(justasd): 644 (owner read, write; group read; others read) - mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; + mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH } - fd, fderr := open(filename, flags, mode); + fd, fderr := open(filename, flags, mode) if fderr != 0 { - return E_General.Cannot_Open_File; + return E_General.Cannot_Open_File } - defer close(fd); + defer close(fd) - magic := Signature; + magic := Signature - write_ptr(fd, &magic, 8); + write_ptr(fd, &magic, 8) ihdr := IHDR{ width = u32be(width), @@ -465,61 +465,61 @@ when false { compression_method = 0, filter_method = 0, interlace_method = .None, - }; + } switch channels { - case 1: ihdr.color_type = Color_Type{}; - case 2: ihdr.color_type = Color_Type{.Alpha}; - case 3: ihdr.color_type = Color_Type{.Color}; - case 4: ihdr.color_type = Color_Type{.Color, .Alpha}; + case 1: ihdr.color_type = Color_Type{} + case 2: ihdr.color_type = Color_Type{.Alpha} + case 3: ihdr.color_type = Color_Type{.Color} + case 4: ihdr.color_type = Color_Type{.Color, .Alpha} case:// Unhandled - return E_PNG.Unknown_Color_Type; + return E_PNG.Unknown_Color_Type } - h := make_chunk(ihdr, .IHDR); - write_chunk(fd, h); + h := make_chunk(ihdr, .IHDR) + write_chunk(fd, h) - bytes_needed := width * height * int(channels) + height; - filter_bytes := mem.make_dynamic_array_len_cap([dynamic]u8, bytes_needed, bytes_needed, context.allocator); - defer delete(filter_bytes); + bytes_needed := width * height * int(channels) + height + filter_bytes := mem.make_dynamic_array_len_cap([dynamic]u8, bytes_needed, bytes_needed, context.allocator) + defer delete(filter_bytes) - i := 0; j := 0; + i := 0; j := 0 // Add a filter byte 0 per pixel row for y := 0; y < height; y += 1 { - filter_bytes[j] = 0; j += 1; + filter_bytes[j] = 0; j += 1 for x := 0; x < width; x += 1 { for z := 0; z < channels; z += 1 { - filter_bytes[j+z] = image.pixels[i+z]; + filter_bytes[j+z] = image.pixels[i+z] } - i += channels; j += channels; + i += channels; j += channels } } - assert(j == bytes_needed); + assert(j == bytes_needed) - a: []u8 = filter_bytes[:]; + a: []u8 = filter_bytes[:] - out_buf: ^[dynamic]u8; - defer free(out_buf); + out_buf: ^[dynamic]u8 + defer free(out_buf) ctx := zlib.ZLIB_Context{ in_buf = &a, out_buf = out_buf, - }; - err = zlib.write_zlib_stream_from_memory(&ctx); + } + err = zlib.write_zlib_stream_from_memory(&ctx) - b: []u8; + b: []u8 if err == nil { - b = ctx.out_buf[:]; + b = ctx.out_buf[:] } else { - return err; + return err } - idat := make_chunk(b, .IDAT); + idat := make_chunk(b, .IDAT) - write_chunk(fd, idat); + write_chunk(fd, idat) - iend := make_chunk([]u8{}, .IEND); - write_chunk(fd, iend); + iend := make_chunk([]u8{}, .IEND) + write_chunk(fd, iend) - return nil; + return nil } } diff --git a/core/image/png/png.odin b/core/image/png/png.odin index 587fa4042..847dc1943 100644 --- a/core/image/png/png.odin +++ b/core/image/png/png.odin @@ -21,13 +21,13 @@ import "core:io" import "core:mem" import "core:intrinsics" -Error :: compress.Error; -E_General :: compress.General_Error; -E_PNG :: image.Error; -E_Deflate :: compress.Deflate_Error; +Error :: compress.Error +E_General :: compress.General_Error +E_PNG :: image.Error +E_Deflate :: compress.Deflate_Error -Image :: image.Image; -Options :: image.Options; +Image :: image.Image +Options :: image.Options Signature :: enum u64be { // 0x89504e470d0a1a0a @@ -108,7 +108,7 @@ IHDR :: struct #packed { filter_method: u8, interlace_method: Interlace_Method, } -IHDR_SIZE :: size_of(IHDR); +IHDR_SIZE :: size_of(IHDR) #assert (IHDR_SIZE == 13); Color_Value :: enum u8 { @@ -116,7 +116,7 @@ Color_Value :: enum u8 { Color = 1, // 1 << 1 = 2 Alpha = 2, // 1 << 2 = 4 } -Color_Type :: distinct bit_set[Color_Value; u8]; +Color_Type :: distinct bit_set[Color_Value; u8] Interlace_Method :: enum u8 { None = 0, @@ -129,9 +129,9 @@ Row_Filter :: enum u8 { Up = 2, Average = 3, Paeth = 4, -}; +} -PLTE_Entry :: [3]u8; +PLTE_Entry :: [3]u8 PLTE :: struct #packed { entries: [256]PLTE_Entry, @@ -161,7 +161,7 @@ tIME :: struct #packed { hour: u8, minute: u8, second: u8, -}; +} #assert(size_of(tIME) == 7); CIE_1931_Raw :: struct #packed { @@ -192,27 +192,27 @@ cHRM :: struct #packed { gAMA :: struct { gamma_100k: u32be, // Gamma * 100k -}; +} #assert(size_of(gAMA) == 4); pHYs :: struct #packed { ppu_x: u32be, ppu_y: u32be, unit: pHYs_Unit, -}; +} #assert(size_of(pHYs) == 9); pHYs_Unit :: enum u8 { Unknown = 0, Meter = 1, -}; +} Text :: struct { keyword: string, keyword_localized: string, language: string, text: string, -}; +} Exif :: struct { byte_order: enum { @@ -238,65 +238,65 @@ sRGB :: struct #packed { intent: sRGB_Rendering_Intent, } -ADAM7_X_ORIG := []int{ 0,4,0,2,0,1,0 }; -ADAM7_Y_ORIG := []int{ 0,0,4,0,2,0,1 }; -ADAM7_X_SPACING := []int{ 8,8,4,4,2,2,1 }; -ADAM7_Y_SPACING := []int{ 8,8,8,4,4,2,2 }; +ADAM7_X_ORIG := []int{ 0,4,0,2,0,1,0 } +ADAM7_Y_ORIG := []int{ 0,0,4,0,2,0,1 } +ADAM7_X_SPACING := []int{ 8,8,4,4,2,2,1 } +ADAM7_Y_SPACING := []int{ 8,8,8,4,4,2,2 } // Implementation starts here read_chunk :: proc(ctx: ^$C) -> (chunk: Chunk, err: Error) { - ch, e := compress.read_data(ctx, Chunk_Header); + ch, e := compress.read_data(ctx, Chunk_Header) if e != .None { - return {}, E_General.Stream_Too_Short; + return {}, E_General.Stream_Too_Short } - chunk.header = ch; + chunk.header = ch - chunk.data, e = compress.read_slice(ctx, int(ch.length)); + chunk.data, e = compress.read_slice(ctx, int(ch.length)) if e != .None { - return {}, E_General.Stream_Too_Short; + return {}, E_General.Stream_Too_Short } // Compute CRC over chunk type + data - type := (^[4]byte)(&ch.type)^; - computed_crc := hash.crc32(type[:]); - computed_crc = hash.crc32(chunk.data, computed_crc); + type := (^[4]byte)(&ch.type)^ + computed_crc := hash.crc32(type[:]) + computed_crc = hash.crc32(chunk.data, computed_crc) - crc, e3 := compress.read_data(ctx, u32be); + crc, e3 := compress.read_data(ctx, u32be) if e3 != .None { - return {}, E_General.Stream_Too_Short; + return {}, E_General.Stream_Too_Short } - chunk.crc = crc; + chunk.crc = crc if chunk.crc != u32be(computed_crc) { - return {}, E_General.Checksum_Failed; + return {}, E_General.Checksum_Failed } - return chunk, nil; + return chunk, nil } read_header :: proc(ctx: ^$C) -> (IHDR, Error) { - c, e := read_chunk(ctx); + c, e := read_chunk(ctx) if e != nil { - return {}, e; + return {}, e } - header := (^IHDR)(raw_data(c.data))^; + header := (^IHDR)(raw_data(c.data))^ // Validate IHDR - using header; + using header if width == 0 || height == 0 { - return {}, E_PNG.Invalid_Image_Dimensions; + return {}, E_PNG.Invalid_Image_Dimensions } if compression_method != 0 { - return {}, E_General.Unknown_Compression_Method; + return {}, E_General.Unknown_Compression_Method } if filter_method != 0 { - return {}, E_PNG.Unknown_Filter_Method; + return {}, E_PNG.Unknown_Filter_Method } if interlace_method != .None && interlace_method != .Adam7 { - return {}, E_PNG.Unknown_Interlace_Method; + return {}, E_PNG.Unknown_Interlace_Method } @@ -306,15 +306,15 @@ read_header :: proc(ctx: ^$C) -> (IHDR, Error) { Grayscale. Allowed bit depths: 1, 2, 4, 8 and 16. */ - allowed := false; + allowed := false for i in ([]u8{1, 2, 4, 8, 16}) { if bit_depth == i { - allowed = true; - break; + allowed = true + break } } if !allowed { - return {}, E_PNG.Invalid_Color_Bit_Depth_Combo; + return {}, E_PNG.Invalid_Color_Bit_Depth_Combo } case 2, 4, 6: /* @@ -322,168 +322,168 @@ read_header :: proc(ctx: ^$C) -> (IHDR, Error) { Allowed bit depths: 8 and 16 */ if bit_depth != 8 && bit_depth != 16 { - return {}, E_PNG.Invalid_Color_Bit_Depth_Combo; + return {}, E_PNG.Invalid_Color_Bit_Depth_Combo } case 3: /* Paletted. PLTE chunk must appear. Allowed bit depths: 1, 2, 4 and 8. */ - allowed := false; + allowed := false for i in ([]u8{1, 2, 4, 8}) { if bit_depth == i { - allowed = true; - break; + allowed = true + break } } if !allowed { - return {}, E_PNG.Invalid_Color_Bit_Depth_Combo; + return {}, E_PNG.Invalid_Color_Bit_Depth_Combo } case: - return {}, E_PNG.Unknown_Color_Type; + return {}, E_PNG.Unknown_Color_Type } - return header, nil; + return header, nil } chunk_type_to_name :: proc(type: ^Chunk_Type) -> string { - t := transmute(^u8)type; - return strings.string_from_ptr(t, 4); + t := transmute(^u8)type + return strings.string_from_ptr(t, 4) } load_from_slice :: proc(slice: []u8, options := Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) { ctx := &compress.Context_Memory_Input{ input_data = slice, - }; + } /* TODO: Add a flag to tell the PNG loader that the stream is backed by a slice. This way the stream reader could avoid the copy into the temp memory returned by it, and instead return a slice into the original memory that's already owned by the caller. */ - img, err = load_from_context(ctx, options, allocator); + img, err = load_from_context(ctx, options, allocator) - return img, err; + return img, err } load_from_file :: proc(filename: string, options := Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) { - data, ok := os.read_entire_file(filename, allocator); - defer delete(data); + data, ok := os.read_entire_file(filename, allocator) + defer delete(data) if ok { - return load_from_slice(data, options, allocator); + return load_from_slice(data, options, allocator) } else { - img = new(Image); - return img, E_General.File_Not_Found; + img = new(Image) + return img, E_General.File_Not_Found } } load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) { - options := options; + options := options if .info in options { - options |= {.return_metadata, .do_not_decompress_image}; - options -= {.info}; + options |= {.return_metadata, .do_not_decompress_image} + options -= {.info} } if .alpha_drop_if_present in options && .alpha_add_if_missing in options { - return {}, E_General.Incompatible_Options; + return {}, E_General.Incompatible_Options } if .do_not_expand_channels in options { - options |= {.do_not_expand_grayscale, .do_not_expand_indexed}; + options |= {.do_not_expand_grayscale, .do_not_expand_indexed} } if img == nil { - img = new(Image); + img = new(Image) } - info := new(Info, context.allocator); - img.metadata_ptr = info; - img.metadata_type = typeid_of(Info); + info := new(Info, context.allocator) + img.metadata_ptr = info + img.metadata_type = typeid_of(Info) - signature, io_error := compress.read_data(ctx, Signature); + signature, io_error := compress.read_data(ctx, Signature) if io_error != .None || signature != .PNG { - return img, E_PNG.Invalid_PNG_Signature; + return img, E_PNG.Invalid_PNG_Signature } - idat: []u8; - idat_b: bytes.Buffer; - idat_length := u32be(0); - defer bytes.buffer_destroy(&idat_b); + idat: []u8 + idat_b: bytes.Buffer + idat_length := u32be(0) + defer bytes.buffer_destroy(&idat_b) - c: Chunk; - ch: Chunk_Header; - e: io.Error; + c: Chunk + ch: Chunk_Header + e: io.Error - header: IHDR; + header: IHDR - info.chunks.allocator = context.temp_allocator; + info.chunks.allocator = context.temp_allocator // State to ensure correct chunk ordering. - seen_ihdr := false; first := true; - seen_plte := false; - seen_bkgd := false; - seen_trns := false; - seen_idat := false; - seen_iend := false; + seen_ihdr := false; first := true + seen_plte := false + seen_bkgd := false + seen_trns := false + seen_idat := false + seen_iend := false - _plte := PLTE{}; - trns := Chunk{}; + _plte := PLTE{} + trns := Chunk{} - final_image_channels := 0; + final_image_channels := 0 - read_error: io.Error; + read_error: io.Error // 12 bytes is the size of a chunk with a zero-length payload. for read_error == .None && !seen_iend { // Peek at next chunk's length and type. // TODO: Some streams may not provide seek/read_at - ch, e = compress.peek_data(ctx, Chunk_Header); + ch, e = compress.peek_data(ctx, Chunk_Header) if e != .None { - return img, E_General.Stream_Too_Short; + return img, E_General.Stream_Too_Short } // name := chunk_type_to_name(&ch.type); // Only used for debug prints during development. #partial switch ch.type { case .IHDR: if seen_ihdr || !first { - return {}, E_PNG.IHDR_Not_First_Chunk; + return {}, E_PNG.IHDR_Not_First_Chunk } - seen_ihdr = true; + seen_ihdr = true - header = read_header(ctx) or_return; + header = read_header(ctx) or_return if .Paletted in header.color_type { // Color type 3 - img.channels = 1; - final_image_channels = 3; - img.depth = 8; + img.channels = 1 + final_image_channels = 3 + img.depth = 8 } else if .Color in header.color_type { // Color image without a palette - img.channels = 3; - final_image_channels = 3; - img.depth = int(header.bit_depth); + img.channels = 3 + final_image_channels = 3 + img.depth = int(header.bit_depth) } else { // Grayscale - img.channels = 1; - final_image_channels = 1; - img.depth = int(header.bit_depth); + img.channels = 1 + final_image_channels = 1 + img.depth = int(header.bit_depth) } if .Alpha in header.color_type { - img.channels += 1; - final_image_channels += 1; + img.channels += 1 + final_image_channels += 1 } if img.channels == 0 || img.depth == 0 { - return {}, E_PNG.IHDR_Corrupt; + return {}, E_PNG.IHDR_Corrupt } - img.width = int(header.width); - img.height = int(header.height); + img.width = int(header.width) + img.height = int(header.height) - using header; + using header h := IHDR{ width = width, height = height, @@ -492,110 +492,110 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a compression_method = compression_method, filter_method = filter_method, interlace_method = interlace_method, - }; - info.header = h; + } + info.header = h case .PLTE: - seen_plte = true; + seen_plte = true // PLTE must appear before IDAT and can't appear for color types 0, 4. - ct := transmute(u8)info.header.color_type; + ct := transmute(u8)info.header.color_type if seen_idat || ct == 0 || ct == 4 { - return img, E_PNG.PLTE_Encountered_Unexpectedly; + return img, E_PNG.PLTE_Encountered_Unexpectedly } - c = read_chunk(ctx) or_return; + c = read_chunk(ctx) or_return if c.header.length % 3 != 0 || c.header.length > 768 { - return img, E_PNG.PLTE_Invalid_Length; + return img, E_PNG.PLTE_Invalid_Length } - plte_ok: bool; - _plte, plte_ok = plte(c); + plte_ok: bool + _plte, plte_ok = plte(c) if !plte_ok { - return img, E_PNG.PLTE_Invalid_Length; + return img, E_PNG.PLTE_Invalid_Length } if .return_metadata in options { - append(&info.chunks, c); + append(&info.chunks, c) } case .IDAT: // If we only want image metadata and don't want the pixel data, we can early out. if .return_metadata not_in options && .do_not_decompress_image in options { - img.channels = final_image_channels; - return img, nil; + img.channels = final_image_channels + return img, nil } // There must be at least 1 IDAT, contiguous if more. if seen_idat { - return img, E_PNG.IDAT_Must_Be_Contiguous; + return img, E_PNG.IDAT_Must_Be_Contiguous } if idat_length > 0 { - return img, E_PNG.IDAT_Must_Be_Contiguous; + return img, E_PNG.IDAT_Must_Be_Contiguous } - next := ch.type; + next := ch.type for next == .IDAT { - c = read_chunk(ctx) or_return; + c = read_chunk(ctx) or_return - bytes.buffer_write(&idat_b, c.data); - idat_length += c.header.length; + bytes.buffer_write(&idat_b, c.data) + idat_length += c.header.length - ch, e = compress.peek_data(ctx, Chunk_Header); + ch, e = compress.peek_data(ctx, Chunk_Header) if e != .None { - return img, E_General.Stream_Too_Short; + return img, E_General.Stream_Too_Short } - next = ch.type; + next = ch.type } - idat = bytes.buffer_to_bytes(&idat_b); + idat = bytes.buffer_to_bytes(&idat_b) if int(idat_length) != len(idat) { - return {}, E_PNG.IDAT_Corrupt; + return {}, E_PNG.IDAT_Corrupt } - seen_idat = true; + seen_idat = true case .IEND: - c = read_chunk(ctx) or_return; - seen_iend = true; + c = read_chunk(ctx) or_return + seen_iend = true case .bKGD: // TODO: Make sure that 16-bit bKGD + tRNS chunks return u16 instead of u16be - c = read_chunk(ctx) or_return; - seen_bkgd = true; + c = read_chunk(ctx) or_return + seen_bkgd = true if .return_metadata in options { - append(&info.chunks, c); + append(&info.chunks, c) } - ct := transmute(u8)info.header.color_type; + ct := transmute(u8)info.header.color_type switch ct { case 3: // Indexed color if c.header.length != 1 { - return {}, E_PNG.BKGD_Invalid_Length; + return {}, E_PNG.BKGD_Invalid_Length } - col := _plte.entries[c.data[0]]; + col := _plte.entries[c.data[0]] img.background = [3]u16{ u16(col[0]) << 8 | u16(col[0]), u16(col[1]) << 8 | u16(col[1]), u16(col[2]) << 8 | u16(col[2]), - }; + } case 0, 4: // Grayscale, with and without Alpha if c.header.length != 2 { - return {}, E_PNG.BKGD_Invalid_Length; + return {}, E_PNG.BKGD_Invalid_Length } - col := u16(mem.slice_data_cast([]u16be, c.data[:])[0]); - img.background = [3]u16{col, col, col}; + col := u16(mem.slice_data_cast([]u16be, c.data[:])[0]) + img.background = [3]u16{col, col, col} case 2, 6: // Color, with and without Alpha if c.header.length != 6 { - return {}, E_PNG.BKGD_Invalid_Length; + return {}, E_PNG.BKGD_Invalid_Length } - col := mem.slice_data_cast([]u16be, c.data[:]); - img.background = [3]u16{u16(col[0]), u16(col[1]), u16(col[2])}; + col := mem.slice_data_cast([]u16be, c.data[:]) + img.background = [3]u16{u16(col[0]), u16(col[1]), u16(col[2])} } case .tRNS: - c = read_chunk(ctx) or_return; + c = read_chunk(ctx) or_return if .Alpha in info.header.color_type { - return img, E_PNG.TRNS_Encountered_Unexpectedly; + return img, E_PNG.TRNS_Encountered_Unexpectedly } if .return_metadata in options { - append(&info.chunks, c); + append(&info.chunks, c) } /* @@ -605,46 +605,46 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a we'll set it to 'final_image_channels'. */ - final_image_channels += 1; + final_image_channels += 1 - seen_trns = true; + seen_trns = true if info.header.bit_depth < 8 && .Paletted not_in info.header.color_type { // Rescale tRNS data so key matches intensity - dsc := depth_scale_table; - scale := dsc[info.header.bit_depth]; + dsc := depth_scale_table + scale := dsc[info.header.bit_depth] if scale != 1 { - key := mem.slice_data_cast([]u16be, c.data)[0] * u16be(scale); - c.data = []u8{0, u8(key & 255)}; + key := mem.slice_data_cast([]u16be, c.data)[0] * u16be(scale) + c.data = []u8{0, u8(key & 255)} } } - trns = c; + trns = c case .iDOT, .CbGI: /* iPhone PNG bastardization that doesn't adhere to spec with broken IDAT chunk. We're not going to add support for it. If you have the misfortunte of coming across one of these files, use a utility to defry it.s */ - return img, E_PNG.PNG_Does_Not_Adhere_to_Spec; + return img, E_PNG.PNG_Does_Not_Adhere_to_Spec case: // Unhandled type - c = read_chunk(ctx) or_return; + c = read_chunk(ctx) or_return if .return_metadata in options { // NOTE: Chunk cata is currently allocated on the temp allocator. - append(&info.chunks, c); + append(&info.chunks, c) } - first = false; + first = false } } if .do_not_decompress_image in options { - img.channels = final_image_channels; - return img, nil; + img.channels = final_image_channels + return img, nil } if !seen_idat { - return img, E_PNG.IDAT_Missing; + return img, E_PNG.IDAT_Missing } /* @@ -653,35 +653,35 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a Let's calcalate the expected size of the IDAT based on its dimensions, and whether or not it's interlaced. */ - expected_size: int; + expected_size: int if header.interlace_method != .Adam7 { - expected_size = compute_buffer_size(int(header.width), int(header.height), int(img.channels), int(header.bit_depth), 1); + expected_size = compute_buffer_size(int(header.width), int(header.height), int(img.channels), int(header.bit_depth), 1) } else { /* Because Adam7 divides the image up into sub-images, and each scanline must start with a filter byte, Adam7 interlaced images can have a larger raw size. */ for p := 0; p < 7; p += 1 { - x := (int(header.width) - ADAM7_X_ORIG[p] + ADAM7_X_SPACING[p] - 1) / ADAM7_X_SPACING[p]; - y := (int(header.height) - ADAM7_Y_ORIG[p] + ADAM7_Y_SPACING[p] - 1) / ADAM7_Y_SPACING[p]; + x := (int(header.width) - ADAM7_X_ORIG[p] + ADAM7_X_SPACING[p] - 1) / ADAM7_X_SPACING[p] + y := (int(header.height) - ADAM7_Y_ORIG[p] + ADAM7_Y_SPACING[p] - 1) / ADAM7_Y_SPACING[p] if x > 0 && y > 0 { - expected_size += compute_buffer_size(int(x), int(y), int(img.channels), int(header.bit_depth), 1); + expected_size += compute_buffer_size(int(x), int(y), int(img.channels), int(header.bit_depth), 1) } } } - buf: bytes.Buffer; - zlib_error := zlib.inflate(idat, &buf, false, expected_size); - defer bytes.buffer_destroy(&buf); + buf: bytes.Buffer + zlib_error := zlib.inflate(idat, &buf, false, expected_size) + defer bytes.buffer_destroy(&buf) if zlib_error != nil { - return {}, zlib_error; + return {}, zlib_error } - buf_len := len(buf.buf); + buf_len := len(buf.buf) if expected_size != buf_len { - return {}, E_PNG.IDAT_Corrupt; + return {}, E_PNG.IDAT_Corrupt } /* @@ -689,10 +689,10 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a So, we'll save the old value of img.channels we return to the user as metadata, and set it instead to the raw number of channels. */ - defilter_error := defilter(img, &buf, &header, options); + defilter_error := defilter(img, &buf, &header, options) if defilter_error != nil { - bytes.buffer_destroy(&img.pixels); - return {}, defilter_error; + bytes.buffer_destroy(&img.pixels) + return {}, defilter_error } /* @@ -705,111 +705,111 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a */ if .Paletted in header.color_type && .do_not_expand_indexed in options { - return img, nil; + return img, nil } if .Color not_in header.color_type && .do_not_expand_grayscale in options { - return img, nil; + return img, nil } - raw_image_channels := img.channels; - out_image_channels := 3; + raw_image_channels := img.channels + out_image_channels := 3 /* To give ourselves less options to test, we'll knock out `.blend_background` and `seen_bkgd` if we haven't seen both. */ if !(seen_bkgd && .blend_background in options) { - options -= {.blend_background}; - seen_bkgd = false; + options -= {.blend_background} + seen_bkgd = false } if seen_trns || .Alpha in info.header.color_type || .alpha_add_if_missing in options { - out_image_channels = 4; + out_image_channels = 4 } if .alpha_drop_if_present in options { - out_image_channels = 3; + out_image_channels = 3 } if seen_bkgd && .blend_background in options && .alpha_add_if_missing not_in options { - out_image_channels = 3; + out_image_channels = 3 } - add_alpha := (seen_trns && .alpha_drop_if_present not_in options) || (.alpha_add_if_missing in options); - premultiply := .alpha_premultiply in options || seen_bkgd; + add_alpha := (seen_trns && .alpha_drop_if_present not_in options) || (.alpha_add_if_missing in options) + premultiply := .alpha_premultiply in options || seen_bkgd - img.channels = out_image_channels; + img.channels = out_image_channels if .Paletted in header.color_type { - temp := img.pixels; - defer bytes.buffer_destroy(&temp); + temp := img.pixels + defer bytes.buffer_destroy(&temp) // We need to create a new image buffer - dest_raw_size := compute_buffer_size(int(header.width), int(header.height), out_image_channels, 8); - t := bytes.Buffer{}; - resize(&t.buf, dest_raw_size); + dest_raw_size := compute_buffer_size(int(header.width), int(header.height), out_image_channels, 8) + t := bytes.Buffer{} + resize(&t.buf, dest_raw_size) - i := 0; j := 0; + i := 0; j := 0 // If we don't have transparency or drop it without applying it, we can do this: if (!seen_trns || (seen_trns && .alpha_drop_if_present in options && .alpha_premultiply not_in options)) && .alpha_add_if_missing not_in options { for h := 0; h < int(img.height); h += 1 { for w := 0; w < int(img.width); w += 1 { - c := _plte.entries[temp.buf[i]]; - t.buf[j ] = c.r; - t.buf[j+1] = c.g; - t.buf[j+2] = c.b; - i += 1; j += 3; + c := _plte.entries[temp.buf[i]] + t.buf[j ] = c.r + t.buf[j+1] = c.g + t.buf[j+2] = c.b + i += 1; j += 3 } } } else if add_alpha || .alpha_drop_if_present in options { - bg := [3]f32{0, 0, 0}; + bg := [3]f32{0, 0, 0} if premultiply && seen_bkgd { - c16 := img.background.([3]u16); - bg = [3]f32{f32(c16.r), f32(c16.g), f32(c16.b)}; + c16 := img.background.([3]u16) + bg = [3]f32{f32(c16.r), f32(c16.g), f32(c16.b)} } - no_alpha := (.alpha_drop_if_present in options || premultiply) && .alpha_add_if_missing not_in options; - blend_background := seen_bkgd && .blend_background in options; + no_alpha := (.alpha_drop_if_present in options || premultiply) && .alpha_add_if_missing not_in options + blend_background := seen_bkgd && .blend_background in options for h := 0; h < int(img.height); h += 1 { for w := 0; w < int(img.width); w += 1 { - index := temp.buf[i]; + index := temp.buf[i] - c := _plte.entries[index]; - a := int(index) < len(trns.data) ? trns.data[index] : 255; - alpha := f32(a) / 255.0; + c := _plte.entries[index] + a := int(index) < len(trns.data) ? trns.data[index] : 255 + alpha := f32(a) / 255.0 if blend_background { - c.r = u8((1.0 - alpha) * bg[0] + f32(c.r) * alpha); - c.g = u8((1.0 - alpha) * bg[1] + f32(c.g) * alpha); - c.b = u8((1.0 - alpha) * bg[2] + f32(c.b) * alpha); - a = 255; + c.r = u8((1.0 - alpha) * bg[0] + f32(c.r) * alpha) + c.g = u8((1.0 - alpha) * bg[1] + f32(c.g) * alpha) + c.b = u8((1.0 - alpha) * bg[2] + f32(c.b) * alpha) + a = 255 } else if premultiply { - c.r = u8(f32(c.r) * alpha); - c.g = u8(f32(c.g) * alpha); - c.b = u8(f32(c.b) * alpha); + c.r = u8(f32(c.r) * alpha) + c.g = u8(f32(c.g) * alpha) + c.b = u8(f32(c.b) * alpha) } - t.buf[j ] = c.r; - t.buf[j+1] = c.g; - t.buf[j+2] = c.b; - i += 1; + t.buf[j ] = c.r + t.buf[j+1] = c.g + t.buf[j+2] = c.b + i += 1 if no_alpha { - j += 3; + j += 3 } else { - t.buf[j+3] = u8(a); - j += 4; + t.buf[j+3] = u8(a) + j += 4 } } } } else { - unreachable(); + unreachable() } - img.pixels = t; + img.pixels = t } else if img.depth == 16 { // Check if we need to do something. @@ -817,100 +817,100 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a // If we have 3 in and 3 out, or 4 in and 4 out without premultiplication... if raw_image_channels == 4 && .alpha_premultiply not_in options && !seen_bkgd { // Then we're done. - return img, nil; + return img, nil } } - temp := img.pixels; - defer bytes.buffer_destroy(&temp); + temp := img.pixels + defer bytes.buffer_destroy(&temp) // We need to create a new image buffer - dest_raw_size := compute_buffer_size(int(header.width), int(header.height), out_image_channels, 16); - t := bytes.Buffer{}; - resize(&t.buf, dest_raw_size); + dest_raw_size := compute_buffer_size(int(header.width), int(header.height), out_image_channels, 16) + t := bytes.Buffer{} + resize(&t.buf, dest_raw_size) - p16 := mem.slice_data_cast([]u16, temp.buf[:]); - o16 := mem.slice_data_cast([]u16, t.buf[:]); + p16 := mem.slice_data_cast([]u16, temp.buf[:]) + o16 := mem.slice_data_cast([]u16, t.buf[:]) switch raw_image_channels { case 1: // Gray without Alpha. Might have tRNS alpha. - key := u16(0); + key := u16(0) if seen_trns { - key = mem.slice_data_cast([]u16, trns.data)[0]; + key = mem.slice_data_cast([]u16, trns.data)[0] } for len(p16) > 0 { - r := p16[0]; + r := p16[0] - alpha := u16(1); // Default to full opaque + alpha := u16(1) // Default to full opaque if seen_trns { if r == key { if seen_bkgd { - c := img.background.([3]u16); - r = c[0]; + c := img.background.([3]u16) + r = c[0] } else { - alpha = 0; // Keyed transparency + alpha = 0 // Keyed transparency } } } if premultiply { - o16[0] = r * alpha; - o16[1] = r * alpha; - o16[2] = r * alpha; + o16[0] = r * alpha + o16[1] = r * alpha + o16[2] = r * alpha } else { - o16[0] = r; - o16[1] = r; - o16[2] = r; + o16[0] = r + o16[1] = r + o16[2] = r } if out_image_channels == 4 { - o16[3] = alpha * 65535; + o16[3] = alpha * 65535 } - p16 = p16[1:]; - o16 = o16[out_image_channels:]; + p16 = p16[1:] + o16 = o16[out_image_channels:] } case 2: // Gray with alpha, we shouldn't have a tRNS chunk. - bg := f32(0.0); + bg := f32(0.0) if seen_bkgd { - bg = f32(img.background.([3]u16)[0]); + bg = f32(img.background.([3]u16)[0]) } for len(p16) > 0 { - r := p16[0]; + r := p16[0] if seen_bkgd { - alpha := f32(p16[1]) / f32(65535); - c := u16(f32(r) * alpha + (1.0 - alpha) * bg); - o16[0] = c; - o16[1] = c; - o16[2] = c; + alpha := f32(p16[1]) / f32(65535) + c := u16(f32(r) * alpha + (1.0 - alpha) * bg) + o16[0] = c + o16[1] = c + o16[2] = c /* After BG blending, the pixel is now fully opaque. Update the value we'll write to the output alpha. */ - p16[1] = 65535; + p16[1] = 65535 } else if premultiply { - alpha := p16[1]; - c := u16(f32(r) * f32(alpha) / f32(65535)); - o16[0] = c; - o16[1] = c; - o16[2] = c; + alpha := p16[1] + c := u16(f32(r) * f32(alpha) / f32(65535)) + o16[0] = c + o16[1] = c + o16[2] = c } else { - o16[0] = r; - o16[1] = r; - o16[2] = r; + o16[0] = r + o16[1] = r + o16[2] = r } if out_image_channels == 4 { - o16[3] = p16[1]; + o16[3] = p16[1] } - p16 = p16[2:]; - o16 = o16[out_image_channels:]; + p16 = p16[2:] + o16 = o16[out_image_channels:] } case 3: /* @@ -918,95 +918,95 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a We may still have a tRNS chunk or `.alpha_add_if_missing`. */ - key: []u16; + key: []u16 if seen_trns { - key = mem.slice_data_cast([]u16, trns.data); + key = mem.slice_data_cast([]u16, trns.data) } for len(p16) > 0 { - r := p16[0]; - g := p16[1]; - b := p16[2]; + r := p16[0] + g := p16[1] + b := p16[2] - alpha := u16(1); // Default to full opaque + alpha := u16(1) // Default to full opaque if seen_trns { if r == key[0] && g == key[1] && b == key[2] { if seen_bkgd { - c := img.background.([3]u16); - r = c[0]; - g = c[1]; - b = c[2]; + c := img.background.([3]u16) + r = c[0] + g = c[1] + b = c[2] } else { - alpha = 0; // Keyed transparency + alpha = 0 // Keyed transparency } } } if premultiply { - o16[0] = r * alpha; - o16[1] = g * alpha; - o16[2] = b * alpha; + o16[0] = r * alpha + o16[1] = g * alpha + o16[2] = b * alpha } else { - o16[0] = r; - o16[1] = g; - o16[2] = b; + o16[0] = r + o16[1] = g + o16[2] = b } if out_image_channels == 4 { - o16[3] = alpha * 65535; + o16[3] = alpha * 65535 } - p16 = p16[3:]; - o16 = o16[out_image_channels:]; + p16 = p16[3:] + o16 = o16[out_image_channels:] } case 4: // Color with Alpha, can't have tRNS. for len(p16) > 0 { - r := p16[0]; - g := p16[1]; - b := p16[2]; - a := p16[3]; + r := p16[0] + g := p16[1] + b := p16[2] + a := p16[3] if seen_bkgd { - alpha := f32(a) / 65535.0; - c := img.background.([3]u16); - rb := f32(c[0]) * (1.0 - alpha); - gb := f32(c[1]) * (1.0 - alpha); - bb := f32(c[2]) * (1.0 - alpha); - - o16[0] = u16(f32(r) * alpha + rb); - o16[1] = u16(f32(g) * alpha + gb); - o16[2] = u16(f32(b) * alpha + bb); + alpha := f32(a) / 65535.0 + c := img.background.([3]u16) + rb := f32(c[0]) * (1.0 - alpha) + gb := f32(c[1]) * (1.0 - alpha) + bb := f32(c[2]) * (1.0 - alpha) + + o16[0] = u16(f32(r) * alpha + rb) + o16[1] = u16(f32(g) * alpha + gb) + o16[2] = u16(f32(b) * alpha + bb) /* After BG blending, the pixel is now fully opaque. Update the value we'll write to the output alpha. */ - a = 65535; + a = 65535 } else if premultiply { - alpha := f32(a) / 65535.0; - o16[0] = u16(f32(r) * alpha); - o16[1] = u16(f32(g) * alpha); - o16[2] = u16(f32(b) * alpha); + alpha := f32(a) / 65535.0 + o16[0] = u16(f32(r) * alpha) + o16[1] = u16(f32(g) * alpha) + o16[2] = u16(f32(b) * alpha) } else { - o16[0] = r; - o16[1] = g; - o16[2] = b; + o16[0] = r + o16[1] = g + o16[2] = b } if out_image_channels == 4 { - o16[3] = a; + o16[3] = a } - p16 = p16[4:]; - o16 = o16[out_image_channels:]; + p16 = p16[4:] + o16 = o16[out_image_channels:] } case: - unreachable("We should never seen # channels other than 1-4 inclusive."); + unreachable("We should never seen # channels other than 1-4 inclusive.") } - img.pixels = t; - img.channels = out_image_channels; + img.pixels = t + img.channels = out_image_channels } else if img.depth == 8 { // Check if we need to do something. @@ -1014,216 +1014,216 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a // If we have 3 in and 3 out, or 4 in and 4 out without premultiplication... if !premultiply { // Then we're done. - return img, nil; + return img, nil } } - temp := img.pixels; - defer bytes.buffer_destroy(&temp); + temp := img.pixels + defer bytes.buffer_destroy(&temp) // We need to create a new image buffer - dest_raw_size := compute_buffer_size(int(header.width), int(header.height), out_image_channels, 8); - t := bytes.Buffer{}; - resize(&t.buf, dest_raw_size); + dest_raw_size := compute_buffer_size(int(header.width), int(header.height), out_image_channels, 8) + t := bytes.Buffer{} + resize(&t.buf, dest_raw_size) - p := mem.slice_data_cast([]u8, temp.buf[:]); - o := mem.slice_data_cast([]u8, t.buf[:]); + p := mem.slice_data_cast([]u8, temp.buf[:]) + o := mem.slice_data_cast([]u8, t.buf[:]) switch raw_image_channels { case 1: // Gray without Alpha. Might have tRNS alpha. - key := u8(0); + key := u8(0) if seen_trns { - key = u8(mem.slice_data_cast([]u16be, trns.data)[0]); + key = u8(mem.slice_data_cast([]u16be, trns.data)[0]) } for len(p) > 0 { - r := p[0]; - alpha := u8(1); + r := p[0] + alpha := u8(1) if seen_trns { if r == key { if seen_bkgd { - bc := img.background.([3]u16); - r = u8(bc[0]); + bc := img.background.([3]u16) + r = u8(bc[0]) } else { - alpha = 0; // Keyed transparency + alpha = 0 // Keyed transparency } } if premultiply { - r *= alpha; + r *= alpha } } - o[0] = r; - o[1] = r; - o[2] = r; + o[0] = r + o[1] = r + o[2] = r if out_image_channels == 4 { - o[3] = alpha * 255; + o[3] = alpha * 255 } - p = p[1:]; - o = o[out_image_channels:]; + p = p[1:] + o = o[out_image_channels:] } case 2: // Gray with alpha, we shouldn't have a tRNS chunk. - bg := f32(0.0); + bg := f32(0.0) if seen_bkgd { - bg = f32(img.background.([3]u16)[0]); + bg = f32(img.background.([3]u16)[0]) } for len(p) > 0 { - r := p[0]; + r := p[0] if seen_bkgd { - alpha := f32(p[1]) / f32(255); - c := u8(f32(r) * alpha + (1.0 - alpha) * bg); - o[0] = c; - o[1] = c; - o[2] = c; + alpha := f32(p[1]) / f32(255) + c := u8(f32(r) * alpha + (1.0 - alpha) * bg) + o[0] = c + o[1] = c + o[2] = c /* After BG blending, the pixel is now fully opaque. Update the value we'll write to the output alpha. */ - p[1] = 255; + p[1] = 255 } else if .alpha_premultiply in options { - alpha := p[1]; - c := u8(f32(r) * f32(alpha) / f32(255)); - o[0] = c; - o[1] = c; - o[2] = c; + alpha := p[1] + c := u8(f32(r) * f32(alpha) / f32(255)) + o[0] = c + o[1] = c + o[2] = c } else { - o[0] = r; - o[1] = r; - o[2] = r; + o[0] = r + o[1] = r + o[2] = r } if out_image_channels == 4 { - o[3] = p[1]; + o[3] = p[1] } - p = p[2:]; - o = o[out_image_channels:]; + p = p[2:] + o = o[out_image_channels:] } case 3: // Color without Alpha. We may still have a tRNS chunk - key: []u8; + key: []u8 if seen_trns { /* For 8-bit images, the tRNS chunk still contains a triple in u16be. We use only the low byte in this case. */ - key = []u8{trns.data[1], trns.data[3], trns.data[5]}; + key = []u8{trns.data[1], trns.data[3], trns.data[5]} } for len(p) > 0 { - r := p[0]; - g := p[1]; - b := p[2]; + r := p[0] + g := p[1] + b := p[2] - alpha := u8(1); // Default to full opaque + alpha := u8(1) // Default to full opaque if seen_trns { if r == key[0] && g == key[1] && b == key[2] { if seen_bkgd { - c := img.background.([3]u16); - r = u8(c[0]); - g = u8(c[1]); - b = u8(c[2]); + c := img.background.([3]u16) + r = u8(c[0]) + g = u8(c[1]) + b = u8(c[2]) } else { - alpha = 0; // Keyed transparency + alpha = 0 // Keyed transparency } } if premultiply { - r *= alpha; - g *= alpha; - b *= alpha; + r *= alpha + g *= alpha + b *= alpha } } - o[0] = r; - o[1] = g; - o[2] = b; + o[0] = r + o[1] = g + o[2] = b if out_image_channels == 4 { - o[3] = alpha * 255; + o[3] = alpha * 255 } - p = p[3:]; - o = o[out_image_channels:]; + p = p[3:] + o = o[out_image_channels:] } case 4: // Color with Alpha, can't have tRNS. for len(p) > 0 { - r := p[0]; - g := p[1]; - b := p[2]; - a := p[3]; + r := p[0] + g := p[1] + b := p[2] + a := p[3] if seen_bkgd { - alpha := f32(a) / 255.0; - c := img.background.([3]u16); - rb := f32(c[0]) * (1.0 - alpha); - gb := f32(c[1]) * (1.0 - alpha); - bb := f32(c[2]) * (1.0 - alpha); - - o[0] = u8(f32(r) * alpha + rb); - o[1] = u8(f32(g) * alpha + gb); - o[2] = u8(f32(b) * alpha + bb); + alpha := f32(a) / 255.0 + c := img.background.([3]u16) + rb := f32(c[0]) * (1.0 - alpha) + gb := f32(c[1]) * (1.0 - alpha) + bb := f32(c[2]) * (1.0 - alpha) + + o[0] = u8(f32(r) * alpha + rb) + o[1] = u8(f32(g) * alpha + gb) + o[2] = u8(f32(b) * alpha + bb) /* After BG blending, the pixel is now fully opaque. Update the value we'll write to the output alpha. */ - a = 255; + a = 255 } else if premultiply { - alpha := f32(a) / 255.0; - o[0] = u8(f32(r) * alpha); - o[1] = u8(f32(g) * alpha); - o[2] = u8(f32(b) * alpha); + alpha := f32(a) / 255.0 + o[0] = u8(f32(r) * alpha) + o[1] = u8(f32(g) * alpha) + o[2] = u8(f32(b) * alpha) } else { - o[0] = r; - o[1] = g; - o[2] = b; + o[0] = r + o[1] = g + o[2] = b } if out_image_channels == 4 { - o[3] = a; + o[3] = a } - p = p[4:]; - o = o[out_image_channels:]; + p = p[4:] + o = o[out_image_channels:] } case: - unreachable("We should never seen # channels other than 1-4 inclusive."); + unreachable("We should never seen # channels other than 1-4 inclusive.") } - img.pixels = t; - img.channels = out_image_channels; + img.pixels = t + img.channels = out_image_channels } else { /* This may change if we ever don't expand 1, 2 and 4 bit images. But, those raw returns will likely bypass this processing pipeline. */ - unreachable("We should never see bit depths other than 8, 16 and 'Paletted' here."); + unreachable("We should never see bit depths other than 8, 16 and 'Paletted' here.") } - return img, nil; + return img, nil } filter_paeth :: #force_inline proc(left, up, up_left: u8) -> u8 { - aa, bb, cc := i16(left), i16(up), i16(up_left); - p := aa + bb - cc; - pa := abs(p - aa); - pb := abs(p - bb); - pc := abs(p - cc); + aa, bb, cc := i16(left), i16(up), i16(up_left) + p := aa + bb - cc + pa := abs(p - aa) + pb := abs(p - bb) + pc := abs(p - cc) if pa <= pb && pa <= pc { - return left; + return left } if pb <= pc { - return up; + return up } - return up_left; + return up_left } Filter_Params :: struct #packed { @@ -1236,139 +1236,139 @@ Filter_Params :: struct #packed { rescale: bool, } -depth_scale_table :: []u8{0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01}; +depth_scale_table :: []u8{0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01} // @(optimization_mode="speed") defilter_8 :: proc(params: ^Filter_Params) -> (ok: bool) { - using params; - row_stride := channels * width; + using params + row_stride := channels * width // TODO: See about doing a Duff's #unroll where practicable // Apron so we don't need to special case first rows. - up := make([]u8, row_stride, context.temp_allocator); - ok = true; + up := make([]u8, row_stride, context.temp_allocator) + ok = true for _ in 0..<height { - nk := row_stride - channels; + nk := row_stride - channels - filter := Row_Filter(src[0]); src = src[1:]; + filter := Row_Filter(src[0]); src = src[1:] switch filter { case .None: - copy(dest, src[:row_stride]); + copy(dest, src[:row_stride]) case .Sub: for i := 0; i < channels; i += 1 { - dest[i] = src[i]; + dest[i] = src[i] } for k := 0; k < nk; k += 1 { - dest[channels+k] = (src[channels+k] + dest[k]) & 255; + dest[channels+k] = (src[channels+k] + dest[k]) & 255 } case .Up: for k := 0; k < row_stride; k += 1 { - dest[k] = (src[k] + up[k]) & 255; + dest[k] = (src[k] + up[k]) & 255 } case .Average: for i := 0; i < channels; i += 1 { - avg := up[i] >> 1; - dest[i] = (src[i] + avg) & 255; + avg := up[i] >> 1 + dest[i] = (src[i] + avg) & 255 } for k := 0; k < nk; k += 1 { - avg := u8((u16(up[channels+k]) + u16(dest[k])) >> 1); - dest[channels+k] = (src[channels+k] + avg) & 255; + avg := u8((u16(up[channels+k]) + u16(dest[k])) >> 1) + dest[channels+k] = (src[channels+k] + avg) & 255 } case .Paeth: for i := 0; i < channels; i += 1 { - paeth := filter_paeth(0, up[i], 0); - dest[i] = (src[i] + paeth) & 255; + paeth := filter_paeth(0, up[i], 0) + dest[i] = (src[i] + paeth) & 255 } for k := 0; k < nk; k += 1 { - paeth := filter_paeth(dest[k], up[channels+k], up[k]); - dest[channels+k] = (src[channels+k] + paeth) & 255; + paeth := filter_paeth(dest[k], up[channels+k], up[k]) + dest[channels+k] = (src[channels+k] + paeth) & 255 } case: - return false; + return false } - src = src[row_stride:]; - up = dest; - dest = dest[row_stride:]; + src = src[row_stride:] + up = dest + dest = dest[row_stride:] } - return; + return } // @(optimization_mode="speed") defilter_less_than_8 :: proc(params: ^Filter_Params) -> (ok: bool) #no_bounds_check { - using params; - ok = true; + using params + ok = true - row_stride_in := ((channels * width * depth) + 7) >> 3; - row_stride_out := channels * width; + row_stride_in := ((channels * width * depth) + 7) >> 3 + row_stride_out := channels * width // Store defiltered bytes rightmost so we can widen in-place. - row_offset := row_stride_out - row_stride_in; + row_offset := row_stride_out - row_stride_in // Save original dest because we'll need it for the bit widening. - orig_dest := dest; + orig_dest := dest // TODO: See about doing a Duff's #unroll where practicable // Apron so we don't need to special case first rows. - up := make([]u8, row_stride_out, context.temp_allocator); + up := make([]u8, row_stride_out, context.temp_allocator) #no_bounds_check for _ in 0..<height { - nk := row_stride_in - channels; + nk := row_stride_in - channels - dest = dest[row_offset:]; + dest = dest[row_offset:] - filter := Row_Filter(src[0]); src = src[1:]; + filter := Row_Filter(src[0]); src = src[1:] switch filter { case .None: - copy(dest, src[:row_stride_in]); + copy(dest, src[:row_stride_in]) case .Sub: for i in 0..=channels { - dest[i] = src[i]; + dest[i] = src[i] } for k in 0..=nk { - dest[channels+k] = (src[channels+k] + dest[k]) & 255; + dest[channels+k] = (src[channels+k] + dest[k]) & 255 } case .Up: for k in 0..=row_stride_in { - dest[k] = (src[k] + up[k]) & 255; + dest[k] = (src[k] + up[k]) & 255 } case .Average: for i in 0..=channels { - avg := up[i] >> 1; - dest[i] = (src[i] + avg) & 255; + avg := up[i] >> 1 + dest[i] = (src[i] + avg) & 255 } for k in 0..=nk { - avg := u8((u16(up[channels+k]) + u16(dest[k])) >> 1); - dest[channels+k] = (src[channels+k] + avg) & 255; + avg := u8((u16(up[channels+k]) + u16(dest[k])) >> 1) + dest[channels+k] = (src[channels+k] + avg) & 255 } case .Paeth: for i in 0..=channels { - paeth := filter_paeth(0, up[i], 0); - dest[i] = (src[i] + paeth) & 255; + paeth := filter_paeth(0, up[i], 0) + dest[i] = (src[i] + paeth) & 255 } for k in 0..=nk { - paeth := filter_paeth(dest[k], up[channels+k], up[k]); - dest[channels+k] = (src[channels+k] + paeth) & 255; + paeth := filter_paeth(dest[k], up[channels+k], up[k]) + dest[channels+k] = (src[channels+k] + paeth) & 255 } case: - return false; + return false } - src = src[row_stride_in:]; - up = dest; - dest = dest[row_stride_in:]; + src = src[row_stride_in:] + up = dest + dest = dest[row_stride_in:] } // Let's expand the bits - dest = orig_dest; + dest = orig_dest // Don't rescale the bits if we're a paletted image. - dsc := depth_scale_table; - scale := rescale ? dsc[depth] : 1; + dsc := depth_scale_table + scale := rescale ? dsc[depth] : 1 /* For sBIT support we should probably set scale to 1 and mask the significant bits. @@ -1377,163 +1377,163 @@ defilter_less_than_8 :: proc(params: ^Filter_Params) -> (ok: bool) #no_bounds_ch */ for j := 0; j < height; j += 1 { - src = dest[row_offset:]; + src = dest[row_offset:] switch depth { case 4: - k := row_stride_out; + k := row_stride_out for ; k >= 2; k -= 2 { - c := src[0]; - dest[0] = scale * (c >> 4); - dest[1] = scale * (c & 15); - dest = dest[2:]; src = src[1:]; + c := src[0] + dest[0] = scale * (c >> 4) + dest[1] = scale * (c & 15) + dest = dest[2:]; src = src[1:] } if k > 0 { - c := src[0]; - dest[0] = scale * (c >> 4); - dest = dest[1:]; + c := src[0] + dest[0] = scale * (c >> 4) + dest = dest[1:] } case 2: - k := row_stride_out; + k := row_stride_out for ; k >= 4; k -= 4 { - c := src[0]; - dest[0] = scale * ((c >> 6) ); - dest[1] = scale * ((c >> 4) & 3); - dest[2] = scale * ((c >> 2) & 3); - dest[3] = scale * ((c ) & 3); - dest = dest[4:]; src = src[1:]; + c := src[0] + dest[0] = scale * ((c >> 6) ) + dest[1] = scale * ((c >> 4) & 3) + dest[2] = scale * ((c >> 2) & 3) + dest[3] = scale * ((c ) & 3) + dest = dest[4:]; src = src[1:] } if k > 0 { - c := src[0]; - dest[0] = scale * ((c >> 6) ); + c := src[0] + dest[0] = scale * ((c >> 6) ) if k > 1 { - dest[1] = scale * ((c >> 4) & 3); + dest[1] = scale * ((c >> 4) & 3) } if k > 2 { - dest[2] = scale * ((c >> 2) & 3); + dest[2] = scale * ((c >> 2) & 3) } - dest = dest[k:]; + dest = dest[k:] } case 1: - k := row_stride_out; + k := row_stride_out for ; k >= 8; k -= 8 { - c := src[0]; - dest[0] = scale * ((c >> 7) ); - dest[1] = scale * ((c >> 6) & 1); - dest[2] = scale * ((c >> 5) & 1); - dest[3] = scale * ((c >> 4) & 1); - dest[4] = scale * ((c >> 3) & 1); - dest[5] = scale * ((c >> 2) & 1); - dest[6] = scale * ((c >> 1) & 1); - dest[7] = scale * ((c ) & 1); - dest = dest[8:]; src = src[1:]; + c := src[0] + dest[0] = scale * ((c >> 7) ) + dest[1] = scale * ((c >> 6) & 1) + dest[2] = scale * ((c >> 5) & 1) + dest[3] = scale * ((c >> 4) & 1) + dest[4] = scale * ((c >> 3) & 1) + dest[5] = scale * ((c >> 2) & 1) + dest[6] = scale * ((c >> 1) & 1) + dest[7] = scale * ((c ) & 1) + dest = dest[8:]; src = src[1:] } if k > 0 { - c := src[0]; - dest[0] = scale * ((c >> 7) ); + c := src[0] + dest[0] = scale * ((c >> 7) ) if k > 1 { - dest[1] = scale * ((c >> 6) & 1); + dest[1] = scale * ((c >> 6) & 1) } if k > 2 { - dest[2] = scale * ((c >> 5) & 1); + dest[2] = scale * ((c >> 5) & 1) } if k > 3 { - dest[3] = scale * ((c >> 4) & 1); + dest[3] = scale * ((c >> 4) & 1) } if k > 4 { - dest[4] = scale * ((c >> 3) & 1); + dest[4] = scale * ((c >> 3) & 1) } if k > 5 { - dest[5] = scale * ((c >> 2) & 1); + dest[5] = scale * ((c >> 2) & 1) } if k > 6 { - dest[6] = scale * ((c >> 1) & 1); + dest[6] = scale * ((c >> 1) & 1) } - dest = dest[k:]; + dest = dest[k:] } } } - return; + return } // @(optimization_mode="speed") defilter_16 :: proc(params: ^Filter_Params) -> (ok: bool) { - using params; - ok = true; + using params + ok = true - stride := channels * 2; - row_stride := width * stride; + stride := channels * 2 + row_stride := width * stride // TODO: See about doing a Duff's #unroll where practicable // Apron so we don't need to special case first rows. - up := make([]u8, row_stride, context.temp_allocator); + up := make([]u8, row_stride, context.temp_allocator) for y := 0; y < height; y += 1 { - nk := row_stride - stride; + nk := row_stride - stride - filter := Row_Filter(src[0]); src = src[1:]; + filter := Row_Filter(src[0]); src = src[1:] switch filter { case .None: - copy(dest, src[:row_stride]); + copy(dest, src[:row_stride]) case .Sub: for i := 0; i < stride; i += 1 { - dest[i] = src[i]; + dest[i] = src[i] } for k := 0; k < nk; k += 1 { - dest[stride+k] = (src[stride+k] + dest[k]) & 255; + dest[stride+k] = (src[stride+k] + dest[k]) & 255 } case .Up: for k := 0; k < row_stride; k += 1 { - dest[k] = (src[k] + up[k]) & 255; + dest[k] = (src[k] + up[k]) & 255 } case .Average: for i := 0; i < stride; i += 1 { - avg := up[i] >> 1; - dest[i] = (src[i] + avg) & 255; + avg := up[i] >> 1 + dest[i] = (src[i] + avg) & 255 } for k := 0; k < nk; k += 1 { - avg := u8((u16(up[stride+k]) + u16(dest[k])) >> 1); - dest[stride+k] = (src[stride+k] + avg) & 255; + avg := u8((u16(up[stride+k]) + u16(dest[k])) >> 1) + dest[stride+k] = (src[stride+k] + avg) & 255 } case .Paeth: for i := 0; i < stride; i += 1 { - paeth := filter_paeth(0, up[i], 0); - dest[i] = (src[i] + paeth) & 255; + paeth := filter_paeth(0, up[i], 0) + dest[i] = (src[i] + paeth) & 255 } for k := 0; k < nk; k += 1 { - paeth := filter_paeth(dest[k], up[stride+k], up[k]); - dest[stride+k] = (src[stride+k] + paeth) & 255; + paeth := filter_paeth(dest[k], up[stride+k], up[k]) + dest[stride+k] = (src[stride+k] + paeth) & 255 } case: - return false; + return false } - src = src[row_stride:]; - up = dest; - dest = dest[row_stride:]; + src = src[row_stride:] + up = dest + dest = dest[row_stride:] } - return; + return } defilter :: proc(img: ^Image, filter_bytes: ^bytes.Buffer, header: ^IHDR, options: Options) -> (err: compress.Error) { - input := bytes.buffer_to_bytes(filter_bytes); - width := int(header.width); - height := int(header.height); - channels := int(img.channels); - depth := int(header.bit_depth); - rescale := .Color not_in header.color_type; + input := bytes.buffer_to_bytes(filter_bytes) + width := int(header.width) + height := int(header.height) + channels := int(img.channels) + depth := int(header.bit_depth) + rescale := .Color not_in header.color_type - bytes_per_channel := depth == 16 ? 2 : 1; + bytes_per_channel := depth == 16 ? 2 : 1 - num_bytes := compute_buffer_size(width, height, channels, depth == 16 ? 16 : 8); - resize(&img.pixels.buf, num_bytes); + num_bytes := compute_buffer_size(width, height, channels, depth == 16 ? 16 : 8) + resize(&img.pixels.buf, num_bytes) - filter_ok: bool; + filter_ok: bool if header.interlace_method != .Adam7 { params := Filter_Params{ @@ -1544,19 +1544,19 @@ defilter :: proc(img: ^Image, filter_bytes: ^bytes.Buffer, header: ^IHDR, option depth = depth, rescale = rescale, dest = img.pixels.buf[:], - }; + } if depth == 8 { - filter_ok = defilter_8(¶ms); + filter_ok = defilter_8(¶ms) } else if depth < 8 { - filter_ok = defilter_less_than_8(¶ms); - img.depth = 8; + filter_ok = defilter_less_than_8(¶ms) + img.depth = 8 } else { - filter_ok = defilter_16(¶ms); + filter_ok = defilter_16(¶ms) } if !filter_ok { // Caller will destroy buffer for us. - return E_PNG.Unknown_Filter_Method; + return E_PNG.Unknown_Filter_Method } } else { /* @@ -1565,13 +1565,13 @@ defilter :: proc(img: ^Image, filter_bytes: ^bytes.Buffer, header: ^IHDR, option */ for p := 0; p < 7; p += 1 { - i,j,x,y: int; - x = (width - ADAM7_X_ORIG[p] + ADAM7_X_SPACING[p] - 1) / ADAM7_X_SPACING[p]; - y = (height - ADAM7_Y_ORIG[p] + ADAM7_Y_SPACING[p] - 1) / ADAM7_Y_SPACING[p]; + i,j,x,y: int + x = (width - ADAM7_X_ORIG[p] + ADAM7_X_SPACING[p] - 1) / ADAM7_X_SPACING[p] + y = (height - ADAM7_Y_ORIG[p] + ADAM7_Y_SPACING[p] - 1) / ADAM7_Y_SPACING[p] if x > 0 && y > 0 { - temp: bytes.Buffer; - temp_len := compute_buffer_size(x, y, channels, depth == 16 ? 16 : 8); - resize(&temp.buf, temp_len); + temp: bytes.Buffer + temp_len := compute_buffer_size(x, y, channels, depth == 16 ? 16 : 8) + resize(&temp.buf, temp_len) params := Filter_Params{ src = input, @@ -1581,55 +1581,55 @@ defilter :: proc(img: ^Image, filter_bytes: ^bytes.Buffer, header: ^IHDR, option depth = depth, rescale = rescale, dest = temp.buf[:], - }; + } if depth == 8 { - filter_ok = defilter_8(¶ms); + filter_ok = defilter_8(¶ms) } else if depth < 8 { - filter_ok = defilter_less_than_8(¶ms); - img.depth = 8; + filter_ok = defilter_less_than_8(¶ms) + img.depth = 8 } else { - filter_ok = defilter_16(¶ms); + filter_ok = defilter_16(¶ms) } if !filter_ok { // Caller will destroy buffer for us. - return E_PNG.Unknown_Filter_Method; + return E_PNG.Unknown_Filter_Method } - t := temp.buf[:]; + t := temp.buf[:] for j = 0; j < y; j += 1 { for i = 0; i < x; i += 1 { - out_y := j * ADAM7_Y_SPACING[p] + ADAM7_Y_ORIG[p]; - out_x := i * ADAM7_X_SPACING[p] + ADAM7_X_ORIG[p]; + out_y := j * ADAM7_Y_SPACING[p] + ADAM7_Y_ORIG[p] + out_x := i * ADAM7_X_SPACING[p] + ADAM7_X_ORIG[p] - out_off := out_y * width * channels * bytes_per_channel; - out_off += out_x * channels * bytes_per_channel; + out_off := out_y * width * channels * bytes_per_channel + out_off += out_x * channels * bytes_per_channel for z := 0; z < channels * bytes_per_channel; z += 1 { - img.pixels.buf[out_off + z] = t[z]; + img.pixels.buf[out_off + z] = t[z] } - t = t[channels * bytes_per_channel:]; + t = t[channels * bytes_per_channel:] } } - bytes.buffer_destroy(&temp); - input_stride := compute_buffer_size(x, y, channels, depth, 1); - input = input[input_stride:]; + bytes.buffer_destroy(&temp) + input_stride := compute_buffer_size(x, y, channels, depth, 1) + input = input[input_stride:] } } } when ODIN_ENDIAN == "little" { if img.depth == 16 { // The pixel components are in Big Endian. Let's byteswap. - input := mem.slice_data_cast([]u16be, img.pixels.buf[:]); - output := mem.slice_data_cast([]u16 , img.pixels.buf[:]); + input := mem.slice_data_cast([]u16be, img.pixels.buf[:]) + output := mem.slice_data_cast([]u16 , img.pixels.buf[:]) #no_bounds_check for v, i in input { - output[i] = u16(v); + output[i] = u16(v) } } } - return nil; + return nil } -load :: proc{load_from_file, load_from_slice, load_from_context}; +load :: proc{load_from_file, load_from_slice, load_from_context} diff --git a/core/io/conv.odin b/core/io/conv.odin index f47e61a10..af20866f2 100644 --- a/core/io/conv.odin +++ b/core/io/conv.odin @@ -1,194 +1,194 @@ package io to_reader :: proc(s: Stream) -> (r: Reader, ok: bool = true) { - r.stream = s; + r.stream = s if s.stream_vtable == nil || s.impl_read == nil { - ok = false; + ok = false } - return; + return } to_writer :: proc(s: Stream) -> (w: Writer, ok: bool = true) { - w.stream = s; + w.stream = s if s.stream_vtable == nil || s.impl_write == nil { - ok = false; + ok = false } - return; + return } to_closer :: proc(s: Stream) -> (c: Closer, ok: bool = true) { - c.stream = s; + c.stream = s if s.stream_vtable == nil || s.impl_close == nil { - ok = false; + ok = false } - return; + return } to_flusher :: proc(s: Stream) -> (f: Flusher, ok: bool = true) { - f.stream = s; + f.stream = s if s.stream_vtable == nil || s.impl_flush == nil { - ok = false; + ok = false } - return; + return } to_seeker :: proc(s: Stream) -> (seeker: Seeker, ok: bool = true) { - seeker.stream = s; + seeker.stream = s if s.stream_vtable == nil || s.impl_seek == nil { - ok = false; + ok = false } - return; + return } to_read_writer :: proc(s: Stream) -> (r: Read_Writer, ok: bool = true) { - r.stream = s; + r.stream = s if s.stream_vtable == nil || s.impl_read == nil || s.impl_write == nil { - ok = false; + ok = false } - return; + return } to_read_closer :: proc(s: Stream) -> (r: Read_Closer, ok: bool = true) { - r.stream = s; + r.stream = s if s.stream_vtable == nil || s.impl_read == nil || s.impl_close == nil { - ok = false; + ok = false } - return; + return } to_read_write_closer :: proc(s: Stream) -> (r: Read_Write_Closer, ok: bool = true) { - r.stream = s; + r.stream = s if s.stream_vtable == nil || s.impl_read == nil || s.impl_write == nil || s.impl_close == nil { - ok = false; + ok = false } - return; + return } to_read_write_seeker :: proc(s: Stream) -> (r: Read_Write_Seeker, ok: bool = true) { - r.stream = s; + r.stream = s if s.stream_vtable == nil || s.impl_read == nil || s.impl_write == nil || s.impl_seek == nil { - ok = false; + ok = false } - return; + return } to_write_flusher :: proc(s: Stream) -> (w: Write_Flusher, ok: bool = true) { - w.stream = s; + w.stream = s if s.stream_vtable == nil || s.impl_write == nil || s.impl_flush == nil { - ok = false; + ok = false } - return; + return } to_write_flush_closer :: proc(s: Stream) -> (w: Write_Flush_Closer, ok: bool = true) { - w.stream = s; + w.stream = s if s.stream_vtable == nil || s.impl_write == nil || s.impl_flush == nil || s.impl_close == nil { - ok = false; + ok = false } - return; + return } to_reader_at :: proc(s: Stream) -> (r: Reader_At, ok: bool = true) { - r.stream = s; + r.stream = s if s.stream_vtable == nil || s.impl_read_at == nil { - ok = false; + ok = false } - return; + return } to_writer_at :: proc(s: Stream) -> (w: Writer_At, ok: bool = true) { - w.stream = s; + w.stream = s if s.stream_vtable == nil || s.impl_write_at == nil { - ok = false; + ok = false } - return; + return } to_reader_from :: proc(s: Stream) -> (r: Reader_From, ok: bool = true) { - r.stream = s; + r.stream = s if s.stream_vtable == nil || s.impl_read_from == nil { - ok = false; + ok = false } - return; + return } to_writer_to :: proc(s: Stream) -> (w: Writer_To, ok: bool = true) { - w.stream = s; + w.stream = s if s.stream_vtable == nil || s.impl_write_to == nil { - ok = false; + ok = false } - return; + return } to_write_closer :: proc(s: Stream) -> (w: Write_Closer, ok: bool = true) { - w.stream = s; + w.stream = s if s.stream_vtable == nil || s.impl_write == nil || s.impl_close == nil { - ok = false; + ok = false } - return; + return } to_write_seeker :: proc(s: Stream) -> (w: Write_Seeker, ok: bool = true) { - w.stream = s; + w.stream = s if s.stream_vtable == nil || s.impl_write == nil || s.impl_seek == nil { - ok = false; + ok = false } - return; + return } to_byte_reader :: proc(s: Stream) -> (b: Byte_Reader, ok: bool = true) { - b.stream = s; + b.stream = s if s.stream_vtable == nil || s.impl_read_byte == nil { - ok = false; + ok = false if s.stream_vtable != nil && s.impl_read != nil { - ok = true; + ok = true } } - return; + return } to_byte_scanner :: proc(s: Stream) -> (b: Byte_Scanner, ok: bool = true) { - b.stream = s; + b.stream = s if s.stream_vtable != nil { if s.impl_unread_byte == nil { - ok = false; - return; + ok = false + return } if s.impl_read_byte != nil { - ok = true; + ok = true } else if s.impl_read != nil { - ok = true; + ok = true } else { - ok = false; + ok = false } } - return; + return } to_byte_writer :: proc(s: Stream) -> (b: Byte_Writer, ok: bool = true) { - b.stream = s; + b.stream = s if s.stream_vtable == nil || s.impl_write_byte == nil { - ok = false; + ok = false if s.stream_vtable != nil && s.impl_write != nil { - ok = true; + ok = true } } - return; + return } to_rune_reader :: proc(s: Stream) -> (r: Rune_Reader, ok: bool = true) { - r.stream = s; + r.stream = s if s.stream_vtable == nil || s.impl_read_rune == nil { - ok = false; + ok = false if s.stream_vtable != nil && s.impl_read != nil { - ok = true; + ok = true } } - return; + return } to_rune_scanner :: proc(s: Stream) -> (r: Rune_Scanner, ok: bool = true) { - r.stream = s; + r.stream = s if s.stream_vtable != nil { if s.impl_unread_rune == nil { - ok = false; - return; + ok = false + return } if s.impl_read_rune != nil { - ok = true; + ok = true } else if s.impl_read != nil { - ok = true; + ok = true } else { - ok = false; + ok = false } } else { - ok = false; + ok = false } - return; + return } diff --git a/core/io/io.odin b/core/io/io.odin index e7a1a4b5c..ec95c91d3 100644 --- a/core/io/io.odin +++ b/core/io/io.odin @@ -50,23 +50,23 @@ Error :: enum i32 { Empty = -1, } -Close_Proc :: proc(using s: Stream) -> Error; -Flush_Proc :: proc(using s: Stream) -> Error; -Seek_Proc :: proc(using s: Stream, offset: i64, whence: Seek_From) -> (n: i64, err: Error); -Size_Proc :: proc(using s: Stream) -> i64; -Read_Proc :: proc(using s: Stream, p: []byte) -> (n: int, err: Error); -Read_At_Proc :: proc(using s: Stream, p: []byte, off: i64) -> (n: int, err: Error); -Read_From_Proc :: proc(using s: Stream, r: Reader) -> (n: i64, err: Error); -Read_Byte_Proc :: proc(using s: Stream) -> (byte, Error); -Read_Rune_Proc :: proc(using s: Stream) -> (ch: rune, size: int, err: Error); -Unread_Byte_Proc :: proc(using s: Stream) -> Error; -Unread_Rune_Proc :: proc(using s: Stream) -> Error; -Write_Proc :: proc(using s: Stream, p: []byte) -> (n: int, err: Error); -Write_At_Proc :: proc(using s: Stream, p: []byte, off: i64) -> (n: int, err: Error); -Write_To_Proc :: proc(using s: Stream, w: Writer) -> (n: i64, err: Error); -Write_Byte_Proc :: proc(using s: Stream, c: byte) -> Error; -Write_Rune_Proc :: proc(using s: Stream, r: rune) -> (size: int, err: Error); -Destroy_Proc :: proc(using s: Stream) -> Error; +Close_Proc :: proc(using s: Stream) -> Error +Flush_Proc :: proc(using s: Stream) -> Error +Seek_Proc :: proc(using s: Stream, offset: i64, whence: Seek_From) -> (n: i64, err: Error) +Size_Proc :: proc(using s: Stream) -> i64 +Read_Proc :: proc(using s: Stream, p: []byte) -> (n: int, err: Error) +Read_At_Proc :: proc(using s: Stream, p: []byte, off: i64) -> (n: int, err: Error) +Read_From_Proc :: proc(using s: Stream, r: Reader) -> (n: i64, err: Error) +Read_Byte_Proc :: proc(using s: Stream) -> (byte, Error) +Read_Rune_Proc :: proc(using s: Stream) -> (ch: rune, size: int, err: Error) +Unread_Byte_Proc :: proc(using s: Stream) -> Error +Unread_Rune_Proc :: proc(using s: Stream) -> Error +Write_Proc :: proc(using s: Stream, p: []byte) -> (n: int, err: Error) +Write_At_Proc :: proc(using s: Stream, p: []byte, off: i64) -> (n: int, err: Error) +Write_To_Proc :: proc(using s: Stream, w: Writer) -> (n: i64, err: Error) +Write_Byte_Proc :: proc(using s: Stream, c: byte) -> Error +Write_Rune_Proc :: proc(using s: Stream, r: rune) -> (size: int, err: Error) +Destroy_Proc :: proc(using s: Stream) -> Error Stream :: struct { @@ -99,109 +99,109 @@ Stream_VTable :: struct { } -Reader :: struct {using stream: Stream}; -Writer :: struct {using stream: Stream}; -Closer :: struct {using stream: Stream}; -Flusher :: struct {using stream: Stream}; -Seeker :: struct {using stream: Stream}; +Reader :: struct {using stream: Stream} +Writer :: struct {using stream: Stream} +Closer :: struct {using stream: Stream} +Flusher :: struct {using stream: Stream} +Seeker :: struct {using stream: Stream} -Read_Writer :: struct {using stream: Stream}; -Read_Closer :: struct {using stream: Stream}; -Read_Write_Closer :: struct {using stream: Stream}; -Read_Write_Seeker :: struct {using stream: Stream}; +Read_Writer :: struct {using stream: Stream} +Read_Closer :: struct {using stream: Stream} +Read_Write_Closer :: struct {using stream: Stream} +Read_Write_Seeker :: struct {using stream: Stream} -Write_Closer :: struct {using stream: Stream}; -Write_Seeker :: struct {using stream: Stream}; -Write_Flusher :: struct {using stream: Stream}; -Write_Flush_Closer :: struct {using stream: Stream}; +Write_Closer :: struct {using stream: Stream} +Write_Seeker :: struct {using stream: Stream} +Write_Flusher :: struct {using stream: Stream} +Write_Flush_Closer :: struct {using stream: Stream} -Reader_At :: struct {using stream: Stream}; -Writer_At :: struct {using stream: Stream}; -Reader_From :: struct {using stream: Stream}; -Writer_To :: struct {using stream: Stream}; +Reader_At :: struct {using stream: Stream} +Writer_At :: struct {using stream: Stream} +Reader_From :: struct {using stream: Stream} +Writer_To :: struct {using stream: Stream} -Byte_Reader :: struct {using stream: Stream}; -Byte_Scanner :: struct {using stream: Stream}; -Byte_Writer :: struct {using stream: Stream}; +Byte_Reader :: struct {using stream: Stream} +Byte_Scanner :: struct {using stream: Stream} +Byte_Writer :: struct {using stream: Stream} -Rune_Reader :: struct {using stream: Stream}; -Rune_Scanner :: struct {using stream: Stream}; +Rune_Reader :: struct {using stream: Stream} +Rune_Scanner :: struct {using stream: Stream} destroy :: proc(s: Stream) -> Error { - close_err := close({s}); + close_err := close({s}) if s.stream_vtable != nil && s.impl_destroy != nil { - return s->impl_destroy(); + return s->impl_destroy() } if close_err != .None { - return close_err; + return close_err } - return .Empty; + return .Empty } read :: proc(s: Reader, p: []byte) -> (n: int, err: Error) { if s.stream_vtable != nil && s.impl_read != nil { - return s->impl_read(p); + return s->impl_read(p) } - return 0, .Empty; + return 0, .Empty } write :: proc(s: Writer, p: []byte) -> (n: int, err: Error) { if s.stream_vtable != nil && s.impl_write != nil { - return s->impl_write(p); + return s->impl_write(p) } - return 0, .Empty; + return 0, .Empty } seek :: proc(s: Seeker, offset: i64, whence: Seek_From) -> (n: i64, err: Error) { if s.stream_vtable != nil && s.impl_seek != nil { - return s->impl_seek(offset, whence); + return s->impl_seek(offset, whence) } - return 0, .Empty; + return 0, .Empty } close :: proc(s: Closer) -> Error { if s.stream_vtable != nil && s.impl_close != nil { - return s->impl_close(); + return s->impl_close() } // Instead of .Empty, .None is fine in this case - return .None; + return .None } flush :: proc(s: Flusher) -> Error { if s.stream_vtable != nil && s.impl_flush != nil { - return s->impl_flush(); + return s->impl_flush() } // Instead of .Empty, .None is fine in this case - return .None; + return .None } size :: proc(s: Stream) -> i64 { if s.stream_vtable == nil { - return 0; + return 0 } if s.impl_size != nil { - return s->impl_size(); + return s->impl_size() } if s.impl_seek == nil { - return 0; + return 0 } - curr, end: i64; - err: Error; + curr, end: i64 + err: Error if curr, err = s->impl_seek(0, .Current); err != nil { - return 0; + return 0 } if end, err = s->impl_seek(0, .End); err != nil { - return 0; + return 0 } if _, err = s->impl_seek(curr, .Start); err != nil { - return 0; + return 0 } - return end; + return end } @@ -209,225 +209,225 @@ size :: proc(s: Stream) -> i64 { read_at :: proc(r: Reader_At, p: []byte, offset: i64) -> (n: int, err: Error) { if r.stream_vtable == nil { - return 0, .Empty; + return 0, .Empty } if r.impl_read_at != nil { - return r->impl_read_at(p, offset); + return r->impl_read_at(p, offset) } if r.impl_seek == nil || r.impl_read == nil { - return 0, .Empty; + return 0, .Empty } - curr_offset: i64; - curr_offset, err = r->impl_seek(offset, .Current); + curr_offset: i64 + curr_offset, err = r->impl_seek(offset, .Current) if err != nil { - return 0, err; + return 0, err } - n, err = r->impl_read(p); - _, err1 := r->impl_seek(curr_offset, .Start); + n, err = r->impl_read(p) + _, err1 := r->impl_seek(curr_offset, .Start) if err1 != nil && err == nil { - err = err1; + err = err1 } - return; + return } write_at :: proc(w: Writer_At, p: []byte, offset: i64) -> (n: int, err: Error) { if w.stream_vtable == nil { - return 0, .Empty; + return 0, .Empty } if w.impl_write_at != nil { - return w->impl_write_at(p, offset); + return w->impl_write_at(p, offset) } if w.impl_seek == nil || w.impl_write == nil { - return 0, .Empty; + return 0, .Empty } - curr_offset: i64; - curr_offset, err = w->impl_seek(offset, .Current); + curr_offset: i64 + curr_offset, err = w->impl_seek(offset, .Current) if err != nil { - return 0, err; + return 0, err } - n, err = w->impl_write(p); - _, err1 := w->impl_seek(curr_offset, .Start); + n, err = w->impl_write(p) + _, err1 := w->impl_seek(curr_offset, .Start) if err1 != nil && err == nil { - err = err1; + err = err1 } - return; + return } write_to :: proc(r: Writer_To, w: Writer) -> (n: i64, err: Error) { if r.stream_vtable == nil || w.stream_vtable == nil { - return 0, .Empty; + return 0, .Empty } if r.impl_write_to != nil { - return r->impl_write_to(w); + return r->impl_write_to(w) } - return 0, .Empty; + return 0, .Empty } read_from :: proc(w: Reader_From, r: Reader) -> (n: i64, err: Error) { if r.stream_vtable == nil || w.stream_vtable == nil { - return 0, .Empty; + return 0, .Empty } if r.impl_read_from != nil { - return w->impl_read_from(r); + return w->impl_read_from(r) } - return 0, .Empty; + return 0, .Empty } read_byte :: proc(r: Byte_Reader) -> (byte, Error) { if r.stream_vtable == nil { - return 0, .Empty; + return 0, .Empty } if r.impl_read_byte != nil { - return r->impl_read_byte(); + return r->impl_read_byte() } if r.impl_read == nil { - return 0, .Empty; + return 0, .Empty } - b: [1]byte; - _, err := r->impl_read(b[:]); - return b[0], err; + b: [1]byte + _, err := r->impl_read(b[:]) + return b[0], err } write_byte :: proc{ write_byte_to_byte_writer, write_byte_to_writer, -}; +} write_byte_to_byte_writer :: proc(w: Byte_Writer, c: byte) -> Error { - return _write_byte(w, c); + return _write_byte(w, c) } write_byte_to_writer :: proc(w: Writer, c: byte) -> Error { - return _write_byte(auto_cast w, c); + return _write_byte(auto_cast w, c) } @(private) _write_byte :: proc(w: Byte_Writer, c: byte) -> Error { if w.stream_vtable == nil { - return .Empty; + return .Empty } if w.impl_write_byte != nil { - return w->impl_write_byte(c); + return w->impl_write_byte(c) } if w.impl_write == nil { - return .Empty; + return .Empty } - b := [1]byte{c}; - _, err := w->impl_write(b[:]); - return err; + b := [1]byte{c} + _, err := w->impl_write(b[:]) + return err } read_rune :: proc(br: Rune_Reader) -> (ch: rune, size: int, err: Error) { if br.stream_vtable == nil { - return 0, 0, .Empty; + return 0, 0, .Empty } if br.impl_read_rune != nil { - return br->impl_read_rune(); + return br->impl_read_rune() } if br.impl_read == nil { - return 0, 0, .Empty; + return 0, 0, .Empty } - b: [utf8.UTF_MAX]byte; - _, err = br->impl_read(b[:1]); + b: [utf8.UTF_MAX]byte + _, err = br->impl_read(b[:1]) - s0 := b[0]; - ch = rune(s0); - size = 1; + s0 := b[0] + ch = rune(s0) + size = 1 if err != nil { - return; + return } if ch < utf8.RUNE_SELF { - return; + return } - x := utf8.accept_sizes[s0]; + x := utf8.accept_sizes[s0] if x >= 0xf0 { - mask := rune(x) << 31 >> 31; - ch = ch &~ mask | utf8.RUNE_ERROR&mask; - return; + mask := rune(x) << 31 >> 31 + ch = ch &~ mask | utf8.RUNE_ERROR&mask + return } - sz := int(x&7); - n: int; - n, err = br->impl_read(b[1:sz]); + sz := int(x&7) + n: int + n, err = br->impl_read(b[1:sz]) if err != nil || n+1 < sz { - ch = utf8.RUNE_ERROR; - return; + ch = utf8.RUNE_ERROR + return } - ch, size = utf8.decode_rune(b[:sz]); - return; + ch, size = utf8.decode_rune(b[:sz]) + return } unread_byte :: proc(s: Byte_Scanner) -> Error { if s.stream_vtable != nil && s.impl_unread_byte != nil { - return s->impl_unread_byte(); + return s->impl_unread_byte() } - return .Empty; + return .Empty } unread_rune :: proc(s: Rune_Scanner) -> Error { if s.stream_vtable != nil && s.impl_unread_rune != nil { - return s->impl_unread_rune(); + return s->impl_unread_rune() } - return .Empty; + return .Empty } write_string :: proc(s: Writer, str: string) -> (n: int, err: Error) { - return write(s, transmute([]byte)str); + return write(s, transmute([]byte)str) } write_rune :: proc(s: Writer, r: rune) -> (size: int, err: Error) { if s.stream_vtable != nil && s.impl_write_rune != nil { - return s->impl_write_rune(r); + return s->impl_write_rune(r) } if r < utf8.RUNE_SELF { - err = write_byte(s, byte(r)); + err = write_byte(s, byte(r)) if err == nil { - size = 1; + size = 1 } - return; + return } - buf, w := utf8.encode_rune(r); - return write(s, buf[:w]); + buf, w := utf8.encode_rune(r) + return write(s, buf[:w]) } read_full :: proc(r: Reader, buf: []byte) -> (n: int, err: Error) { - return read_at_least(r, buf, len(buf)); + return read_at_least(r, buf, len(buf)) } read_at_least :: proc(r: Reader, buf: []byte, min: int) -> (n: int, err: Error) { if len(buf) < min { - return 0, .Short_Buffer; + return 0, .Short_Buffer } for n < min && err == nil { - nn: int; - nn, err = read(r, buf[n:]); - n += n; + nn: int + nn, err = read(r, buf[n:]) + n += n } if n >= min { - err = nil; + err = nil } else if n > 0 && err == .EOF { - err = .Unexpected_EOF; + err = .Unexpected_EOF } - return; + return } // copy copies from src to dst till either EOF is reached on src or an error occurs // It returns the number of bytes copied and the first error that occurred whilst copying, if any. copy :: proc(dst: Writer, src: Reader) -> (written: i64, err: Error) { - return _copy_buffer(dst, src, nil); + return _copy_buffer(dst, src, nil) } // copy_buffer is the same as copy except that it stages through the provided buffer (if one is required) @@ -435,9 +435,9 @@ copy :: proc(dst: Writer, src: Reader) -> (written: i64, err: Error) { // If buf is `nil`, it is allocate through `intrinsics.alloca`; otherwise if it has zero length, it will panic copy_buffer :: proc(dst: Writer, src: Reader, buf: []byte) -> (written: i64, err: Error) { if buf != nil && len(buf) == 0 { - panic("empty buffer in io.copy_buffer"); + panic("empty buffer in io.copy_buffer") } - return _copy_buffer(dst, src, buf); + return _copy_buffer(dst, src, buf) } @@ -446,69 +446,69 @@ copy_buffer :: proc(dst: Writer, src: Reader, buf: []byte) -> (written: i64, err // It returns the number of bytes copied and the first error that occurred whilst copying, if any. // On return, written == n IFF err == nil copy_n :: proc(dst: Writer, src: Reader, n: i64) -> (written: i64, err: Error) { - nsrc := limited_reader_init(&Limited_Reader{}, src, n); - written, err = copy(dst, nsrc); + nsrc := limited_reader_init(&Limited_Reader{}, src, n) + written, err = copy(dst, nsrc) if written == n { - return n, nil; + return n, nil } if written < n && err == nil { // src stopped early and must have been an EOF - err = .EOF; + err = .EOF } - return; + return } @(private) _copy_buffer :: proc(dst: Writer, src: Reader, buf: []byte) -> (written: i64, err: Error) { if dst.stream_vtable == nil || src.stream_vtable == nil { - return 0, .Empty; + return 0, .Empty } if src.impl_write_to != nil { - return src->impl_write_to(dst); + return src->impl_write_to(dst) } if src.impl_read_from != nil { - return dst->impl_read_from(src); + return dst->impl_read_from(src) } - buf := buf; + buf := buf if buf == nil { - DEFAULT_SIZE :: 4 * 1024; - size := DEFAULT_SIZE; + DEFAULT_SIZE :: 4 * 1024 + size := DEFAULT_SIZE if src.stream_vtable == _limited_reader_vtable { - l := (^Limited_Reader)(src.stream_data); + l := (^Limited_Reader)(src.stream_data) if i64(size) > l.n { if l.n < 1 { - size = 1; + size = 1 } else { - size = int(l.n); + size = int(l.n) } } } // NOTE(bill): alloca is fine here - buf = transmute([]byte)runtime.Raw_Slice{intrinsics.alloca(size, 2*align_of(rawptr)), size}; + buf = transmute([]byte)runtime.Raw_Slice{intrinsics.alloca(size, 2*align_of(rawptr)), size} } for { - nr, er := read(src, buf); + nr, er := read(src, buf) if nr > 0 { - nw, ew := write(dst, buf[0:nr]); + nw, ew := write(dst, buf[0:nr]) if nw > 0 { - written += i64(nw); + written += i64(nw) } if ew != nil { - err = ew; - break; + err = ew + break } if nr != nw { - err = .Short_Write; - break; + err = .Short_Write + break } } if er != nil { if er != .EOF { - err = er; + err = er } - break; + break } } - return; + return } diff --git a/core/io/multi.odin b/core/io/multi.odin index 14170ea8b..64c533e37 100644 --- a/core/io/multi.odin +++ b/core/io/multi.odin @@ -7,46 +7,46 @@ Multi_Reader :: struct { @(private) _multi_reader_vtable := &Stream_VTable{ impl_read = proc(s: Stream, p: []byte) -> (n: int, err: Error) { - mr := (^Multi_Reader)(s.stream_data); + mr := (^Multi_Reader)(s.stream_data) for len(mr.readers) > 0 { - r := mr.readers[0]; - n, err = read(r, p); + r := mr.readers[0] + n, err = read(r, p) if err == .EOF { - ordered_remove(&mr.readers, 0); + ordered_remove(&mr.readers, 0) } if n > 0 || err != .EOF { if err == .EOF && len(mr.readers) > 0 { // Don't return EOF yet, more readers remain - err = nil; + err = nil } - return; + return } } - return 0, .EOF; + return 0, .EOF }, -}; +} multi_reader_init :: proc(mr: ^Multi_Reader, readers: ..Reader, allocator := context.allocator) -> (r: Reader) { - all_readers := make([dynamic]Reader, 0, len(readers), allocator); + all_readers := make([dynamic]Reader, 0, len(readers), allocator) for w in readers { if w.stream_vtable == _multi_reader_vtable { - other := (^Multi_Reader)(w.stream_data); - append(&all_readers, ..other.readers[:]); + other := (^Multi_Reader)(w.stream_data) + append(&all_readers, ..other.readers[:]) } else { - append(&all_readers, w); + append(&all_readers, w) } } - mr.readers = all_readers; + mr.readers = all_readers - r.stream_vtable = _multi_reader_vtable; - r.stream_data = mr; - return; + r.stream_vtable = _multi_reader_vtable + r.stream_data = mr + return } multi_reader_destroy :: proc(mr: ^Multi_Reader) { - delete(mr.readers); + delete(mr.readers) } @@ -57,39 +57,39 @@ Multi_Writer :: struct { @(private) _multi_writer_vtable := &Stream_VTable{ impl_write = proc(s: Stream, p: []byte) -> (n: int, err: Error) { - mw := (^Multi_Writer)(s.stream_data); + mw := (^Multi_Writer)(s.stream_data) for w in mw.writers { - n, err = write(w, p); + n, err = write(w, p) if err != nil { - return; + return } if n != len(p) { - err = .Short_Write; - return; + err = .Short_Write + return } } - return len(p), nil; + return len(p), nil }, -}; +} multi_writer_init :: proc(mw: ^Multi_Writer, writers: ..Writer, allocator := context.allocator) -> (out: Writer) { - mw.writers = make([dynamic]Writer, 0, len(writers), allocator); + mw.writers = make([dynamic]Writer, 0, len(writers), allocator) for w in writers { if w.stream_vtable == _multi_writer_vtable { - other := (^Multi_Writer)(w.stream_data); - append(&mw.writers, ..other.writers[:]); + other := (^Multi_Writer)(w.stream_data) + append(&mw.writers, ..other.writers[:]) } else { - append(&mw.writers, w); + append(&mw.writers, w) } } - out.stream_vtable = _multi_writer_vtable; - out.stream_data = mw; - return; + out.stream_vtable = _multi_writer_vtable + out.stream_data = mw + return } multi_writer_destroy :: proc(mw: ^Multi_Writer) { - delete(mw.writers); + delete(mw.writers) } diff --git a/core/io/util.odin b/core/io/util.odin index 38243e953..afb301124 100644 --- a/core/io/util.odin +++ b/core/io/util.odin @@ -5,37 +5,37 @@ import "core:strconv" read_ptr :: proc(r: Reader, p: rawptr, byte_size: int) -> (n: int, err: Error) { - return read(r, mem.byte_slice(p, byte_size)); + return read(r, mem.byte_slice(p, byte_size)) } write_ptr :: proc(w: Writer, p: rawptr, byte_size: int) -> (n: int, err: Error) { - return write(w, mem.byte_slice(p, byte_size)); + return write(w, mem.byte_slice(p, byte_size)) } read_ptr_at :: proc(r: Reader_At, p: rawptr, byte_size: int, offset: i64) -> (n: int, err: Error) { - return read_at(r, mem.byte_slice(p, byte_size), offset); + return read_at(r, mem.byte_slice(p, byte_size), offset) } write_ptr_at :: proc(w: Writer_At, p: rawptr, byte_size: int, offset: i64) -> (n: int, err: Error) { - return write_at(w, mem.byte_slice(p, byte_size), offset); + return write_at(w, mem.byte_slice(p, byte_size), offset) } write_u64 :: proc(w: Writer, i: u64, base: int = 10) -> (n: int, err: Error) { - buf: [32]byte; - s := strconv.append_bits(buf[:], i, base, false, 64, strconv.digits, nil); - return write_string(w, s); + buf: [32]byte + s := strconv.append_bits(buf[:], i, base, false, 64, strconv.digits, nil) + return write_string(w, s) } write_i64 :: proc(w: Writer, i: i64, base: int = 10) -> (n: int, err: Error) { - buf: [32]byte; - s := strconv.append_bits(buf[:], u64(i), base, true, 64, strconv.digits, nil); - return write_string(w, s); + buf: [32]byte + s := strconv.append_bits(buf[:], u64(i), base, true, 64, strconv.digits, nil) + return write_string(w, s) } write_uint :: proc(w: Writer, i: uint, base: int = 10) -> (n: int, err: Error) { - return write_u64(w, u64(i), base); + return write_u64(w, u64(i), base) } write_int :: proc(w: Writer, i: int, base: int = 10) -> (n: int, err: Error) { - return write_i64(w, i64(i), base); + return write_i64(w, i64(i), base) } Tee_Reader :: struct { @@ -46,16 +46,16 @@ Tee_Reader :: struct { @(private) _tee_reader_vtable := &Stream_VTable{ impl_read = proc(s: Stream, p: []byte) -> (n: int, err: Error) { - t := (^Tee_Reader)(s.stream_data); - n, err = read(t.r, p); + t := (^Tee_Reader)(s.stream_data) + n, err = read(t.r, p) if n > 0 { if wn, werr := write(t.w, p[:n]); werr != nil { - return wn, werr; + return wn, werr } } - return; + return }, -}; +} // tee_reader_init returns a Reader that writes to 'w' what it reads from 'r' // All reads from 'r' performed through it are matched with a corresponding write to 'w' @@ -64,14 +64,14 @@ _tee_reader_vtable := &Stream_VTable{ // Any error encountered whilst writing is reported as a 'read' error // tee_reader_init must call io.destroy when done with tee_reader_init :: proc(t: ^Tee_Reader, r: Reader, w: Writer, allocator := context.allocator) -> Reader { - t.r, t.w = r, w; - return tee_reader_to_reader(t); + t.r, t.w = r, w + return tee_reader_to_reader(t) } tee_reader_to_reader :: proc(t: ^Tee_Reader) -> (r: Reader) { - r.stream_data = t; - r.stream_vtable = _tee_reader_vtable; - return; + r.stream_data = t + r.stream_vtable = _tee_reader_vtable + return } @@ -86,30 +86,30 @@ Limited_Reader :: struct { @(private) _limited_reader_vtable := &Stream_VTable{ impl_read = proc(s: Stream, p: []byte) -> (n: int, err: Error) { - l := (^Limited_Reader)(s.stream_data); + l := (^Limited_Reader)(s.stream_data) if l.n <= 0 { - return 0, .EOF; + return 0, .EOF } - p := p; + p := p if i64(len(p)) > l.n { - p = p[0:l.n]; + p = p[0:l.n] } - n, err = read(l.r, p); - l.n -= i64(n); - return; + n, err = read(l.r, p) + l.n -= i64(n) + return }, -}; +} limited_reader_init :: proc(l: ^Limited_Reader, r: Reader, n: i64) -> Reader { - l.r = r; - l.n = n; - return limited_reader_to_reader(l); + l.r = r + l.n = n + return limited_reader_to_reader(l) } limited_reader_to_reader :: proc(l: ^Limited_Reader) -> (r: Reader) { - r.stream_vtable = _limited_reader_vtable; - r.stream_data = l; - return; + r.stream_vtable = _limited_reader_vtable + r.stream_data = l + return } // Section_Reader implements read, seek, and read_at on a section of an underlying Reader_At @@ -121,74 +121,74 @@ Section_Reader :: struct { } section_reader_init :: proc(s: ^Section_Reader, r: Reader_At, off: i64, n: i64) { - s.r = r; - s.off = off; - s.limit = off + n; - return; + s.r = r + s.off = off + s.limit = off + n + return } section_reader_to_stream :: proc(s: ^Section_Reader) -> (out: Stream) { - out.stream_data = s; - out.stream_vtable = _section_reader_vtable; - return; + out.stream_data = s + out.stream_vtable = _section_reader_vtable + return } @(private) _section_reader_vtable := &Stream_VTable{ impl_read = proc(stream: Stream, p: []byte) -> (n: int, err: Error) { - s := (^Section_Reader)(stream.stream_data); + s := (^Section_Reader)(stream.stream_data) if s.off >= s.limit { - return 0, .EOF; + return 0, .EOF } - p := p; + p := p if max := s.limit - s.off; i64(len(p)) > max { - p = p[0:max]; + p = p[0:max] } - n, err = read_at(s.r, p, s.off); - s.off += i64(n); - return; + n, err = read_at(s.r, p, s.off) + s.off += i64(n) + return }, impl_read_at = proc(stream: Stream, p: []byte, off: i64) -> (n: int, err: Error) { - s := (^Section_Reader)(stream.stream_data); - p, off := p, off; + s := (^Section_Reader)(stream.stream_data) + p, off := p, off if off < 0 || off >= s.limit - s.base { - return 0, .EOF; + return 0, .EOF } - off += s.base; + off += s.base if max := s.limit - off; i64(len(p)) > max { - p = p[0:max]; - n, err = read_at(s.r, p, off); + p = p[0:max] + n, err = read_at(s.r, p, off) if err == nil { - err = .EOF; + err = .EOF } - return; + return } - return read_at(s.r, p, off); + return read_at(s.r, p, off) }, impl_seek = proc(stream: Stream, offset: i64, whence: Seek_From) -> (n: i64, err: Error) { - s := (^Section_Reader)(stream.stream_data); + s := (^Section_Reader)(stream.stream_data) - offset := offset; + offset := offset switch whence { case: - return 0, .Invalid_Whence; + return 0, .Invalid_Whence case .Start: - offset += s.base; + offset += s.base case .Current: - offset += s.off; + offset += s.off case .End: - offset += s.limit; + offset += s.limit } if offset < s.base { - return 0, .Invalid_Offset; + return 0, .Invalid_Offset } - s.off = offset; - n = offset - s.base; - return; + s.off = offset + n = offset - s.base + return }, impl_size = proc(stream: Stream) -> i64 { - s := (^Section_Reader)(stream.stream_data); - return s.limit - s.base; + s := (^Section_Reader)(stream.stream_data) + return s.limit - s.base }, -}; +} diff --git a/core/log/file_console_logger.odin b/core/log/file_console_logger.odin index de491950d..a3070cd0b 100644 --- a/core/log/file_console_logger.odin +++ b/core/log/file_console_logger.odin @@ -1,9 +1,9 @@ package log -import "core:fmt"; -import "core:strings"; -import "core:os"; -import "core:time"; +import "core:fmt" +import "core:strings" +import "core:os" +import "core:time" Level_Headers := [?]string{ 0..<10 = "[DEBUG] --- ", @@ -11,7 +11,7 @@ Level_Headers := [?]string{ 20..<30 = "[WARN ] --- ", 30..<40 = "[ERROR] --- ", 40..<50 = "[FATAL] --- ", -}; +} Default_Console_Logger_Opts :: Options{ .Level, @@ -19,14 +19,14 @@ Default_Console_Logger_Opts :: Options{ .Short_File_Path, .Line, .Procedure, -} | Full_Timestamp_Opts; +} | Full_Timestamp_Opts Default_File_Logger_Opts :: Options{ .Level, .Short_File_Path, .Line, .Procedure, -} | Full_Timestamp_Opts; +} | Full_Timestamp_Opts File_Console_Logger_Data :: struct { @@ -35,128 +35,128 @@ File_Console_Logger_Data :: struct { } create_file_logger :: proc(h: os.Handle, lowest := Level.Debug, opt := Default_File_Logger_Opts, ident := "") -> Logger { - data := new(File_Console_Logger_Data); - data.file_handle = h; - data.ident = ident; - return Logger{file_console_logger_proc, data, lowest, opt}; + data := new(File_Console_Logger_Data) + data.file_handle = h + data.ident = ident + return Logger{file_console_logger_proc, data, lowest, opt} } destroy_file_logger :: proc(log: ^Logger) { - data := cast(^File_Console_Logger_Data)log.data; + data := cast(^File_Console_Logger_Data)log.data if data.file_handle != os.INVALID_HANDLE { - os.close(data.file_handle); + os.close(data.file_handle) } - free(data); + free(data) } create_console_logger :: proc(lowest := Level.Debug, opt := Default_Console_Logger_Opts, ident := "") -> Logger { - data := new(File_Console_Logger_Data); - data.file_handle = os.INVALID_HANDLE; - data.ident = ident; - return Logger{file_console_logger_proc, data, lowest, opt}; + data := new(File_Console_Logger_Data) + data.file_handle = os.INVALID_HANDLE + data.ident = ident + return Logger{file_console_logger_proc, data, lowest, opt} } destroy_console_logger :: proc(log: ^Logger) { - free(log.data); + free(log.data) } file_console_logger_proc :: proc(logger_data: rawptr, level: Level, text: string, options: Options, location := #caller_location) { - data := cast(^File_Console_Logger_Data)logger_data; - h: os.Handle = os.stdout if level <= Level.Error else os.stderr; + data := cast(^File_Console_Logger_Data)logger_data + h: os.Handle = os.stdout if level <= Level.Error else os.stderr if data.file_handle != os.INVALID_HANDLE { - h = data.file_handle; + h = data.file_handle } - backing: [1024]byte; //NOTE(Hoej): 1024 might be too much for a header backing, unless somebody has really long paths. - buf := strings.builder_from_slice(backing[:]); + backing: [1024]byte //NOTE(Hoej): 1024 might be too much for a header backing, unless somebody has really long paths. + buf := strings.builder_from_slice(backing[:]) - do_level_header(options, level, &buf); + do_level_header(options, level, &buf) when time.IS_SUPPORTED { if Full_Timestamp_Opts & options != nil { - fmt.sbprint(&buf, "["); - t := time.now(); - y, m, d := time.date(t); - h, min, s := time.clock(t); + fmt.sbprint(&buf, "[") + t := time.now() + y, m, d := time.date(t) + h, min, s := time.clock(t) if .Date in options { fmt.sbprintf(&buf, "%d-%02d-%02d ", y, m, d); } if .Time in options { fmt.sbprintf(&buf, "%02d:%02d:%02d", h, min, s); } - fmt.sbprint(&buf, "] "); + fmt.sbprint(&buf, "] ") } } - do_location_header(options, &buf, location); + do_location_header(options, &buf, location) if .Thread_Id in options { // NOTE(Oskar): not using context.thread_id here since that could be // incorrect when replacing context for a thread. - fmt.sbprintf(&buf, "[{}] ", os.current_thread_id()); + fmt.sbprintf(&buf, "[{}] ", os.current_thread_id()) } if data.ident != "" { - fmt.sbprintf(&buf, "[%s] ", data.ident); + fmt.sbprintf(&buf, "[%s] ", data.ident) } //TODO(Hoej): When we have better atomics and such, make this thread-safe - fmt.fprintf(h, "%s %s\n", strings.to_string(buf), text); + fmt.fprintf(h, "%s %s\n", strings.to_string(buf), text) } do_level_header :: proc(opts: Options, level: Level, str: ^strings.Builder) { - RESET :: "\x1b[0m"; - RED :: "\x1b[31m"; - YELLOW :: "\x1b[33m"; - DARK_GREY :: "\x1b[90m"; + RESET :: "\x1b[0m" + RED :: "\x1b[31m" + YELLOW :: "\x1b[33m" + DARK_GREY :: "\x1b[90m" - col := RESET; + col := RESET switch level { - case .Debug: col = DARK_GREY; - case .Info: col = RESET; - case .Warning: col = YELLOW; - case .Error, .Fatal: col = RED; + case .Debug: col = DARK_GREY + case .Info: col = RESET + case .Warning: col = YELLOW + case .Error, .Fatal: col = RED } if .Level in opts { if .Terminal_Color in opts { - fmt.sbprint(str, col); + fmt.sbprint(str, col) } - fmt.sbprint(str, Level_Headers[level]); + fmt.sbprint(str, Level_Headers[level]) if .Terminal_Color in opts { - fmt.sbprint(str, RESET); + fmt.sbprint(str, RESET) } } } do_location_header :: proc(opts: Options, buf: ^strings.Builder, location := #caller_location) { if Location_Header_Opts & opts == nil { - return; + return } - fmt.sbprint(buf, "["); + fmt.sbprint(buf, "[") - file := location.file_path; + file := location.file_path if .Short_File_Path in opts { - last := 0; + last := 0 for r, i in location.file_path { if r == '/' { - last = i+1; + last = i+1 } } - file = location.file_path[last:]; + file = location.file_path[last:] } if Location_File_Opts & opts != nil { - fmt.sbprint(buf, file); + fmt.sbprint(buf, file) } if .Line in opts { if Location_File_Opts & opts != nil { - fmt.sbprint(buf, ":"); + fmt.sbprint(buf, ":") } - fmt.sbprint(buf, location.line); + fmt.sbprint(buf, location.line) } if .Procedure in opts { if (Location_File_Opts | {.Line}) & opts != nil { - fmt.sbprint(buf, ":"); + fmt.sbprint(buf, ":") } - fmt.sbprintf(buf, "%s()", location.procedure); + fmt.sbprintf(buf, "%s()", location.procedure) } - fmt.sbprint(buf, "] "); + fmt.sbprint(buf, "] ") } diff --git a/core/log/log.odin b/core/log/log.odin index 418ad617e..d34a135cc 100644 --- a/core/log/log.odin +++ b/core/log/log.odin @@ -6,7 +6,7 @@ import "core:fmt" // NOTE(bill, 2019-12-31): These are defined in `package runtime` as they are used in the `context`. This is to prevent an import definition cycle. -Level :: runtime.Logger_Level; +Level :: runtime.Logger_Level /* Logger_Level :: enum { Debug = 0, @@ -17,7 +17,7 @@ Logger_Level :: enum { } */ -Option :: runtime.Logger_Option; +Option :: runtime.Logger_Option /* Option :: enum { Level, @@ -31,7 +31,7 @@ Option :: enum { } */ -Options :: runtime.Logger_Options; +Options :: runtime.Logger_Options /* Options :: bit_set[Option]; */ @@ -39,25 +39,25 @@ Options :: bit_set[Option]; Full_Timestamp_Opts :: Options{ .Date, .Time, -}; +} Location_Header_Opts :: Options{ .Short_File_Path, .Long_File_Path, .Line, .Procedure, -}; +} Location_File_Opts :: Options{ .Short_File_Path, .Long_File_Path, -}; +} -Logger_Proc :: runtime.Logger_Proc; +Logger_Proc :: runtime.Logger_Proc /* Logger_Proc :: #type proc(data: rawptr, level: Level, text: string, options: Options, location := #caller_location); */ -Logger :: runtime.Logger; +Logger :: runtime.Logger /* Logger :: struct { procedure: Logger_Proc, @@ -72,74 +72,74 @@ nil_logger_proc :: proc(data: rawptr, level: Level, text: string, options: Optio } nil_logger :: proc() -> Logger { - return Logger{nil_logger_proc, nil, Level.Debug, nil}; + return Logger{nil_logger_proc, nil, Level.Debug, nil} } // TODO(bill): Should these be redesigned so that they are do not rely upon `package fmt`? debugf :: proc(fmt_str: string, args: ..any, location := #caller_location) { - logf(level=.Debug, fmt_str=fmt_str, args=args, location=location); + logf(level=.Debug, fmt_str=fmt_str, args=args, location=location) } infof :: proc(fmt_str: string, args: ..any, location := #caller_location) { - logf(level=.Info, fmt_str=fmt_str, args=args, location=location); + logf(level=.Info, fmt_str=fmt_str, args=args, location=location) } warnf :: proc(fmt_str: string, args: ..any, location := #caller_location) { - logf(level=.Warning, fmt_str=fmt_str, args=args, location=location); + logf(level=.Warning, fmt_str=fmt_str, args=args, location=location) } errorf :: proc(fmt_str: string, args: ..any, location := #caller_location) { - logf(level=.Error, fmt_str=fmt_str, args=args, location=location); + logf(level=.Error, fmt_str=fmt_str, args=args, location=location) } fatalf :: proc(fmt_str: string, args: ..any, location := #caller_location) { - logf(level=.Fatal, fmt_str=fmt_str, args=args, location=location); + logf(level=.Fatal, fmt_str=fmt_str, args=args, location=location) } debug :: proc(args: ..any, sep := " ", location := #caller_location) { - log(level=.Debug, args=args, sep=sep, location=location); + log(level=.Debug, args=args, sep=sep, location=location) } info :: proc(args: ..any, sep := " ", location := #caller_location) { - log(level=.Info, args=args, sep=sep, location=location); + log(level=.Info, args=args, sep=sep, location=location) } warn :: proc(args: ..any, sep := " ", location := #caller_location) { - log(level=.Warning, args=args, sep=sep, location=location); + log(level=.Warning, args=args, sep=sep, location=location) } error :: proc(args: ..any, sep := " ", location := #caller_location) { - log(level=.Error, args=args, sep=sep, location=location); + log(level=.Error, args=args, sep=sep, location=location) } fatal :: proc(args: ..any, sep := " ", location := #caller_location) { - log(level=.Fatal, args=args, sep=sep, location=location); + log(level=.Fatal, args=args, sep=sep, location=location) } panic :: proc(args: ..any, location := #caller_location) -> ! { - log(level=.Fatal, args=args, location=location); - runtime.panic("log.panic", location); + log(level=.Fatal, args=args, location=location) + runtime.panic("log.panic", location) } panicf :: proc(fmt_str: string, args: ..any, location := #caller_location) -> ! { - logf(level=.Fatal, fmt_str=fmt_str, args=args, location=location); - runtime.panic("log.panicf", location); + logf(level=.Fatal, fmt_str=fmt_str, args=args, location=location) + runtime.panic("log.panicf", location) } log :: proc(level: Level, args: ..any, sep := " ", location := #caller_location) { - logger := context.logger; + logger := context.logger if logger.procedure == nil { - return; + return } if level < logger.lowest_level { - return; + return } - str := fmt.tprint(args=args, sep=sep); //NOTE(Hoej): While tprint isn't thread-safe, no logging is. - logger.procedure(logger.data, level, str, logger.options, location); + str := fmt.tprint(args=args, sep=sep) //NOTE(Hoej): While tprint isn't thread-safe, no logging is. + logger.procedure(logger.data, level, str, logger.options, location) } logf :: proc(level: Level, fmt_str: string, args: ..any, location := #caller_location) { - logger := context.logger; + logger := context.logger if logger.procedure == nil { - return; + return } if level < logger.lowest_level { - return; + return } - str := fmt.tprintf(fmt_str, ..args); - logger.procedure(logger.data, level, str, logger.options, location); + str := fmt.tprintf(fmt_str, ..args) + logger.procedure(logger.data, level, str, logger.options, location) } diff --git a/core/log/multi_logger.odin b/core/log/multi_logger.odin index 7b852bb5c..b4cd8b1a1 100644 --- a/core/log/multi_logger.odin +++ b/core/log/multi_logger.odin @@ -6,24 +6,24 @@ Multi_Logger_Data :: struct { } create_multi_logger :: proc(logs: ..Logger) -> Logger { - data := new(Multi_Logger_Data); - data.loggers = make([]Logger, len(logs)); - copy(data.loggers, logs); - return Logger{multi_logger_proc, data, Level.Debug, nil}; + data := new(Multi_Logger_Data) + data.loggers = make([]Logger, len(logs)) + copy(data.loggers, logs) + return Logger{multi_logger_proc, data, Level.Debug, nil} } destroy_multi_logger :: proc(log : ^Logger) { - free(log.data); - log^ = nil_logger(); + free(log.data) + log^ = nil_logger() } multi_logger_proc :: proc(logger_data: rawptr, level: Level, text: string, options: Options, location := #caller_location) { - data := cast(^Multi_Logger_Data)logger_data; + data := cast(^Multi_Logger_Data)logger_data for log in data.loggers { if level < log.lowest_level { - return; + return } - log.procedure(log.data, level, text, log.options, location); + log.procedure(log.data, level, text, log.options, location) } } diff --git a/core/math/big/api.odin b/core/math/big/api.odin index 1f2eab8d7..1c7833730 100644 --- a/core/math/big/api.odin +++ b/core/math/big/api.odin @@ -31,7 +31,7 @@ add :: proc { int_add_digit :: proc(dest, a: ^Int, digit: DIGIT, allocator := context.allocator) -> (err: Error) */ int_add_digit, -}; +} /* err = sub(dest, a, b); @@ -45,7 +45,7 @@ sub :: proc { int_sub_digit :: proc(dest, a: ^Int, digit: DIGIT) -> (err: Error) */ int_sub_digit, -}; +} /* === === === === === === === === === === === === === === === === === === === === === === === === @@ -59,44 +59,44 @@ is_initialized :: proc { int_is_initialized :: proc(a: ^Int) -> bool */ int_is_initialized, -}; +} is_zero :: proc { /* int_is_zero :: proc(a: ^Int) -> bool */ int_is_zero, -}; +} is_positive :: proc { /* int_is_positive :: proc(a: ^Int) -> bool */ int_is_positive, -}; -is_pos :: is_positive; +} +is_pos :: is_positive is_negative :: proc { /* int_is_negative :: proc(a: ^Int) -> bool */ int_is_negative, -}; -is_neg :: is_negative; +} +is_neg :: is_negative is_even :: proc { /* int_is_even :: proc(a: ^Int) -> bool */ int_is_even, -}; +} is_odd :: proc { /* int_is_odd :: proc(a: ^Int) -> bool */ int_is_odd, -}; +} is_power_of_two :: proc { /* @@ -107,7 +107,7 @@ is_power_of_two :: proc { int_is_power_of_two :: proc(a: ^Int) -> (res: bool) */ int_is_power_of_two, -}; +} compare :: proc { /* @@ -122,16 +122,16 @@ compare :: proc { int_compare_digit :: proc(a: ^Int, u: DIGIT) -> Comparison_Flag */ int_compare_digit, -}; -cmp :: compare; +} +cmp :: compare compare_magnitude :: proc { /* Compare the magnitude of two `Int`s, unsigned. */ int_compare_magnitude, -}; -cmp_mag :: compare_magnitude; +} +cmp_mag :: compare_magnitude /* === === === === === === === === === === === === === === === === === === === === === === === === @@ -147,6 +147,6 @@ destroy :: proc { int_destroy :: proc(integers: ..^Int) */ int_destroy, -}; +} diff --git a/core/math/big/common.odin b/core/math/big/common.odin index ce1f7d77f..f23754e89 100644 --- a/core/math/big/common.odin +++ b/core/math/big/common.odin @@ -33,15 +33,15 @@ import "core:intrinsics" To allow tests to run we add `-define:MATH_BIG_EXE=false` to hardcode the cutoffs for now. */ when #config(MATH_BIG_EXE, true) { - MUL_KARATSUBA_CUTOFF := initialize_constants(); - SQR_KARATSUBA_CUTOFF := _DEFAULT_SQR_KARATSUBA_CUTOFF; - MUL_TOOM_CUTOFF := _DEFAULT_MUL_TOOM_CUTOFF; - SQR_TOOM_CUTOFF := _DEFAULT_SQR_TOOM_CUTOFF; + MUL_KARATSUBA_CUTOFF := initialize_constants() + SQR_KARATSUBA_CUTOFF := _DEFAULT_SQR_KARATSUBA_CUTOFF + MUL_TOOM_CUTOFF := _DEFAULT_MUL_TOOM_CUTOFF + SQR_TOOM_CUTOFF := _DEFAULT_SQR_TOOM_CUTOFF } else { - MUL_KARATSUBA_CUTOFF := _DEFAULT_MUL_KARATSUBA_CUTOFF; - SQR_KARATSUBA_CUTOFF := _DEFAULT_SQR_KARATSUBA_CUTOFF; - MUL_TOOM_CUTOFF := _DEFAULT_MUL_TOOM_CUTOFF; - SQR_TOOM_CUTOFF := _DEFAULT_SQR_TOOM_CUTOFF; + MUL_KARATSUBA_CUTOFF := _DEFAULT_MUL_KARATSUBA_CUTOFF + SQR_KARATSUBA_CUTOFF := _DEFAULT_SQR_KARATSUBA_CUTOFF + MUL_TOOM_CUTOFF := _DEFAULT_MUL_TOOM_CUTOFF + SQR_TOOM_CUTOFF := _DEFAULT_SQR_TOOM_CUTOFF } /* @@ -57,24 +57,24 @@ when #config(MATH_BIG_EXE, true) { debugged where necessary. */ -_DEFAULT_MUL_KARATSUBA_CUTOFF :: #config(MUL_KARATSUBA_CUTOFF, 80); -_DEFAULT_SQR_KARATSUBA_CUTOFF :: #config(SQR_KARATSUBA_CUTOFF, 120); -_DEFAULT_MUL_TOOM_CUTOFF :: #config(MUL_TOOM_CUTOFF, 350); -_DEFAULT_SQR_TOOM_CUTOFF :: #config(SQR_TOOM_CUTOFF, 400); +_DEFAULT_MUL_KARATSUBA_CUTOFF :: #config(MUL_KARATSUBA_CUTOFF, 80) +_DEFAULT_SQR_KARATSUBA_CUTOFF :: #config(SQR_KARATSUBA_CUTOFF, 120) +_DEFAULT_MUL_TOOM_CUTOFF :: #config(MUL_TOOM_CUTOFF, 350) +_DEFAULT_SQR_TOOM_CUTOFF :: #config(SQR_TOOM_CUTOFF, 400) -MAX_ITERATIONS_ROOT_N := 500; +MAX_ITERATIONS_ROOT_N := 500 /* Largest `N` for which we'll compute `N!` */ -FACTORIAL_MAX_N := 1_000_000; +FACTORIAL_MAX_N := 1_000_000 /* Cutoff to switch to int_factorial_binary_split, and its max recursion level. */ -FACTORIAL_BINARY_SPLIT_CUTOFF := 6100; -FACTORIAL_BINARY_SPLIT_MAX_RECURSIONS := 100; +FACTORIAL_BINARY_SPLIT_CUTOFF := 6100 +FACTORIAL_BINARY_SPLIT_MAX_RECURSIONS := 100 /* @@ -85,15 +85,15 @@ FACTORIAL_BINARY_SPLIT_MAX_RECURSIONS := 100; 2) Optimizations thanks to precomputed masks wouldn't work. */ -MATH_BIG_FORCE_64_BIT :: #config(MATH_BIG_FORCE_64_BIT, false); -MATH_BIG_FORCE_32_BIT :: #config(MATH_BIG_FORCE_32_BIT, false); +MATH_BIG_FORCE_64_BIT :: #config(MATH_BIG_FORCE_64_BIT, false) +MATH_BIG_FORCE_32_BIT :: #config(MATH_BIG_FORCE_32_BIT, false) when (MATH_BIG_FORCE_32_BIT && MATH_BIG_FORCE_64_BIT) { #panic("Cannot force 32-bit and 64-bit big backend simultaneously."); }; -_LOW_MEMORY :: #config(BIGINT_SMALL_MEMORY, false); +_LOW_MEMORY :: #config(BIGINT_SMALL_MEMORY, false) when _LOW_MEMORY { - _DEFAULT_DIGIT_COUNT :: 8; + _DEFAULT_DIGIT_COUNT :: 8 } else { - _DEFAULT_DIGIT_COUNT :: 32; + _DEFAULT_DIGIT_COUNT :: 32 } /* @@ -103,22 +103,22 @@ when _LOW_MEMORY { Sign :: enum u8 { Zero_or_Positive = 0, Negative = 1, -}; +} Int :: struct { used: int, digit: [dynamic]DIGIT, sign: Sign, flags: Flags, -}; +} Flag :: enum u8 { NaN, Inf, Immutable, -}; +} -Flags :: bit_set[Flag; u8]; +Flags :: bit_set[Flag; u8] /* Errors are a strict superset of runtime.Allocation_Error. @@ -138,7 +138,7 @@ Error :: enum int { Math_Domain_Error = 9, Unimplemented = 127, -}; +} Error_String :: #partial [Error]string{ .Out_Of_Memory = "Out of memory", @@ -154,14 +154,14 @@ Error_String :: #partial [Error]string{ .Math_Domain_Error = "Math domain error", .Unimplemented = "Unimplemented", -}; +} Primality_Flag :: enum u8 { Blum_Blum_Shub = 0, /* BBS style prime */ Safe = 1, /* Safe prime (p-1)/2 == prime */ Second_MSB_On = 3, /* force 2nd MSB to 1 */ -}; -Primality_Flags :: bit_set[Primality_Flag; u8]; +} +Primality_Flags :: bit_set[Primality_Flag; u8] /* How do we store the Ints? @@ -171,7 +171,7 @@ Primality_Flags :: bit_set[Primality_Flag; u8]; - Must be large enough such that `init_integer` can store `u128` in the `Int` without growing. */ -_MIN_DIGIT_COUNT :: max(3, ((size_of(u128) + _DIGIT_BITS) - 1) / _DIGIT_BITS); +_MIN_DIGIT_COUNT :: max(3, ((size_of(u128) + _DIGIT_BITS) - 1) / _DIGIT_BITS) #assert(_DEFAULT_DIGIT_COUNT >= _MIN_DIGIT_COUNT); /* @@ -180,36 +180,36 @@ _MIN_DIGIT_COUNT :: max(3, ((size_of(u128) + _DIGIT_BITS) - 1) / _DIGIT_BITS); - Must be small enough such that `_radix_size` for base 2 does not overflow. `_radix_size` needs two additional bytes for zero termination and sign. */ -_MAX_BIT_COUNT :: (max(int) - 2); -_MAX_DIGIT_COUNT :: _MAX_BIT_COUNT / _DIGIT_BITS; +_MAX_BIT_COUNT :: (max(int) - 2) +_MAX_DIGIT_COUNT :: _MAX_BIT_COUNT / _DIGIT_BITS when MATH_BIG_FORCE_64_BIT || (!MATH_BIG_FORCE_32_BIT && size_of(rawptr) == 8) { /* We can use u128 as an intermediary. */ - DIGIT :: distinct u64; - _WORD :: distinct u128; + DIGIT :: distinct u64 + _WORD :: distinct u128 } else { - DIGIT :: distinct u32; - _WORD :: distinct u64; + DIGIT :: distinct u32 + _WORD :: distinct u64 } #assert(size_of(_WORD) == 2 * size_of(DIGIT)); -_DIGIT_TYPE_BITS :: 8 * size_of(DIGIT); -_WORD_TYPE_BITS :: 8 * size_of(_WORD); +_DIGIT_TYPE_BITS :: 8 * size_of(DIGIT) +_WORD_TYPE_BITS :: 8 * size_of(_WORD) -_DIGIT_BITS :: _DIGIT_TYPE_BITS - 4; -_WORD_BITS :: 2 * _DIGIT_BITS; +_DIGIT_BITS :: _DIGIT_TYPE_BITS - 4 +_WORD_BITS :: 2 * _DIGIT_BITS -_MASK :: (DIGIT(1) << DIGIT(_DIGIT_BITS)) - DIGIT(1); -_DIGIT_MAX :: _MASK; -_MAX_COMBA :: 1 << (_WORD_TYPE_BITS - (2 * _DIGIT_BITS)) ; -_WARRAY :: 1 << ((_WORD_TYPE_BITS - (2 * _DIGIT_BITS)) + 1); +_MASK :: (DIGIT(1) << DIGIT(_DIGIT_BITS)) - DIGIT(1) +_DIGIT_MAX :: _MASK +_MAX_COMBA :: 1 << (_WORD_TYPE_BITS - (2 * _DIGIT_BITS)) +_WARRAY :: 1 << ((_WORD_TYPE_BITS - (2 * _DIGIT_BITS)) + 1) Order :: enum i8 { LSB_First = -1, MSB_First = 1, -}; +} Endianness :: enum i8 { Little = -1, diff --git a/core/math/big/example.odin b/core/math/big/example.odin index 4542e9e15..d764ad940 100644 --- a/core/math/big/example.odin +++ b/core/math/big/example.odin @@ -47,186 +47,186 @@ MAX_ITERATIONS_ROOT_N, FACTORIAL_MAX_N, FACTORIAL_BINARY_SPLIT_CUTOFF, FACTORIAL_BINARY_SPLIT_MAX_RECURSIONS, -); +) } print :: proc(name: string, a: ^Int, base := i8(10), print_name := true, newline := true, print_extra_info := false) { - assert_if_nil(a); + assert_if_nil(a) - as, err := itoa(a, base); - defer delete(as); + as, err := itoa(a, base) + defer delete(as) - cb := internal_count_bits(a); + cb := internal_count_bits(a) if print_name { - fmt.printf("%v", name); + fmt.printf("%v", name) } if err != nil { - fmt.printf("%v (error: %v | %v)", name, err, a); + fmt.printf("%v (error: %v | %v)", name, err, a) } - fmt.printf("%v", as); + fmt.printf("%v", as) if print_extra_info { - fmt.printf(" (base: %v, bits: %v (digits: %v), flags: %v)", base, cb, a.used, a.flags); + fmt.printf(" (base: %v, bits: %v (digits: %v), flags: %v)", base, cb, a.used, a.flags) } if newline { - fmt.println(); + fmt.println() } } int_to_byte :: proc(v: ^Int) { - err: Error; - size: int; - print("v: ", v); - fmt.println(); + err: Error + size: int + print("v: ", v) + fmt.println() - t := &Int{}; - defer destroy(t); + t := &Int{} + defer destroy(t) if size, err = int_to_bytes_size(v); err != nil { - fmt.printf("int_to_bytes_size returned: %v\n", err); - return; + fmt.printf("int_to_bytes_size returned: %v\n", err) + return } - b1 := make([]u8, size, context.temp_allocator); - err = int_to_bytes_big(v, b1); - int_from_bytes_big(t, b1); - fmt.printf("big: %v | err: %v\n", b1, err); + b1 := make([]u8, size, context.temp_allocator) + err = int_to_bytes_big(v, b1) + int_from_bytes_big(t, b1) + fmt.printf("big: %v | err: %v\n", b1, err) - int_from_bytes_big(t, b1); + int_from_bytes_big(t, b1) if internal_cmp_mag(t, v) != 0 { - print("\tError parsing t: ", t); + print("\tError parsing t: ", t) } if size, err = int_to_bytes_size(v); err != nil { - fmt.printf("int_to_bytes_size returned: %v\n", err); - return; + fmt.printf("int_to_bytes_size returned: %v\n", err) + return } - b2 := make([]u8, size, context.temp_allocator); - err = int_to_bytes_big_python(v, b2); - fmt.printf("big python: %v | err: %v\n", b2, err); + b2 := make([]u8, size, context.temp_allocator) + err = int_to_bytes_big_python(v, b2) + fmt.printf("big python: %v | err: %v\n", b2, err) if err == nil { - int_from_bytes_big_python(t, b2); + int_from_bytes_big_python(t, b2) if internal_cmp_mag(t, v) != 0 { - print("\tError parsing t: ", t); + print("\tError parsing t: ", t) } } if size, err = int_to_bytes_size(v, true); err != nil { - fmt.printf("int_to_bytes_size returned: %v\n", err); - return; + fmt.printf("int_to_bytes_size returned: %v\n", err) + return } - b3 := make([]u8, size, context.temp_allocator); - err = int_to_bytes_big(v, b3, true); - fmt.printf("big signed: %v | err: %v\n", b3, err); + b3 := make([]u8, size, context.temp_allocator) + err = int_to_bytes_big(v, b3, true) + fmt.printf("big signed: %v | err: %v\n", b3, err) - int_from_bytes_big(t, b3, true); + int_from_bytes_big(t, b3, true) if internal_cmp(t, v) != 0 { - print("\tError parsing t: ", t); + print("\tError parsing t: ", t) } if size, err = int_to_bytes_size(v, true); err != nil { - fmt.printf("int_to_bytes_size returned: %v\n", err); - return; + fmt.printf("int_to_bytes_size returned: %v\n", err) + return } - b4 := make([]u8, size, context.temp_allocator); - err = int_to_bytes_big_python(v, b4, true); - fmt.printf("big signed python: %v | err: %v\n", b4, err); + b4 := make([]u8, size, context.temp_allocator) + err = int_to_bytes_big_python(v, b4, true) + fmt.printf("big signed python: %v | err: %v\n", b4, err) - int_from_bytes_big_python(t, b4, true); + int_from_bytes_big_python(t, b4, true) if internal_cmp(t, v) != 0 { - print("\tError parsing t: ", t); + print("\tError parsing t: ", t) } } int_to_byte_little :: proc(v: ^Int) { - err: Error; - size: int; - print("v: ", v); - fmt.println(); + err: Error + size: int + print("v: ", v) + fmt.println() - t := &Int{}; - defer destroy(t); + t := &Int{} + defer destroy(t) if size, err = int_to_bytes_size(v); err != nil { - fmt.printf("int_to_bytes_size returned: %v\n", err); - return; + fmt.printf("int_to_bytes_size returned: %v\n", err) + return } - b1 := make([]u8, size, context.temp_allocator); - err = int_to_bytes_little(v, b1); - fmt.printf("little: %v | err: %v\n", b1, err); + b1 := make([]u8, size, context.temp_allocator) + err = int_to_bytes_little(v, b1) + fmt.printf("little: %v | err: %v\n", b1, err) - int_from_bytes_little(t, b1); + int_from_bytes_little(t, b1) if internal_cmp_mag(t, v) != 0 { - print("\tError parsing t: ", t); + print("\tError parsing t: ", t) } if size, err = int_to_bytes_size(v); err != nil { - fmt.printf("int_to_bytes_size returned: %v\n", err); - return; + fmt.printf("int_to_bytes_size returned: %v\n", err) + return } - b2 := make([]u8, size, context.temp_allocator); - err = int_to_bytes_little_python(v, b2); - fmt.printf("little python: %v | err: %v\n", b2, err); + b2 := make([]u8, size, context.temp_allocator) + err = int_to_bytes_little_python(v, b2) + fmt.printf("little python: %v | err: %v\n", b2, err) if err == nil { - int_from_bytes_little_python(t, b2); + int_from_bytes_little_python(t, b2) if internal_cmp_mag(t, v) != 0 { - print("\tError parsing t: ", t); + print("\tError parsing t: ", t) } } if size, err = int_to_bytes_size(v, true); err != nil { - fmt.printf("int_to_bytes_size returned: %v\n", err); - return; + fmt.printf("int_to_bytes_size returned: %v\n", err) + return } - b3 := make([]u8, size, context.temp_allocator); - err = int_to_bytes_little(v, b3, true); - fmt.printf("little signed: %v | err: %v\n", b3, err); + b3 := make([]u8, size, context.temp_allocator) + err = int_to_bytes_little(v, b3, true) + fmt.printf("little signed: %v | err: %v\n", b3, err) - int_from_bytes_little(t, b3, true); + int_from_bytes_little(t, b3, true) if internal_cmp(t, v) != 0 { - print("\tError parsing t: ", t); + print("\tError parsing t: ", t) } if size, err = int_to_bytes_size(v, true); err != nil { - fmt.printf("int_to_bytes_size returned: %v\n", err); - return; + fmt.printf("int_to_bytes_size returned: %v\n", err) + return } - b4 := make([]u8, size, context.temp_allocator); - err = int_to_bytes_little_python(v, b4, true); - fmt.printf("little signed python: %v | err: %v\n", b4, err); + b4 := make([]u8, size, context.temp_allocator) + err = int_to_bytes_little_python(v, b4, true) + fmt.printf("little signed python: %v | err: %v\n", b4, err) - int_from_bytes_little_python(t, b4, true); + int_from_bytes_little_python(t, b4, true) if internal_cmp(t, v) != 0 { - print("\tError parsing t: ", t); + print("\tError parsing t: ", t) } } demo :: proc() { - a, b, c, d, e, f := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}; - defer destroy(a, b, c, d, e, f); + a, b, c, d, e, f := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{} + defer destroy(a, b, c, d, e, f) } main :: proc() { - ta := mem.Tracking_Allocator{}; - mem.tracking_allocator_init(&ta, context.allocator); - context.allocator = mem.tracking_allocator(&ta); + ta := mem.Tracking_Allocator{} + mem.tracking_allocator_init(&ta, context.allocator) + context.allocator = mem.tracking_allocator(&ta) - demo(); + demo() - print_configation(); + print_configation() - print_timings(); + print_timings() if len(ta.allocation_map) > 0 { for _, v in ta.allocation_map { - fmt.printf("Leaked %v bytes @ %v\n", v.size, v.location); + fmt.printf("Leaked %v bytes @ %v\n", v.size, v.location) } } if len(ta.bad_free_array) > 0 { - fmt.println("Bad frees:"); + fmt.println("Bad frees:") for v in ta.bad_free_array { - fmt.println(v); + fmt.println(v) } } }
\ No newline at end of file diff --git a/core/math/big/helpers.odin b/core/math/big/helpers.odin index 8ce1b2811..5138dd77d 100644 --- a/core/math/big/helpers.odin +++ b/core/math/big/helpers.odin @@ -22,10 +22,10 @@ import rnd "core:math/rand" Deallocates the backing memory of one or more `Int`s. */ int_destroy :: proc(integers: ..^Int) { - integers := integers; + integers := integers for a in &integers { - assert_if_nil(a); + assert_if_nil(a) } #force_inline internal_int_destroy(..integers); } @@ -35,19 +35,19 @@ int_destroy :: proc(integers: ..^Int) { */ int_set_from_integer :: proc(dest: ^Int, src: $T, minimize := false, allocator := context.allocator) -> (err: Error) where intrinsics.type_is_integer(T) { - context.allocator = allocator; - src := src; + context.allocator = allocator + src := src /* Check that `src` is usable and `dest` isn't immutable. */ - assert_if_nil(dest); + assert_if_nil(dest) #force_inline internal_error_if_immutable(dest) or_return; - return #force_inline internal_int_set_from_integer(dest, src, minimize); + return #force_inline internal_int_set_from_integer(dest, src, minimize) } -set :: proc { int_set_from_integer, int_copy, int_atoi, }; +set :: proc { int_set_from_integer, int_copy, int_atoi, } /* Copy one `Int` to another. @@ -61,15 +61,15 @@ int_copy :: proc(dest, src: ^Int, minimize := false, allocator := context.alloca /* Check that `src` is usable and `dest` isn't immutable. */ - assert_if_nil(dest, src); - context.allocator = allocator; + assert_if_nil(dest, src) + context.allocator = allocator #force_inline internal_clear_if_uninitialized(src) or_return; #force_inline internal_error_if_immutable(dest) or_return; - return #force_inline internal_int_copy(dest, src, minimize); + return #force_inline internal_int_copy(dest, src, minimize) } -copy :: proc { int_copy, }; +copy :: proc { int_copy, } /* In normal code, you can also write `a, b = b, a`. @@ -77,10 +77,10 @@ copy :: proc { int_copy, }; This helper swaps completely. */ int_swap :: proc(a, b: ^Int) { - assert_if_nil(a, b); + assert_if_nil(a, b) #force_inline internal_swap(a, b); } -swap :: proc { int_swap, }; +swap :: proc { int_swap, } /* Set `dest` to |`src`|. @@ -89,19 +89,19 @@ int_abs :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) /* Check that `src` is usable and `dest` isn't immutable. */ - assert_if_nil(dest, src); - context.allocator = allocator; + assert_if_nil(dest, src) + context.allocator = allocator #force_inline internal_clear_if_uninitialized(src) or_return; #force_inline internal_error_if_immutable(dest) or_return; - return #force_inline internal_int_abs(dest, src); + return #force_inline internal_int_abs(dest, src) } platform_abs :: proc(n: $T) -> T where intrinsics.type_is_integer(T) { - return n if n >= 0 else -n; + return n if n >= 0 else -n } -abs :: proc{ int_abs, platform_abs, }; +abs :: proc{ int_abs, platform_abs, } /* Set `dest` to `-src`. @@ -110,32 +110,32 @@ int_neg :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) /* Check that `src` is usable and `dest` isn't immutable. */ - assert_if_nil(dest, src); - context.allocator = allocator; + assert_if_nil(dest, src) + context.allocator = allocator #force_inline internal_clear_if_uninitialized(src) or_return; #force_inline internal_error_if_immutable(dest) or_return; - return #force_inline internal_int_neg(dest, src); + return #force_inline internal_int_neg(dest, src) } -neg :: proc { int_neg, }; +neg :: proc { int_neg, } /* Helpers to extract values from the `Int`. */ int_bitfield_extract_single :: proc(a: ^Int, offset: int, allocator := context.allocator) -> (bit: _WORD, err: Error) { - return #force_inline int_bitfield_extract(a, offset, 1, allocator); + return #force_inline int_bitfield_extract(a, offset, 1, allocator) } int_bitfield_extract :: proc(a: ^Int, offset, count: int, allocator := context.allocator) -> (res: _WORD, err: Error) { /* Check that `a` is usable. */ - assert_if_nil(a); - context.allocator = allocator; + assert_if_nil(a) + context.allocator = allocator #force_inline internal_clear_if_uninitialized(a) or_return; - return #force_inline internal_int_bitfield_extract(a, offset, count); + return #force_inline internal_int_bitfield_extract(a, offset, count) } /* @@ -145,21 +145,21 @@ shrink :: proc(a: ^Int, allocator := context.allocator) -> (err: Error) { /* Check that `a` is usable. */ - assert_if_nil(a); - context.allocator = allocator; + assert_if_nil(a) + context.allocator = allocator #force_inline internal_clear_if_uninitialized(a) or_return; - return #force_inline internal_shrink(a); + return #force_inline internal_shrink(a) } int_grow :: proc(a: ^Int, digits: int, allow_shrink := false, allocator := context.allocator) -> (err: Error) { /* Check that `a` is usable. */ - assert_if_nil(a); - return #force_inline internal_int_grow(a, digits, allow_shrink, allocator); + assert_if_nil(a) + return #force_inline internal_int_grow(a, digits, allow_shrink, allocator) } -grow :: proc { int_grow, }; +grow :: proc { int_grow, } /* Clear `Int` and resize it to the default size. @@ -168,11 +168,11 @@ int_clear :: proc(a: ^Int, minimize := false, allocator := context.allocator) -> /* Check that `a` is usable. */ - assert_if_nil(a); - return #force_inline internal_int_clear(a, minimize, allocator); + assert_if_nil(a) + return #force_inline internal_int_clear(a, minimize, allocator) } -clear :: proc { int_clear, }; -zero :: clear; +clear :: proc { int_clear, } +zero :: clear /* Set the `Int` to 1 and optionally shrink it to the minimum backing size. @@ -181,10 +181,10 @@ int_one :: proc(a: ^Int, minimize := false, allocator := context.allocator) -> ( /* Check that `a` is usable. */ - assert_if_nil(a); - return #force_inline internal_one(a, minimize, allocator); + assert_if_nil(a) + return #force_inline internal_one(a, minimize, allocator) } -one :: proc { int_one, }; +one :: proc { int_one, } /* Set the `Int` to -1 and optionally shrink it to the minimum backing size. @@ -193,10 +193,10 @@ int_minus_one :: proc(a: ^Int, minimize := false, allocator := context.allocator /* Check that `a` is usable. */ - assert_if_nil(a); - return #force_inline internal_minus_one(a, minimize, allocator); + assert_if_nil(a) + return #force_inline internal_minus_one(a, minimize, allocator) } -minus_one :: proc { int_minus_one, }; +minus_one :: proc { int_minus_one, } /* Set the `Int` to Inf and optionally shrink it to the minimum backing size. @@ -205,10 +205,10 @@ int_inf :: proc(a: ^Int, minimize := false, allocator := context.allocator) -> ( /* Check that `a` is usable. */ - assert_if_nil(a); - return #force_inline internal_inf(a, minimize, allocator); + assert_if_nil(a) + return #force_inline internal_inf(a, minimize, allocator) } -inf :: proc { int_inf, }; +inf :: proc { int_inf, } /* Set the `Int` to -Inf and optionally shrink it to the minimum backing size. @@ -217,10 +217,10 @@ int_minus_inf :: proc(a: ^Int, minimize := false, allocator := context.allocator /* Check that `a` is usable. */ - assert_if_nil(a); - return #force_inline internal_minus_inf(a, minimize, allocator); + assert_if_nil(a) + return #force_inline internal_minus_inf(a, minimize, allocator) } -minus_inf :: proc { int_inf, }; +minus_inf :: proc { int_inf, } /* Set the `Int` to NaN and optionally shrink it to the minimum backing size. @@ -229,72 +229,72 @@ int_nan :: proc(a: ^Int, minimize := false, allocator := context.allocator) -> ( /* Check that `a` is usable. */ - assert_if_nil(a); - return #force_inline internal_nan(a, minimize, allocator); + assert_if_nil(a) + return #force_inline internal_nan(a, minimize, allocator) } -nan :: proc { int_nan, }; +nan :: proc { int_nan, } power_of_two :: proc(a: ^Int, power: int, allocator := context.allocator) -> (err: Error) { /* Check that `a` is usable. */ - assert_if_nil(a); - return #force_inline internal_int_power_of_two(a, power, allocator); + assert_if_nil(a) + return #force_inline internal_int_power_of_two(a, power, allocator) } int_get_u128 :: proc(a: ^Int, allocator := context.allocator) -> (res: u128, err: Error) { /* Check that `a` is usable. */ - assert_if_nil(a); - return int_get(a, u128, allocator); + assert_if_nil(a) + return int_get(a, u128, allocator) } -get_u128 :: proc { int_get_u128, }; +get_u128 :: proc { int_get_u128, } int_get_i128 :: proc(a: ^Int, allocator := context.allocator) -> (res: i128, err: Error) { /* Check that `a` is usable. */ - assert_if_nil(a); - return int_get(a, i128, allocator); + assert_if_nil(a) + return int_get(a, i128, allocator) } -get_i128 :: proc { int_get_i128, }; +get_i128 :: proc { int_get_i128, } int_get_u64 :: proc(a: ^Int, allocator := context.allocator) -> (res: u64, err: Error) { /* Check that `a` is usable. */ - assert_if_nil(a); - return int_get(a, u64, allocator); + assert_if_nil(a) + return int_get(a, u64, allocator) } -get_u64 :: proc { int_get_u64, }; +get_u64 :: proc { int_get_u64, } int_get_i64 :: proc(a: ^Int, allocator := context.allocator) -> (res: i64, err: Error) { /* Check that `a` is usable. */ - assert_if_nil(a); - return int_get(a, i64, allocator); + assert_if_nil(a) + return int_get(a, i64, allocator) } -get_i64 :: proc { int_get_i64, }; +get_i64 :: proc { int_get_i64, } int_get_u32 :: proc(a: ^Int, allocator := context.allocator) -> (res: u32, err: Error) { /* Check that `a` is usable. */ - assert_if_nil(a); - return int_get(a, u32, allocator); + assert_if_nil(a) + return int_get(a, u32, allocator) } -get_u32 :: proc { int_get_u32, }; +get_u32 :: proc { int_get_u32, } int_get_i32 :: proc(a: ^Int, allocator := context.allocator) -> (res: i32, err: Error) { /* Check that `a` is usable. */ - assert_if_nil(a); - return int_get(a, i32, allocator); + assert_if_nil(a) + return int_get(a, i32, allocator) } -get_i32 :: proc { int_get_i32, }; +get_i32 :: proc { int_get_i32, } /* TODO: Think about using `count_bits` to check if the value could be returned completely, @@ -304,19 +304,19 @@ int_get :: proc(a: ^Int, $T: typeid, allocator := context.allocator) -> (res: T, /* Check that `a` is usable. */ - assert_if_nil(a); + assert_if_nil(a) #force_inline internal_clear_if_uninitialized(a, allocator) or_return; - return #force_inline internal_int_get(a, T); + return #force_inline internal_int_get(a, T) } -get :: proc { int_get, }; +get :: proc { int_get, } int_get_float :: proc(a: ^Int, allocator := context.allocator) -> (res: f64, err: Error) { /* Check that `a` is usable. */ - assert_if_nil(a); + assert_if_nil(a) #force_inline internal_clear_if_uninitialized(a, allocator) or_return; - return #force_inline internal_int_get_float(a); + return #force_inline internal_int_get_float(a) } /* @@ -326,9 +326,9 @@ count_bits :: proc(a: ^Int, allocator := context.allocator) -> (count: int, err: /* Check that `a` is usable. */ - assert_if_nil(a); + assert_if_nil(a) #force_inline internal_clear_if_uninitialized(a, allocator) or_return; - return #force_inline internal_count_bits(a), nil; + return #force_inline internal_count_bits(a), nil } /* @@ -339,109 +339,109 @@ int_count_lsb :: proc(a: ^Int, allocator := context.allocator) -> (count: int, e /* Check that `a` is usable. */ - assert_if_nil(a); + assert_if_nil(a) #force_inline internal_clear_if_uninitialized(a, allocator) or_return; - return #force_inline internal_int_count_lsb(a); + return #force_inline internal_int_count_lsb(a) } platform_count_lsb :: #force_inline proc(a: $T) -> (count: int) where intrinsics.type_is_integer(T) && intrinsics.type_is_unsigned(T) { - return int(intrinsics.count_trailing_zeros(a)) if a > 0 else 0; + return int(intrinsics.count_trailing_zeros(a)) if a > 0 else 0 } -count_lsb :: proc { int_count_lsb, platform_count_lsb, }; +count_lsb :: proc { int_count_lsb, platform_count_lsb, } int_random_digit :: proc(r: ^rnd.Rand = nil) -> (res: DIGIT) { when _DIGIT_BITS == 60 { // DIGIT = u64 - return DIGIT(rnd.uint64(r)) & _MASK; + return DIGIT(rnd.uint64(r)) & _MASK } else when _DIGIT_BITS == 28 { // DIGIT = u32 - return DIGIT(rnd.uint32(r)) & _MASK; + return DIGIT(rnd.uint32(r)) & _MASK } else { - panic("Unsupported DIGIT size."); + panic("Unsupported DIGIT size.") } - return 0; // We shouldn't get here. + return 0 // We shouldn't get here. } int_rand :: proc(dest: ^Int, bits: int, r: ^rnd.Rand = nil, allocator := context.allocator) -> (err: Error) { /* Check that `a` is usable. */ - assert_if_nil(dest); - return #force_inline internal_int_rand(dest, bits, r, allocator); + assert_if_nil(dest) + return #force_inline internal_int_rand(dest, bits, r, allocator) } -rand :: proc { int_rand, }; +rand :: proc { int_rand, } /* Internal helpers. */ assert_initialized :: proc(a: ^Int, loc := #caller_location) { - assert_if_nil(a); - assert(is_initialized(a), "`Int` was not properly initialized.", loc); + assert_if_nil(a) + assert(is_initialized(a), "`Int` was not properly initialized.", loc) } zero_unused :: proc(dest: ^Int, old_used := -1) { - assert_if_nil(dest); + assert_if_nil(dest) if ! #force_inline is_initialized(dest) { return; } #force_inline internal_zero_unused(dest, old_used); } clear_if_uninitialized_single :: proc(arg: ^Int, allocator := context.allocator) -> (err: Error) { - assert_if_nil(arg); - return #force_inline internal_clear_if_uninitialized_single(arg, allocator); + assert_if_nil(arg) + return #force_inline internal_clear_if_uninitialized_single(arg, allocator) } clear_if_uninitialized_multi :: proc(args: ..^Int, allocator := context.allocator) -> (err: Error) { - args := args; - assert_if_nil(..args); + args := args + assert_if_nil(..args) for i in &args { #force_inline internal_clear_if_uninitialized_single(i, allocator) or_return; } - return err; + return err } -clear_if_uninitialized :: proc {clear_if_uninitialized_single, clear_if_uninitialized_multi, }; +clear_if_uninitialized :: proc {clear_if_uninitialized_single, clear_if_uninitialized_multi, } error_if_immutable_single :: proc(arg: ^Int) -> (err: Error) { if arg != nil && .Immutable in arg.flags { return .Assignment_To_Immutable; } - return nil; + return nil } error_if_immutable_multi :: proc(args: ..^Int) -> (err: Error) { for i in args { if i != nil && .Immutable in i.flags { return .Assignment_To_Immutable; } } - return nil; + return nil } -error_if_immutable :: proc {error_if_immutable_single, error_if_immutable_multi, }; +error_if_immutable :: proc {error_if_immutable_single, error_if_immutable_multi, } /* Allocates several `Int`s at once. */ int_init_multi :: proc(integers: ..^Int, allocator := context.allocator) -> (err: Error) { - assert_if_nil(..integers); + assert_if_nil(..integers) - integers := integers; + integers := integers for a in &integers { #force_inline internal_clear(a, true, allocator) or_return; } - return nil; + return nil } -init_multi :: proc { int_init_multi, }; +init_multi :: proc { int_init_multi, } copy_digits :: proc(dest, src: ^Int, digits: int, offset := int(0), allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator /* Check that `src` is usable and `dest` isn't immutable. */ - assert_if_nil(dest, src); + assert_if_nil(dest, src) #force_inline internal_clear_if_uninitialized(src) or_return; - return #force_inline internal_copy_digits(dest, src, digits, offset); + return #force_inline internal_copy_digits(dest, src, digits, offset) } /* @@ -451,17 +451,17 @@ copy_digits :: proc(dest, src: ^Int, digits: int, offset := int(0), allocator := Typically very fast. Also fixes the sign if there are no more leading digits. */ clamp :: proc(a: ^Int, allocator := context.allocator) -> (err: Error) { - assert_if_nil(a); + assert_if_nil(a) #force_inline internal_clear_if_uninitialized(a, allocator) or_return; for a.used > 0 && a.digit[a.used - 1] == 0 { - a.used -= 1; + a.used -= 1 } if z, _ := is_zero(a); z { - a.sign = .Zero_or_Positive; + a.sign = .Zero_or_Positive } - return nil; + return nil } @@ -469,15 +469,15 @@ clamp :: proc(a: ^Int, allocator := context.allocator) -> (err: Error) { Size binary representation */ int_to_bytes_size :: proc(a: ^Int, signed := false, allocator := context.allocator) -> (size_in_bytes: int, err: Error) { - assert_if_nil(a); + assert_if_nil(a) #force_inline internal_clear_if_uninitialized(a, allocator) or_return; - size_in_bits := internal_count_bits(a); + size_in_bits := internal_count_bits(a) - size_in_bytes = (size_in_bits / 8); - size_in_bytes += 0 if size_in_bits % 8 == 0 else 1; - size_in_bytes += 1 if signed else 0; - return; + size_in_bytes = (size_in_bits / 8) + size_in_bytes += 0 if size_in_bits % 8 == 0 else 1 + size_in_bytes += 1 if signed else 0 + return } /* @@ -485,22 +485,22 @@ int_to_bytes_size :: proc(a: ^Int, signed := false, allocator := context.allocat If `a` is negative and we ask for the default unsigned representation, we return abs(a). */ int_to_bytes_little :: proc(a: ^Int, buf: []u8, signed := false, allocator := context.allocator) -> (err: Error) { - assert_if_nil(a); + assert_if_nil(a) - size_in_bytes := int_to_bytes_size(a, signed, allocator) or_return; - l := len(buf); + size_in_bytes := int_to_bytes_size(a, signed, allocator) or_return + l := len(buf) if size_in_bytes > l { return .Buffer_Overflow; } - size_in_bits := internal_count_bits(a); - i := 0; + size_in_bits := internal_count_bits(a) + i := 0 if signed { - buf[l - 1] = 1 if a.sign == .Negative else 0; + buf[l - 1] = 1 if a.sign == .Negative else 0 } for offset := 0; offset < size_in_bits; offset += 8 { - bits, _ := internal_int_bitfield_extract(a, offset, 8); - buf[i] = u8(bits & 255); i += 1; + bits, _ := internal_int_bitfield_extract(a, offset, 8) + buf[i] = u8(bits & 255); i += 1 } - return; + return } /* @@ -508,23 +508,23 @@ int_to_bytes_little :: proc(a: ^Int, buf: []u8, signed := false, allocator := co If `a` is negative and we ask for the default unsigned representation, we return abs(a). */ int_to_bytes_big :: proc(a: ^Int, buf: []u8, signed := false, allocator := context.allocator) -> (err: Error) { - assert_if_nil(a); + assert_if_nil(a) - size_in_bytes := int_to_bytes_size(a, signed, allocator) or_return; - l := len(buf); + size_in_bytes := int_to_bytes_size(a, signed, allocator) or_return + l := len(buf) if size_in_bytes > l { return .Buffer_Overflow; } - size_in_bits := internal_count_bits(a); - i := l - 1; + size_in_bits := internal_count_bits(a) + i := l - 1 if signed { - buf[0] = 1 if a.sign == .Negative else 0; + buf[0] = 1 if a.sign == .Negative else 0 } for offset := 0; offset < size_in_bits; offset += 8 { - bits, _ := internal_int_bitfield_extract(a, offset, 8); - buf[i] = u8(bits & 255); i -= 1; + bits, _ := internal_int_bitfield_extract(a, offset, 8) + buf[i] = u8(bits & 255); i -= 1 } - return; + return } /* @@ -532,35 +532,35 @@ int_to_bytes_big :: proc(a: ^Int, buf: []u8, signed := false, allocator := conte If `a` is negative when asking for an unsigned number, we return an error like Python does. */ int_to_bytes_little_python :: proc(a: ^Int, buf: []u8, signed := false, allocator := context.allocator) -> (err: Error) { - assert_if_nil(a); + assert_if_nil(a) if !signed && a.sign == .Negative { return .Invalid_Argument; } - l := len(buf); - size_in_bytes := int_to_bytes_size(a, signed, allocator) or_return; + l := len(buf) + size_in_bytes := int_to_bytes_size(a, signed, allocator) or_return if size_in_bytes > l { return .Buffer_Overflow; } if a.sign == .Negative { - t := &Int{}; - defer destroy(t); - internal_complement(t, a, allocator) or_return; + t := &Int{} + defer destroy(t) + internal_complement(t, a, allocator) or_return - size_in_bits := internal_count_bits(t); - i := 0; + size_in_bits := internal_count_bits(t) + i := 0 for offset := 0; offset < size_in_bits; offset += 8 { - bits, _ := internal_int_bitfield_extract(t, offset, 8); - buf[i] = 255 - u8(bits & 255); i += 1; + bits, _ := internal_int_bitfield_extract(t, offset, 8) + buf[i] = 255 - u8(bits & 255); i += 1 } - buf[l-1] = 255; + buf[l-1] = 255 } else { - size_in_bits := internal_count_bits(a); - i := 0; + size_in_bits := internal_count_bits(a) + i := 0 for offset := 0; offset < size_in_bits; offset += 8 { - bits, _ := internal_int_bitfield_extract(a, offset, 8); - buf[i] = u8(bits & 255); i += 1; + bits, _ := internal_int_bitfield_extract(a, offset, 8) + buf[i] = u8(bits & 255); i += 1 } } - return; + return } /* @@ -568,29 +568,29 @@ int_to_bytes_little_python :: proc(a: ^Int, buf: []u8, signed := false, allocato If `a` is negative when asking for an unsigned number, we return an error like Python does. */ int_to_bytes_big_python :: proc(a: ^Int, buf: []u8, signed := false, allocator := context.allocator) -> (err: Error) { - assert_if_nil(a); + assert_if_nil(a) if !signed && a.sign == .Negative { return .Invalid_Argument; } if a.sign == .Zero_or_Positive { return int_to_bytes_big(a, buf, signed, allocator); } - l := len(buf); - size_in_bytes := int_to_bytes_size(a, signed, allocator) or_return; + l := len(buf) + size_in_bytes := int_to_bytes_size(a, signed, allocator) or_return if size_in_bytes > l { return .Buffer_Overflow; } - t := &Int{}; - defer destroy(t); + t := &Int{} + defer destroy(t) - internal_complement(t, a, allocator) or_return; + internal_complement(t, a, allocator) or_return - size_in_bits := internal_count_bits(t); - i := l - 1; + size_in_bits := internal_count_bits(t) + i := l - 1 for offset := 0; offset < size_in_bits; offset += 8 { - bits, _ := internal_int_bitfield_extract(t, offset, 8); - buf[i] = 255 - u8(bits & 255); i -= 1; + bits, _ := internal_int_bitfield_extract(t, offset, 8) + buf[i] = 255 - u8(bits & 255); i -= 1 } - buf[0] = 255; + buf[0] = 255 - return; + return } /* @@ -598,36 +598,36 @@ int_to_bytes_big_python :: proc(a: ^Int, buf: []u8, signed := false, allocator : Sign is detected from the first byte if `signed` is true. */ int_from_bytes_big :: proc(a: ^Int, buf: []u8, signed := false, allocator := context.allocator) -> (err: Error) { - assert_if_nil(a); - buf := buf; - l := len(buf); + assert_if_nil(a) + buf := buf + l := len(buf) if l == 0 { return .Invalid_Argument; } - sign: Sign; - size_in_bits := l * 8; + sign: Sign + size_in_bits := l * 8 if signed { /* First byte denotes the sign. */ - size_in_bits -= 8; + size_in_bits -= 8 } - size_in_digits := (size_in_bits + _DIGIT_BITS - 1) / _DIGIT_BITS; - size_in_digits += 0 if size_in_bits % 8 == 0 else 1; - internal_zero(a, false, allocator) or_return; - internal_grow(a, size_in_digits, false, allocator) or_return; + size_in_digits := (size_in_bits + _DIGIT_BITS - 1) / _DIGIT_BITS + size_in_digits += 0 if size_in_bits % 8 == 0 else 1 + internal_zero(a, false, allocator) or_return + internal_grow(a, size_in_digits, false, allocator) or_return if signed { - sign = .Zero_or_Positive if buf[0] == 0 else .Negative; - buf = buf[1:]; + sign = .Zero_or_Positive if buf[0] == 0 else .Negative + buf = buf[1:] } for v in buf { - internal_shl(a, a, 8) or_return; - a.digit[0] |= DIGIT(v); + internal_shl(a, a, 8) or_return + a.digit[0] |= DIGIT(v) } - a.sign = sign; - a.used = size_in_digits; - return internal_clamp(a); + a.sign = sign + a.used = size_in_digits + return internal_clamp(a) } /* @@ -635,45 +635,45 @@ int_from_bytes_big :: proc(a: ^Int, buf: []u8, signed := false, allocator := con Sign is detected from the first byte if `signed` is true. */ int_from_bytes_big_python :: proc(a: ^Int, buf: []u8, signed := false, allocator := context.allocator) -> (err: Error) { - assert_if_nil(a); - buf := buf; - l := len(buf); + assert_if_nil(a) + buf := buf + l := len(buf) if l == 0 { return .Invalid_Argument; } - sign: Sign; - size_in_bits := l * 8; + sign: Sign + size_in_bits := l * 8 if signed { /* First byte denotes the sign. */ - size_in_bits -= 8; + size_in_bits -= 8 } - size_in_digits := (size_in_bits + _DIGIT_BITS - 1) / _DIGIT_BITS; - size_in_digits += 0 if size_in_bits % 8 == 0 else 1; - internal_zero(a, false, allocator) or_return; - internal_grow(a, size_in_digits, false, allocator) or_return; + size_in_digits := (size_in_bits + _DIGIT_BITS - 1) / _DIGIT_BITS + size_in_digits += 0 if size_in_bits % 8 == 0 else 1 + internal_zero(a, false, allocator) or_return + internal_grow(a, size_in_digits, false, allocator) or_return if signed { - sign = .Zero_or_Positive if buf[0] == 0 else .Negative; - buf = buf[1:]; + sign = .Zero_or_Positive if buf[0] == 0 else .Negative + buf = buf[1:] } for v in buf { - internal_shl(a, a, 8) or_return; + internal_shl(a, a, 8) or_return if signed && sign == .Negative { - a.digit[0] |= DIGIT(255 - v); + a.digit[0] |= DIGIT(255 - v) } else { - a.digit[0] |= DIGIT(v); + a.digit[0] |= DIGIT(v) } } - a.sign = sign; - a.used = size_in_digits; - internal_clamp(a) or_return; + a.sign = sign + a.used = size_in_digits + internal_clamp(a) or_return if signed && sign == .Negative { - return internal_sub(a, a, 1); + return internal_sub(a, a, 1) } - return nil; + return nil } /* @@ -681,37 +681,37 @@ int_from_bytes_big_python :: proc(a: ^Int, buf: []u8, signed := false, allocator Sign is detected from the last byte if `signed` is true. */ int_from_bytes_little :: proc(a: ^Int, buf: []u8, signed := false, allocator := context.allocator) -> (err: Error) { - assert_if_nil(a); - buf := buf; - l := len(buf); + assert_if_nil(a) + buf := buf + l := len(buf) if l == 0 { return .Invalid_Argument; } - sign: Sign; - size_in_bits := l * 8; + sign: Sign + size_in_bits := l * 8 if signed { /* First byte denotes the sign. */ - size_in_bits -= 8; + size_in_bits -= 8 } - size_in_digits := (size_in_bits + _DIGIT_BITS - 1) / _DIGIT_BITS; - size_in_digits += 0 if size_in_bits % 8 == 0 else 1; - internal_zero(a, false, allocator) or_return; - internal_grow(a, size_in_digits, false, allocator) or_return; + size_in_digits := (size_in_bits + _DIGIT_BITS - 1) / _DIGIT_BITS + size_in_digits += 0 if size_in_bits % 8 == 0 else 1 + internal_zero(a, false, allocator) or_return + internal_grow(a, size_in_digits, false, allocator) or_return if signed { - sign = .Zero_or_Positive if buf[l-1] == 0 else .Negative; - buf = buf[:l-1]; - l -= 1; + sign = .Zero_or_Positive if buf[l-1] == 0 else .Negative + buf = buf[:l-1] + l -= 1 } for _, i in buf { - internal_shl(a, a, 8) or_return; - a.digit[0] |= DIGIT(buf[l-i-1]); + internal_shl(a, a, 8) or_return + a.digit[0] |= DIGIT(buf[l-i-1]) } - a.sign = sign; - a.used = size_in_digits; - return internal_clamp(a); + a.sign = sign + a.used = size_in_digits + return internal_clamp(a) } /* @@ -719,67 +719,67 @@ int_from_bytes_little :: proc(a: ^Int, buf: []u8, signed := false, allocator := Sign is detected from the first byte if `signed` is true. */ int_from_bytes_little_python :: proc(a: ^Int, buf: []u8, signed := false, allocator := context.allocator) -> (err: Error) { - assert_if_nil(a); - buf := buf; - l := len(buf); + assert_if_nil(a) + buf := buf + l := len(buf) if l == 0 { return .Invalid_Argument; } - sign: Sign; - size_in_bits := l * 8; + sign: Sign + size_in_bits := l * 8 if signed { /* First byte denotes the sign. */ - size_in_bits -= 8; + size_in_bits -= 8 } - size_in_digits := (size_in_bits + _DIGIT_BITS - 1) / _DIGIT_BITS; - size_in_digits += 0 if size_in_bits % 8 == 0 else 1; - internal_zero(a, false, allocator) or_return; - internal_grow(a, size_in_digits, false, allocator) or_return; + size_in_digits := (size_in_bits + _DIGIT_BITS - 1) / _DIGIT_BITS + size_in_digits += 0 if size_in_bits % 8 == 0 else 1 + internal_zero(a, false, allocator) or_return + internal_grow(a, size_in_digits, false, allocator) or_return if signed { - sign = .Zero_or_Positive if buf[l-1] == 0 else .Negative; - buf = buf[:l-1]; - l -= 1; + sign = .Zero_or_Positive if buf[l-1] == 0 else .Negative + buf = buf[:l-1] + l -= 1 } for _, i in buf { - internal_shl(a, a, 8) or_return; + internal_shl(a, a, 8) or_return if signed && sign == .Negative { - a.digit[0] |= DIGIT(255 - buf[l-i-1]); + a.digit[0] |= DIGIT(255 - buf[l-i-1]) } else { - a.digit[0] |= DIGIT(buf[l-i-1]); + a.digit[0] |= DIGIT(buf[l-i-1]) } } - a.sign = sign; - a.used = size_in_digits; - internal_clamp(a) or_return; + a.sign = sign + a.used = size_in_digits + internal_clamp(a) or_return if signed && sign == .Negative { - return internal_sub(a, a, 1); + return internal_sub(a, a, 1) } - return nil; + return nil } /* Initialize constants. */ -INT_ONE, INT_ZERO, INT_MINUS_ONE, INT_INF, INT_MINUS_INF, INT_NAN := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}; +INT_ONE, INT_ZERO, INT_MINUS_ONE, INT_INF, INT_MINUS_INF, INT_NAN := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{} initialize_constants :: proc() -> (res: int) { - internal_set( INT_ZERO, 0); INT_ZERO.flags = {.Immutable}; - internal_set( INT_ONE, 1); INT_ONE.flags = {.Immutable}; - internal_set(INT_MINUS_ONE, -1); INT_MINUS_ONE.flags = {.Immutable}; + internal_set( INT_ZERO, 0); INT_ZERO.flags = {.Immutable} + internal_set( INT_ONE, 1); INT_ONE.flags = {.Immutable} + internal_set(INT_MINUS_ONE, -1); INT_MINUS_ONE.flags = {.Immutable} /* We set these special values to -1 or 1 so they don't get mistake for zero accidentally. This allows for shortcut tests of is_zero as .used == 0. */ - internal_set( INT_NAN, 1); INT_NAN.flags = {.Immutable, .NaN}; - internal_set( INT_INF, 1); INT_INF.flags = {.Immutable, .Inf}; - internal_set( INT_INF, -1); INT_MINUS_INF.flags = {.Immutable, .Inf}; + internal_set( INT_NAN, 1); INT_NAN.flags = {.Immutable, .NaN} + internal_set( INT_INF, 1); INT_INF.flags = {.Immutable, .Inf} + internal_set( INT_INF, -1); INT_MINUS_INF.flags = {.Immutable, .Inf} - return _DEFAULT_MUL_KARATSUBA_CUTOFF; + return _DEFAULT_MUL_KARATSUBA_CUTOFF } /* @@ -787,14 +787,14 @@ initialize_constants :: proc() -> (res: int) { Optional for an EXE, as this would be called at the very end of a process. */ destroy_constants :: proc() { - internal_destroy(INT_ONE, INT_ZERO, INT_MINUS_ONE, INT_INF, INT_MINUS_INF, INT_NAN); + internal_destroy(INT_ONE, INT_ZERO, INT_MINUS_ONE, INT_INF, INT_MINUS_INF, INT_NAN) } assert_if_nil :: #force_inline proc(integers: ..^Int, loc := #caller_location) { - integers := integers; + integers := integers for i in &integers { - assert(i != nil, "(nil)", loc); + assert(i != nil, "(nil)", loc) } } diff --git a/core/math/big/internal.odin b/core/math/big/internal.odin index 9422067ae..033bc11a2 100644 --- a/core/math/big/internal.odin +++ b/core/math/big/internal.odin @@ -43,43 +43,43 @@ import rnd "core:math/rand" `dest`, `a` and `b` != `nil` and have been initalized. */ internal_int_add_unsigned :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) { - dest := dest; x := a; y := b; - context.allocator = allocator; + dest := dest; x := a; y := b + context.allocator = allocator - old_used, min_used, max_used, i: int; + old_used, min_used, max_used, i: int if x.used < y.used { - x, y = y, x; + x, y = y, x } - min_used = y.used; - max_used = x.used; - old_used = dest.used; + min_used = y.used + max_used = x.used + old_used = dest.used - internal_grow(dest, max(max_used + 1, _DEFAULT_DIGIT_COUNT)) or_return; - dest.used = max_used + 1; + internal_grow(dest, max(max_used + 1, _DEFAULT_DIGIT_COUNT)) or_return + dest.used = max_used + 1 /* All parameters have been initialized. */ /* Zero the carry */ - carry := DIGIT(0); + carry := DIGIT(0) #no_bounds_check for i = 0; i < min_used; i += 1 { /* Compute the sum one _DIGIT at a time. dest[i] = a[i] + b[i] + carry; */ - dest.digit[i] = x.digit[i] + y.digit[i] + carry; + dest.digit[i] = x.digit[i] + y.digit[i] + carry /* Compute carry */ - carry = dest.digit[i] >> _DIGIT_BITS; + carry = dest.digit[i] >> _DIGIT_BITS /* Mask away carry from result digit. */ - dest.digit[i] &= _MASK; + dest.digit[i] &= _MASK } if min_used != max_used { @@ -88,32 +88,32 @@ internal_int_add_unsigned :: proc(dest, a, b: ^Int, allocator := context.allocat If A or B has more digits, add those in. */ #no_bounds_check for ; i < max_used; i += 1 { - dest.digit[i] = x.digit[i] + carry; + dest.digit[i] = x.digit[i] + carry /* Compute carry */ - carry = dest.digit[i] >> _DIGIT_BITS; + carry = dest.digit[i] >> _DIGIT_BITS /* Mask away carry from result digit. */ - dest.digit[i] &= _MASK; + dest.digit[i] &= _MASK } } /* Add remaining carry. */ - dest.digit[i] = carry; + dest.digit[i] = carry /* Zero remainder. */ - internal_zero_unused(dest, old_used); + internal_zero_unused(dest, old_used) /* Adjust dest.used based on leading zeroes. */ - return internal_clamp(dest); + return internal_clamp(dest) } -internal_add_unsigned :: proc { internal_int_add_unsigned, }; +internal_add_unsigned :: proc { internal_int_add_unsigned, } /* Low-level addition, signed. Handbook of Applied Cryptography, algorithm 14.7. @@ -122,14 +122,14 @@ internal_add_unsigned :: proc { internal_int_add_unsigned, }; `dest`, `a` and `b` != `nil` and have been initalized. */ internal_int_add_signed :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) { - x := a; y := b; - context.allocator = allocator; + x := a; y := b + context.allocator = allocator /* Handle both negative or both positive. */ if x.sign == y.sign { - dest.sign = x.sign; - return #force_inline internal_int_add_unsigned(dest, x, y); + dest.sign = x.sign + return #force_inline internal_int_add_unsigned(dest, x, y) } /* @@ -138,13 +138,13 @@ internal_int_add_signed :: proc(dest, a, b: ^Int, allocator := context.allocator The result gets the sign of the one with the greater magnitude. */ if #force_inline internal_cmp_mag(a, b) == -1 { - x, y = y, x; + x, y = y, x } - dest.sign = x.sign; - return #force_inline internal_int_sub_unsigned(dest, x, y); + dest.sign = x.sign + return #force_inline internal_int_sub_unsigned(dest, x, y) } -internal_add_signed :: proc { internal_int_add_signed, }; +internal_add_signed :: proc { internal_int_add_signed, } /* Low-level addition Int+DIGIT, signed. Handbook of Applied Cryptography, algorithm 14.7. @@ -154,9 +154,9 @@ internal_add_signed :: proc { internal_int_add_signed, }; `dest` is large enough (a.used + 1) to fit result. */ internal_int_add_digit :: proc(dest, a: ^Int, digit: DIGIT, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator - internal_grow(dest, a.used + 1) or_return; + internal_grow(dest, a.used + 1) or_return /* Fast paths for destination and input Int being the same. */ @@ -165,17 +165,17 @@ internal_int_add_digit :: proc(dest, a: ^Int, digit: DIGIT, allocator := context Fast path for dest.digit[0] + digit fits in dest.digit[0] without overflow. */ if dest.sign == .Zero_or_Positive && (dest.digit[0] + digit < _DIGIT_MAX) { - dest.digit[0] += digit; - dest.used += 1; - return internal_clamp(dest); + dest.digit[0] += digit + dest.used += 1 + return internal_clamp(dest) } /* Can be subtracted from dest.digit[0] without underflow. */ if a.sign == .Negative && (dest.digit[0] > digit) { - dest.digit[0] -= digit; - dest.used += 1; - return internal_clamp(dest); + dest.digit[0] -= digit + dest.used += 1 + return internal_clamp(dest) } } @@ -186,7 +186,7 @@ internal_int_add_digit :: proc(dest, a: ^Int, digit: DIGIT, allocator := context /* Temporarily fix `a`'s sign. */ - a.sign = .Zero_or_Positive; + a.sign = .Zero_or_Positive /* dest = |a| - digit */ @@ -194,22 +194,22 @@ internal_int_add_digit :: proc(dest, a: ^Int, digit: DIGIT, allocator := context /* Restore a's sign. */ - a.sign = .Negative; - return err; + a.sign = .Negative + return err } /* Restore sign and set `dest` sign. */ - a.sign = .Negative; - dest.sign = .Negative; + a.sign = .Negative + dest.sign = .Negative - return internal_clamp(dest); + return internal_clamp(dest) } /* Remember the currently used number of digits in `dest`. */ - old_used := dest.used; + old_used := dest.used /* If `a` is positive @@ -218,53 +218,53 @@ internal_int_add_digit :: proc(dest, a: ^Int, digit: DIGIT, allocator := context /* Add digits, use `carry`. */ - i: int; - carry := digit; + i: int + carry := digit #no_bounds_check for i = 0; i < a.used; i += 1 { - dest.digit[i] = a.digit[i] + carry; - carry = dest.digit[i] >> _DIGIT_BITS; - dest.digit[i] &= _MASK; + dest.digit[i] = a.digit[i] + carry + carry = dest.digit[i] >> _DIGIT_BITS + dest.digit[i] &= _MASK } /* Set final carry. */ - dest.digit[i] = carry; + dest.digit[i] = carry /* Set `dest` size. */ - dest.used = a.used + 1; + dest.used = a.used + 1 } else { /* `a` was negative and |a| < digit. */ - dest.used = 1; + dest.used = 1 /* The result is a single DIGIT. */ - dest.digit[0] = digit - a.digit[0] if a.used == 1 else digit; + dest.digit[0] = digit - a.digit[0] if a.used == 1 else digit } /* Sign is always positive. */ - dest.sign = .Zero_or_Positive; + dest.sign = .Zero_or_Positive /* Zero remainder. */ - internal_zero_unused(dest, old_used); + internal_zero_unused(dest, old_used) /* Adjust dest.used based on leading zeroes. */ - return internal_clamp(dest); + return internal_clamp(dest) } -internal_add :: proc { internal_int_add_signed, internal_int_add_digit, }; +internal_add :: proc { internal_int_add_signed, internal_int_add_digit, } internal_int_incr :: proc(dest: ^Int, allocator := context.allocator) -> (err: Error) { - return #force_inline internal_add(dest, dest, 1); + return #force_inline internal_add(dest, dest, 1) } -internal_incr :: proc { internal_int_incr, }; +internal_incr :: proc { internal_int_incr, } /* Low-level subtraction, dest = number - decrease. Assumes |number| > |decrease|. @@ -274,66 +274,66 @@ internal_incr :: proc { internal_int_incr, }; `dest`, `number` and `decrease` != `nil` and have been initalized. */ internal_int_sub_unsigned :: proc(dest, number, decrease: ^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator - dest := dest; x := number; y := decrease; - old_used := dest.used; - min_used := y.used; - max_used := x.used; - i: int; + dest := dest; x := number; y := decrease + old_used := dest.used + min_used := y.used + max_used := x.used + i: int - grow(dest, max(max_used, _DEFAULT_DIGIT_COUNT)) or_return; - dest.used = max_used; + grow(dest, max(max_used, _DEFAULT_DIGIT_COUNT)) or_return + dest.used = max_used /* All parameters have been initialized. */ - borrow := DIGIT(0); + borrow := DIGIT(0) #no_bounds_check for i = 0; i < min_used; i += 1 { - dest.digit[i] = (x.digit[i] - y.digit[i] - borrow); + dest.digit[i] = (x.digit[i] - y.digit[i] - borrow) /* borrow = carry bit of dest[i] Note this saves performing an AND operation since if a carry does occur, it will propagate all the way to the MSB. As a result a single shift is enough to get the carry. */ - borrow = dest.digit[i] >> ((size_of(DIGIT) * 8) - 1); + borrow = dest.digit[i] >> ((size_of(DIGIT) * 8) - 1) /* Clear borrow from dest[i]. */ - dest.digit[i] &= _MASK; + dest.digit[i] &= _MASK } /* Now copy higher words if any, e.g. if A has more digits than B */ #no_bounds_check for ; i < max_used; i += 1 { - dest.digit[i] = x.digit[i] - borrow; + dest.digit[i] = x.digit[i] - borrow /* borrow = carry bit of dest[i] Note this saves performing an AND operation since if a carry does occur, it will propagate all the way to the MSB. As a result a single shift is enough to get the carry. */ - borrow = dest.digit[i] >> ((size_of(DIGIT) * 8) - 1); + borrow = dest.digit[i] >> ((size_of(DIGIT) * 8) - 1) /* Clear borrow from dest[i]. */ - dest.digit[i] &= _MASK; + dest.digit[i] &= _MASK } /* Zero remainder. */ - internal_zero_unused(dest, old_used); + internal_zero_unused(dest, old_used) /* Adjust dest.used based on leading zeroes. */ - return internal_clamp(dest); + return internal_clamp(dest) } -internal_sub_unsigned :: proc { internal_int_sub_unsigned, }; +internal_sub_unsigned :: proc { internal_int_sub_unsigned, } /* Low-level subtraction, signed. Handbook of Applied Cryptography, algorithm 14.9. @@ -343,16 +343,16 @@ internal_sub_unsigned :: proc { internal_int_sub_unsigned, }; `dest`, `number` and `decrease` != `nil` and have been initalized. */ internal_int_sub_signed :: proc(dest, number, decrease: ^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator - number := number; decrease := decrease; + number := number; decrease := decrease if number.sign != decrease.sign { /* Subtract a negative from a positive, OR subtract a positive from a negative. In either case, ADD their magnitudes and use the sign of the first number. */ - dest.sign = number.sign; - return #force_inline internal_int_add_unsigned(dest, number, decrease); + dest.sign = number.sign + return #force_inline internal_int_add_unsigned(dest, number, decrease) } /* @@ -364,16 +364,16 @@ internal_int_sub_signed :: proc(dest, number, decrease: ^Int, allocator := conte The second has a larger magnitude. The result has the *opposite* sign from the first number. */ - dest.sign = .Negative if number.sign == .Zero_or_Positive else .Zero_or_Positive; - number, decrease = decrease, number; + dest.sign = .Negative if number.sign == .Zero_or_Positive else .Zero_or_Positive + number, decrease = decrease, number } else { /* The first has a larger or equal magnitude. Copy the sign from the first. */ - dest.sign = number.sign; + dest.sign = number.sign } - return #force_inline internal_int_sub_unsigned(dest, number, decrease); + return #force_inline internal_int_sub_unsigned(dest, number, decrease) } /* @@ -385,11 +385,11 @@ internal_int_sub_signed :: proc(dest, number, decrease: ^Int, allocator := conte `dest` is large enough (number.used + 1) to fit result. */ internal_int_sub_digit :: proc(dest, number: ^Int, digit: DIGIT, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator - internal_grow(dest, number.used + 1) or_return; + internal_grow(dest, number.used + 1) or_return - dest := dest; digit := digit; + dest := dest; digit := digit /* All parameters have been initialized. @@ -400,15 +400,15 @@ internal_int_sub_digit :: proc(dest, number: ^Int, digit: DIGIT, allocator := co Fast path for `dest` is negative and unsigned addition doesn't overflow the lowest digit. */ if dest.sign == .Negative && (dest.digit[0] + digit < _DIGIT_MAX) { - dest.digit[0] += digit; - return nil; + dest.digit[0] += digit + return nil } /* Can be subtracted from dest.digit[0] without underflow. */ if number.sign == .Zero_or_Positive && (dest.digit[0] > digit) { - dest.digit[0] -= digit; - return nil; + dest.digit[0] -= digit + return nil } } @@ -416,58 +416,58 @@ internal_int_sub_digit :: proc(dest, number: ^Int, digit: DIGIT, allocator := co If `a` is negative, just do an unsigned addition (with fudged signs). */ if number.sign == .Negative { - t := number; - t.sign = .Zero_or_Positive; + t := number + t.sign = .Zero_or_Positive - err = #force_inline internal_int_add_digit(dest, t, digit); - dest.sign = .Negative; + err = #force_inline internal_int_add_digit(dest, t, digit) + dest.sign = .Negative - internal_clamp(dest); - return err; + internal_clamp(dest) + return err } - old_used := dest.used; + old_used := dest.used /* if `a`<= digit, simply fix the single digit. */ if number.used == 1 && (number.digit[0] <= digit) || number.used == 0 { - dest.digit[0] = digit - number.digit[0] if number.used == 1 else digit; - dest.sign = .Negative; - dest.used = 1; + dest.digit[0] = digit - number.digit[0] if number.used == 1 else digit + dest.sign = .Negative + dest.used = 1 } else { - dest.sign = .Zero_or_Positive; - dest.used = number.used; + dest.sign = .Zero_or_Positive + dest.used = number.used /* Subtract with carry. */ - carry := digit; + carry := digit #no_bounds_check for i := 0; i < number.used; i += 1 { - dest.digit[i] = number.digit[i] - carry; - carry = dest.digit[i] >> (_DIGIT_TYPE_BITS - 1); - dest.digit[i] &= _MASK; + dest.digit[i] = number.digit[i] - carry + carry = dest.digit[i] >> (_DIGIT_TYPE_BITS - 1) + dest.digit[i] &= _MASK } } /* Zero remainder. */ - internal_zero_unused(dest, old_used); + internal_zero_unused(dest, old_used) /* Adjust dest.used based on leading zeroes. */ - return internal_clamp(dest); + return internal_clamp(dest) } -internal_sub :: proc { internal_int_sub_signed, internal_int_sub_digit, }; +internal_sub :: proc { internal_int_sub_signed, internal_int_sub_digit, } internal_int_decr :: proc(dest: ^Int, allocator := context.allocator) -> (err: Error) { - return #force_inline internal_sub(dest, dest, 1); + return #force_inline internal_sub(dest, dest, 1) } -internal_decr :: proc { internal_int_decr, }; +internal_decr :: proc { internal_int_decr, } /* dest = src / 2 @@ -477,38 +477,38 @@ internal_decr :: proc { internal_int_decr, }; We make no allocations here. */ internal_int_shr1 :: proc(dest, src: ^Int) -> (err: Error) { - old_used := dest.used; dest.used = src.used; + old_used := dest.used; dest.used = src.used /* Carry */ - fwd_carry := DIGIT(0); + fwd_carry := DIGIT(0) #no_bounds_check for x := dest.used - 1; x >= 0; x -= 1 { /* Get the carry for the next iteration. */ - src_digit := src.digit[x]; - carry := src_digit & 1; + src_digit := src.digit[x] + carry := src_digit & 1 /* Shift the current digit, add in carry and store. */ - dest.digit[x] = (src_digit >> 1) | (fwd_carry << (_DIGIT_BITS - 1)); + dest.digit[x] = (src_digit >> 1) | (fwd_carry << (_DIGIT_BITS - 1)) /* Forward carry to next iteration. */ - fwd_carry = carry; + fwd_carry = carry } /* Zero remainder. */ - internal_zero_unused(dest, old_used); + internal_zero_unused(dest, old_used) /* Adjust dest.used based on leading zeroes. */ - dest.sign = src.sign; - return internal_clamp(dest); + dest.sign = src.sign + return internal_clamp(dest) } /* @@ -516,121 +516,121 @@ internal_int_shr1 :: proc(dest, src: ^Int) -> (err: Error) { dest = src << 1 */ internal_int_shl1 :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator - internal_copy(dest, src) or_return; + internal_copy(dest, src) or_return /* Grow `dest` to accommodate the additional bits. */ - digits_needed := dest.used + 1; - internal_grow(dest, digits_needed) or_return; - dest.used = digits_needed; + digits_needed := dest.used + 1 + internal_grow(dest, digits_needed) or_return + dest.used = digits_needed - mask := (DIGIT(1) << uint(1)) - DIGIT(1); - shift := DIGIT(_DIGIT_BITS - 1); - carry := DIGIT(0); + mask := (DIGIT(1) << uint(1)) - DIGIT(1) + shift := DIGIT(_DIGIT_BITS - 1) + carry := DIGIT(0) #no_bounds_check for x:= 0; x < dest.used; x+= 1 { - fwd_carry := (dest.digit[x] >> shift) & mask; - dest.digit[x] = (dest.digit[x] << uint(1) | carry) & _MASK; - carry = fwd_carry; + fwd_carry := (dest.digit[x] >> shift) & mask + dest.digit[x] = (dest.digit[x] << uint(1) | carry) & _MASK + carry = fwd_carry } /* Use final carry. */ if carry != 0 { - dest.digit[dest.used] = carry; - dest.used += 1; + dest.digit[dest.used] = carry + dest.used += 1 } - return internal_clamp(dest); + return internal_clamp(dest) } /* Multiply by a DIGIT. */ internal_int_mul_digit :: proc(dest, src: ^Int, multiplier: DIGIT, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; - assert_if_nil(dest, src); + context.allocator = allocator + assert_if_nil(dest, src) if multiplier == 0 { - return internal_zero(dest); + return internal_zero(dest) } if multiplier == 1 { - return internal_copy(dest, src); + return internal_copy(dest, src) } /* Power of two? */ if multiplier == 2 { - return #force_inline internal_int_shl1(dest, src); + return #force_inline internal_int_shl1(dest, src) } if #force_inline platform_int_is_power_of_two(int(multiplier)) { - ix := internal_log(multiplier, 2) or_return; - return internal_shl(dest, src, ix); + ix := internal_log(multiplier, 2) or_return + return internal_shl(dest, src, ix) } /* Ensure `dest` is big enough to hold `src` * `multiplier`. */ - grow(dest, max(src.used + 1, _DEFAULT_DIGIT_COUNT)) or_return; + grow(dest, max(src.used + 1, _DEFAULT_DIGIT_COUNT)) or_return /* Save the original used count. */ - old_used := dest.used; + old_used := dest.used /* Set the sign. */ - dest.sign = src.sign; + dest.sign = src.sign /* Set up carry. */ - carry := _WORD(0); + carry := _WORD(0) /* Compute columns. */ - ix := 0; + ix := 0 #no_bounds_check for ; ix < src.used; ix += 1 { /* Compute product and carry sum for this term */ - product := carry + _WORD(src.digit[ix]) * _WORD(multiplier); + product := carry + _WORD(src.digit[ix]) * _WORD(multiplier) /* Mask off higher bits to get a single DIGIT. */ - dest.digit[ix] = DIGIT(product & _WORD(_MASK)); + dest.digit[ix] = DIGIT(product & _WORD(_MASK)) /* Send carry into next iteration */ - carry = product >> _DIGIT_BITS; + carry = product >> _DIGIT_BITS } /* Store final carry [if any] and increment used. */ - dest.digit[ix] = DIGIT(carry); - dest.used = src.used + 1; + dest.digit[ix] = DIGIT(carry) + dest.used = src.used + 1 /* Zero remainder. */ - internal_zero_unused(dest, old_used); + internal_zero_unused(dest, old_used) - return internal_clamp(dest); + return internal_clamp(dest) } /* High level multiplication (handles sign). */ internal_int_mul :: proc(dest, src, multiplier: ^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator /* Early out for `multiplier` is zero; Set `dest` to zero. */ if multiplier.used == 0 || src.used == 0 { return internal_zero(dest); } - neg := src.sign != multiplier.sign; + neg := src.sign != multiplier.sign if src == multiplier { /* @@ -640,19 +640,19 @@ internal_int_mul :: proc(dest, src, multiplier: ^Int, allocator := context.alloc /* Use Toom-Cook? */ - err = #force_inline _private_int_sqr_toom(dest, src); + err = #force_inline _private_int_sqr_toom(dest, src) } else if src.used >= SQR_KARATSUBA_CUTOFF { /* Karatsuba? */ - err = #force_inline _private_int_sqr_karatsuba(dest, src); + err = #force_inline _private_int_sqr_karatsuba(dest, src) } else if ((src.used * 2) + 1) < _WARRAY && src.used < (_MAX_COMBA / 2) { /* Fast comba? */ - err = #force_inline _private_int_sqr_comba(dest, src); + err = #force_inline _private_int_sqr_comba(dest, src) } else { - err = #force_inline _private_int_sqr(dest, src); + err = #force_inline _private_int_sqr(dest, src) } } else { /* @@ -664,23 +664,23 @@ internal_int_mul :: proc(dest, src, multiplier: ^Int, allocator := context.alloc * was actually slower on the author's machine, but YMMV. */ - min_used := min(src.used, multiplier.used); - max_used := max(src.used, multiplier.used); - digits := src.used + multiplier.used + 1; + min_used := min(src.used, multiplier.used) + max_used := max(src.used, multiplier.used) + digits := src.used + multiplier.used + 1 if min_used >= MUL_KARATSUBA_CUTOFF && (max_used / 2) >= MUL_KARATSUBA_CUTOFF && max_used >= (2 * min_used) { /* Not much effect was observed below a ratio of 1:2, but again: YMMV. */ - err = _private_int_mul_balance(dest, src, multiplier); + err = _private_int_mul_balance(dest, src, multiplier) } else if min_used >= MUL_TOOM_CUTOFF { /* Toom path commented out until it no longer fails Factorial 10k or 100k, as reveaved in the long test. */ - err = #force_inline _private_int_mul_toom(dest, src, multiplier); + err = #force_inline _private_int_mul_toom(dest, src, multiplier) } else if min_used >= MUL_KARATSUBA_CUTOFF { - err = #force_inline _private_int_mul_karatsuba(dest, src, multiplier); + err = #force_inline _private_int_mul_karatsuba(dest, src, multiplier) } else if digits < _WARRAY && min_used <= _MAX_COMBA { /* Can we use the fast multiplier? @@ -688,24 +688,24 @@ internal_int_mul :: proc(dest, src, multiplier: ^Int, allocator := context.alloc * have less than MP_WARRAY digits and the number of * digits won't affect carry propagation */ - err = #force_inline _private_int_mul_comba(dest, src, multiplier, digits); + err = #force_inline _private_int_mul_comba(dest, src, multiplier, digits) } else { - err = #force_inline _private_int_mul(dest, src, multiplier, digits); + err = #force_inline _private_int_mul(dest, src, multiplier, digits) } } - dest.sign = .Negative if dest.used > 0 && neg else .Zero_or_Positive; - return err; + dest.sign = .Negative if dest.used > 0 && neg else .Zero_or_Positive + return err } -internal_mul :: proc { internal_int_mul, internal_int_mul_digit, }; +internal_mul :: proc { internal_int_mul, internal_int_mul_digit, } internal_sqr :: proc (dest, src: ^Int, allocator := context.allocator) -> (res: Error) { /* We call `internal_mul` and not e.g. `_private_int_sqr` because the former will dispatch to the optimal implementation depending on the source. */ - return #force_inline internal_mul(dest, src, src, allocator); + return #force_inline internal_mul(dest, src, src, allocator) } /* @@ -714,37 +714,37 @@ internal_sqr :: proc (dest, src: ^Int, allocator := context.allocator) -> (res: `numerator` and `denominator` are expected not to be `nil` and have been initialized. */ internal_int_divmod :: proc(quotient, remainder, numerator, denominator: ^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator if denominator.used == 0 { return .Division_by_Zero; } /* If numerator < denominator then quotient = 0, remainder = numerator. */ if #force_inline internal_cmp_mag(numerator, denominator) == -1 { if remainder != nil { - internal_copy(remainder, numerator) or_return; + internal_copy(remainder, numerator) or_return } if quotient != nil { - internal_zero(quotient); + internal_zero(quotient) } - return nil; + return nil } if (denominator.used > 2 * MUL_KARATSUBA_CUTOFF) && (denominator.used <= (numerator.used / 3) * 2) { - assert(denominator.used >= 160 && numerator.used >= 240, "MUL_KARATSUBA_CUTOFF global not properly set."); - err = _private_int_div_recursive(quotient, remainder, numerator, denominator); + assert(denominator.used >= 160 && numerator.used >= 240, "MUL_KARATSUBA_CUTOFF global not properly set.") + err = _private_int_div_recursive(quotient, remainder, numerator, denominator) // err = #force_inline _private_int_div_school(quotient, remainder, numerator, denominator); } else { when true { - err = #force_inline _private_int_div_school(quotient, remainder, numerator, denominator); + err = #force_inline _private_int_div_school(quotient, remainder, numerator, denominator) } else { /* NOTE(Jeroen): We no longer need or use `_private_int_div_small`. We'll keep it around for a bit until we're reasonably certain div_school is bug free. */ - err = _private_int_div_small(quotient, remainder, numerator, denominator); + err = _private_int_div_small(quotient, remainder, numerator, denominator) } } - return; + return } /* @@ -752,7 +752,7 @@ internal_int_divmod :: proc(quotient, remainder, numerator, denominator: ^Int, a The quotient is optional and may be passed a nil. */ internal_int_divmod_digit :: proc(quotient, numerator: ^Int, denominator: DIGIT, allocator := context.allocator) -> (remainder: DIGIT, err: Error) { - context.allocator = allocator; + context.allocator = allocator /* Cannot divide by zero. @@ -764,9 +764,9 @@ internal_int_divmod_digit :: proc(quotient, numerator: ^Int, denominator: DIGIT, */ if denominator == 1 || numerator.used == 0 { if quotient != nil { - return 0, internal_copy(quotient, numerator); + return 0, internal_copy(quotient, numerator) } - return 0, err; + return 0, err } /* Power of two? @@ -774,75 +774,75 @@ internal_int_divmod_digit :: proc(quotient, numerator: ^Int, denominator: DIGIT, if denominator == 2 { if numerator.used > 0 && numerator.digit[0] & 1 != 0 { // Remainder is 1 if numerator is odd. - remainder = 1; + remainder = 1 } if quotient == nil { - return remainder, nil; + return remainder, nil } - return remainder, internal_shr(quotient, numerator, 1); + return remainder, internal_shr(quotient, numerator, 1) } - ix: int; + ix: int if platform_int_is_power_of_two(int(denominator)) { - ix = 1; + ix = 1 for ix < _DIGIT_BITS && denominator != (1 << uint(ix)) { - ix += 1; + ix += 1 } - remainder = numerator.digit[0] & ((1 << uint(ix)) - 1); + remainder = numerator.digit[0] & ((1 << uint(ix)) - 1) if quotient == nil { - return remainder, nil; + return remainder, nil } - return remainder, internal_shr(quotient, numerator, int(ix)); + return remainder, internal_shr(quotient, numerator, int(ix)) } /* Three? */ if denominator == 3 { - return _private_int_div_3(quotient, numerator); + return _private_int_div_3(quotient, numerator) } /* No easy answer [c'est la vie]. Just division. */ - q := &Int{}; + q := &Int{} - internal_grow(q, numerator.used) or_return; + internal_grow(q, numerator.used) or_return - q.used = numerator.used; - q.sign = numerator.sign; + q.used = numerator.used + q.sign = numerator.sign - w := _WORD(0); + w := _WORD(0) for ix = numerator.used - 1; ix >= 0; ix -= 1 { - t := DIGIT(0); - w = (w << _WORD(_DIGIT_BITS) | _WORD(numerator.digit[ix])); + t := DIGIT(0) + w = (w << _WORD(_DIGIT_BITS) | _WORD(numerator.digit[ix])) if w >= _WORD(denominator) { - t = DIGIT(w / _WORD(denominator)); - w -= _WORD(t) * _WORD(denominator); + t = DIGIT(w / _WORD(denominator)) + w -= _WORD(t) * _WORD(denominator) } - q.digit[ix] = t; + q.digit[ix] = t } - remainder = DIGIT(w); + remainder = DIGIT(w) if quotient != nil { - internal_clamp(q); - internal_swap(q, quotient); + internal_clamp(q) + internal_swap(q, quotient) } - internal_destroy(q); - return remainder, nil; + internal_destroy(q) + return remainder, nil } -internal_divmod :: proc { internal_int_divmod, internal_int_divmod_digit, }; +internal_divmod :: proc { internal_int_divmod, internal_int_divmod_digit, } /* Asssumes quotient, numerator and denominator to have been initialized and not to be nil. */ internal_int_div :: proc(quotient, numerator, denominator: ^Int, allocator := context.allocator) -> (err: Error) { - return #force_inline internal_int_divmod(quotient, nil, numerator, denominator, allocator); + return #force_inline internal_int_divmod(quotient, nil, numerator, denominator, allocator) } -internal_div :: proc { internal_int_div, }; +internal_div :: proc { internal_int_div, } /* remainder = numerator % denominator. @@ -856,50 +856,50 @@ internal_int_mod :: proc(remainder, numerator, denominator: ^Int, allocator := c if remainder.used == 0 || denominator.sign == remainder.sign { return nil; } - return #force_inline internal_add(remainder, remainder, numerator, allocator); + return #force_inline internal_add(remainder, remainder, numerator, allocator) } internal_int_mod_digit :: proc(numerator: ^Int, denominator: DIGIT, allocator := context.allocator) -> (remainder: DIGIT, err: Error) { - return internal_int_divmod_digit(nil, numerator, denominator, allocator); + return internal_int_divmod_digit(nil, numerator, denominator, allocator) } -internal_mod :: proc{ internal_int_mod, internal_int_mod_digit}; +internal_mod :: proc{ internal_int_mod, internal_int_mod_digit} /* remainder = (number + addend) % modulus. */ internal_int_addmod :: proc(remainder, number, addend, modulus: ^Int, allocator := context.allocator) -> (err: Error) { #force_inline internal_add(remainder, number, addend, allocator) or_return; - return #force_inline internal_mod(remainder, remainder, modulus, allocator); + return #force_inline internal_mod(remainder, remainder, modulus, allocator) } -internal_addmod :: proc { internal_int_addmod, }; +internal_addmod :: proc { internal_int_addmod, } /* remainder = (number - decrease) % modulus. */ internal_int_submod :: proc(remainder, number, decrease, modulus: ^Int, allocator := context.allocator) -> (err: Error) { #force_inline internal_sub(remainder, number, decrease, allocator) or_return; - return #force_inline internal_mod(remainder, remainder, modulus, allocator); + return #force_inline internal_mod(remainder, remainder, modulus, allocator) } -internal_submod :: proc { internal_int_submod, }; +internal_submod :: proc { internal_int_submod, } /* remainder = (number * multiplicand) % modulus. */ internal_int_mulmod :: proc(remainder, number, multiplicand, modulus: ^Int, allocator := context.allocator) -> (err: Error) { #force_inline internal_mul(remainder, number, multiplicand, allocator) or_return; - return #force_inline internal_mod(remainder, remainder, modulus, allocator); + return #force_inline internal_mod(remainder, remainder, modulus, allocator) } -internal_mulmod :: proc { internal_int_mulmod, }; +internal_mulmod :: proc { internal_int_mulmod, } /* remainder = (number * number) % modulus. */ internal_int_sqrmod :: proc(remainder, number, modulus: ^Int, allocator := context.allocator) -> (err: Error) { #force_inline internal_sqr(remainder, number, allocator) or_return; - return #force_inline internal_mod(remainder, remainder, modulus, allocator); + return #force_inline internal_mod(remainder, remainder, modulus, allocator) } -internal_sqrmod :: proc { internal_int_sqrmod, }; +internal_sqrmod :: proc { internal_int_sqrmod, } @@ -908,26 +908,26 @@ internal_sqrmod :: proc { internal_int_sqrmod, }; This way we'll have to reallocate less, possibly not at all. */ internal_int_factorial :: proc(res: ^Int, n: int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator if n >= FACTORIAL_BINARY_SPLIT_CUTOFF { - return _private_int_factorial_binary_split(res, n); + return _private_int_factorial_binary_split(res, n) } - i := len(_factorial_table); + i := len(_factorial_table) if n < i { - return #force_inline internal_set(res, _factorial_table[n]); + return #force_inline internal_set(res, _factorial_table[n]) } #force_inline internal_set(res, _factorial_table[i - 1]) or_return; for { if err = #force_inline internal_mul(res, res, DIGIT(i)); err != nil || i == n { - return err; + return err } - i += 1; + i += 1 } - return nil; + return nil } /* @@ -939,7 +939,7 @@ internal_int_factorial :: proc(res: ^Int, n: int, allocator := context.allocator internal_int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int, allocator := context.allocator) -> (err: Error) { if res_gcd == nil && res_lcm == nil { return nil; } - return #force_inline _private_int_gcd_lcm(res_gcd, res_lcm, a, b, allocator); + return #force_inline _private_int_gcd_lcm(res_gcd, res_lcm, a, b, allocator) } /* @@ -956,29 +956,29 @@ internal_int_mod_bits :: proc(remainder, numerator: ^Int, bits: int, allocator : /* If the modulus is larger than the value, return the value. */ - internal_copy(remainder, numerator) or_return; + internal_copy(remainder, numerator) or_return if bits >= (numerator.used * _DIGIT_BITS) { - return; + return } /* Zero digits above the last digit of the modulus. */ - zero_count := (bits / _DIGIT_BITS); - zero_count += 0 if (bits % _DIGIT_BITS == 0) else 1; + zero_count := (bits / _DIGIT_BITS) + zero_count += 0 if (bits % _DIGIT_BITS == 0) else 1 /* Zero remainder. Special case, can't use `internal_zero_unused`. */ if zero_count > 0 { - mem.zero_slice(remainder.digit[zero_count:]); + mem.zero_slice(remainder.digit[zero_count:]) } /* Clear the digit that is not completely outside/inside the modulus. */ - remainder.digit[bits / _DIGIT_BITS] &= DIGIT(1 << DIGIT(bits % _DIGIT_BITS)) - DIGIT(1); - return internal_clamp(remainder); + remainder.digit[bits / _DIGIT_BITS] &= DIGIT(1 << DIGIT(bits % _DIGIT_BITS)) - DIGIT(1) + return internal_clamp(remainder) } /* @@ -997,37 +997,37 @@ internal_int_mod_bits :: proc(remainder, numerator: ^Int, bits: int, allocator : Assumes `a` not to be `nil`. */ internal_int_is_initialized :: #force_inline proc(a: ^Int) -> (initialized: bool) { - raw := transmute(mem.Raw_Dynamic_Array)a.digit; - return raw.cap >= _MIN_DIGIT_COUNT; + raw := transmute(mem.Raw_Dynamic_Array)a.digit + return raw.cap >= _MIN_DIGIT_COUNT } -internal_is_initialized :: proc { internal_int_is_initialized, }; +internal_is_initialized :: proc { internal_int_is_initialized, } /* This procedure will return `true` if the `Int` is zero, `false` if not. Assumes `a` not to be `nil`. */ internal_int_is_zero :: #force_inline proc(a: ^Int) -> (zero: bool) { - return a.used == 0; + return a.used == 0 } -internal_is_zero :: proc { internal_int_is_zero, }; +internal_is_zero :: proc { internal_int_is_zero, } /* This procedure will return `true` if the `Int` is positive, `false` if not. Assumes `a` not to be `nil`. */ internal_int_is_positive :: #force_inline proc(a: ^Int) -> (positive: bool) { - return a.sign == .Zero_or_Positive; + return a.sign == .Zero_or_Positive } -internal_is_positive :: proc { internal_int_is_positive, }; +internal_is_positive :: proc { internal_int_is_positive, } /* This procedure will return `true` if the `Int` is negative, `false` if not. Assumes `a` not to be `nil`. */ internal_int_is_negative :: #force_inline proc(a: ^Int) -> (negative: bool) { - return a.sign == .Negative; + return a.sign == .Negative } -internal_is_negative :: proc { internal_int_is_negative, }; +internal_is_negative :: proc { internal_int_is_negative, } /* This procedure will return `true` if the `Int` is even, `false` if not. @@ -1040,18 +1040,18 @@ internal_int_is_even :: #force_inline proc(a: ^Int) -> (even: bool) { `a.used` > 0 here, because the above handled `is_zero`. We don't need to explicitly test it. */ - return a.digit[0] & 1 == 0; + return a.digit[0] & 1 == 0 } -internal_is_even :: proc { internal_int_is_even, }; +internal_is_even :: proc { internal_int_is_even, } /* This procedure will return `true` if the `Int` is even, `false` if not. Assumes `a` not to be `nil`. */ internal_int_is_odd :: #force_inline proc(a: ^Int) -> (odd: bool) { - return !internal_int_is_even(a); + return !internal_int_is_even(a) } -internal_is_odd :: proc { internal_int_is_odd, }; +internal_is_odd :: proc { internal_int_is_odd, } /* @@ -1080,9 +1080,9 @@ internal_int_is_power_of_two :: #force_inline proc(a: ^Int) -> (power_of_two: bo */ for i := 1; i < a.used && a.digit[i - 1] != 0; i += 1 { return false; } - return true; + return true } -internal_is_power_of_two :: proc { internal_int_is_power_of_two, }; +internal_is_power_of_two :: proc { internal_int_is_power_of_two, } /* Compare two `Int`s, signed. @@ -1091,7 +1091,7 @@ internal_is_power_of_two :: proc { internal_int_is_power_of_two, }; Expects `a` and `b` both to be valid `Int`s, i.e. initialized and not `nil`. */ internal_int_compare :: #force_inline proc(a, b: ^Int) -> (comparison: int) { - a_is_negative := #force_inline internal_is_negative(a); + a_is_negative := #force_inline internal_is_negative(a) /* Compare based on sign. @@ -1102,10 +1102,10 @@ internal_int_compare :: #force_inline proc(a, b: ^Int) -> (comparison: int) { If `a` is negative, compare in the opposite direction */ if a_is_negative { return #force_inline internal_compare_magnitude(b, a); } - return #force_inline internal_compare_magnitude(a, b); + return #force_inline internal_compare_magnitude(a, b) } -internal_compare :: proc { internal_int_compare, internal_int_compare_digit, }; -internal_cmp :: internal_compare; +internal_compare :: proc { internal_int_compare, internal_int_compare_digit, } +internal_cmp :: internal_compare /* Compare an `Int` to an unsigned number upto `DIGIT & _MASK`. @@ -1114,32 +1114,32 @@ internal_cmp :: internal_compare; Expects: `a` and `b` both to be valid `Int`s, i.e. initialized and not `nil`. */ internal_int_compare_digit :: #force_inline proc(a: ^Int, b: DIGIT) -> (comparison: int) { - a_is_negative := #force_inline internal_is_negative(a); + a_is_negative := #force_inline internal_is_negative(a) switch { /* Compare based on sign first. */ - case a_is_negative: return -1; + case a_is_negative: return -1 /* Then compare on magnitude. */ - case a.used > 1: return +1; + case a.used > 1: return +1 /* We have only one digit. Compare it against `b`. */ - case a.digit[0] < b: return -1; - case a.digit[0] == b: return 0; - case a.digit[0] > b: return +1; + case a.digit[0] < b: return -1 + case a.digit[0] == b: return 0 + case a.digit[0] > b: return +1 /* Unreachable. Just here because Odin complains about a missing return value at the bottom of the proc otherwise. */ - case: return; + case: return } } -internal_compare_digit :: proc { internal_int_compare_digit, }; -internal_cmp_digit :: internal_compare_digit; +internal_compare_digit :: proc { internal_int_compare_digit, } +internal_cmp_digit :: internal_compare_digit /* Compare the magnitude of two `Int`s, unsigned. @@ -1150,9 +1150,9 @@ internal_int_compare_magnitude :: #force_inline proc(a, b: ^Int) -> (comparison: */ if a.used != b.used { if a.used > b.used { - return +1; + return +1 } - return -1; + return -1 } /* @@ -1161,16 +1161,16 @@ internal_int_compare_magnitude :: #force_inline proc(a, b: ^Int) -> (comparison: #no_bounds_check for n := a.used - 1; n >= 0; n -= 1 { if a.digit[n] != b.digit[n] { if a.digit[n] > b.digit[n] { - return +1; + return +1 } - return -1; + return -1 } } - return 0; + return 0 } -internal_compare_magnitude :: proc { internal_int_compare_magnitude, }; -internal_cmp_mag :: internal_compare_magnitude; +internal_compare_magnitude :: proc { internal_int_compare_magnitude, } +internal_cmp_mag :: internal_compare_magnitude /* Check if remainders are possible squares - fast exclude non-squares. @@ -1179,12 +1179,12 @@ internal_cmp_mag :: internal_compare_magnitude; Assumes `a` not to be `nil` and to have been initialized. */ internal_int_is_square :: proc(a: ^Int, allocator := context.allocator) -> (square: bool, err: Error) { - context.allocator = allocator; + context.allocator = allocator /* Default to Non-square :) */ - square = false; + square = false if internal_is_negative(a) { return; } if internal_is_zero(a) { return; } @@ -1197,18 +1197,18 @@ internal_int_is_square :: proc(a: ^Int, allocator := context.allocator) -> (squa /* Next check mod 105 (3*5*7). */ - c: DIGIT; - c, err = internal_mod(a, 105); + c: DIGIT + c, err = internal_mod(a, 105) if _private_int_rem_105[c] == 1 { return; } - t := &Int{}; - defer destroy(t); + t := &Int{} + defer destroy(t) - set(t, 11 * 13 * 17 * 19 * 23 * 29 * 31) or_return; - internal_mod(t, a, t) or_return; + set(t, 11 * 13 * 17 * 19 * 23 * 29 * 31) or_return + internal_mod(t, a, t) or_return - r: u64; - r, err = internal_int_get(t, u64); + r: u64 + r, err = internal_int_get(t, u64) /* Check for other prime modules, note it's not an ERROR but we must @@ -1226,12 +1226,12 @@ internal_int_is_square :: proc(a: ^Int, allocator := context.allocator) -> (squa /* Final check - is sqr(sqrt(arg)) == arg? */ - sqrt(t, a) or_return; - sqr(t, t) or_return; + sqrt(t, a) or_return + sqr(t, t) or_return - square = internal_cmp_mag(t, a) == 0; + square = internal_cmp_mag(t, a) == 0 - return; + return } /* @@ -1258,7 +1258,7 @@ internal_int_log :: proc(a: ^Int, base: DIGIT) -> (res: int, err: Error) { */ if a.used == 1 { return internal_log(a.digit[0], DIGIT(base)); } - return _private_int_log(a, base); + return _private_int_log(a, base) } @@ -1277,52 +1277,52 @@ internal_digit_log :: proc(a: DIGIT, base: DIGIT) -> (log: int, err: Error) { */ if a == base { return 1, nil; } - N := _WORD(a); - bracket_low := _WORD(1); - bracket_high := _WORD(base); - high := 1; - low := 0; + N := _WORD(a) + bracket_low := _WORD(1) + bracket_high := _WORD(base) + high := 1 + low := 0 for bracket_high < N { - low = high; - bracket_low = bracket_high; - high <<= 1; - bracket_high *= bracket_high; + low = high + bracket_low = bracket_high + high <<= 1 + bracket_high *= bracket_high } for high - low > 1 { - mid := (low + high) >> 1; - bracket_mid := bracket_low * #force_inline internal_small_pow(_WORD(base), _WORD(mid - low)); + mid := (low + high) >> 1 + bracket_mid := bracket_low * #force_inline internal_small_pow(_WORD(base), _WORD(mid - low)) if N < bracket_mid { - high = mid; - bracket_high = bracket_mid; + high = mid + bracket_high = bracket_mid } if N > bracket_mid { - low = mid; - bracket_low = bracket_mid; + low = mid + bracket_low = bracket_mid } if N == bracket_mid { - return mid, nil; + return mid, nil } } if bracket_high == N { - return high, nil; + return high, nil } else { - return low, nil; + return low, nil } } -internal_log :: proc { internal_int_log, internal_digit_log, }; +internal_log :: proc { internal_int_log, internal_digit_log, } /* Calculate dest = base^power using a square-multiply algorithm. Assumes `dest` and `base` not to be `nil` and to have been initialized. */ internal_int_pow :: proc(dest, base: ^Int, power: int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator - power := power; + power := power /* Early outs. */ @@ -1331,8 +1331,8 @@ internal_int_pow :: proc(dest, base: ^Int, power: int, allocator := context.allo A zero base is a special case. */ if power < 0 { - internal_zero(dest) or_return; - return .Math_Domain_Error; + internal_zero(dest) or_return + return .Math_Domain_Error } if power == 0 { return internal_one(dest); } if power > 0 { return internal_zero(dest); } @@ -1342,52 +1342,52 @@ internal_int_pow :: proc(dest, base: ^Int, power: int, allocator := context.allo /* Fraction, so we'll return zero. */ - return internal_zero(dest); + return internal_zero(dest) } switch(power) { case 0: /* Any base to the power zero is one. */ - return #force_inline internal_one(dest); + return #force_inline internal_one(dest) case 1: /* Any base to the power one is itself. */ - return copy(dest, base); + return copy(dest, base) case 2: - return #force_inline internal_sqr(dest, base); + return #force_inline internal_sqr(dest, base) } - g := &Int{}; - internal_copy(g, base) or_return; + g := &Int{} + internal_copy(g, base) or_return /* Set initial result. */ - internal_one(dest) or_return; + internal_one(dest) or_return - defer internal_destroy(g); + defer internal_destroy(g) for power > 0 { /* If the bit is set, multiply. */ if power & 1 != 0 { - internal_mul(dest, g, dest) or_return; + internal_mul(dest, g, dest) or_return } /* Square. */ if power > 1 { - internal_sqr(g, g) or_return; + internal_sqr(g, g) or_return } /* shift to next bit */ - power >>= 1; + power >>= 1 } - return; + return } /* @@ -1395,34 +1395,34 @@ internal_int_pow :: proc(dest, base: ^Int, power: int, allocator := context.allo Assumes `dest` not to be `nil` and to have been initialized. */ internal_int_pow_int :: proc(dest: ^Int, base, power: int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator - base_t := &Int{}; - defer internal_destroy(base_t); + base_t := &Int{} + defer internal_destroy(base_t) - internal_set(base_t, base) or_return; + internal_set(base_t, base) or_return - return #force_inline internal_int_pow(dest, base_t, power); + return #force_inline internal_int_pow(dest, base_t, power) } -internal_pow :: proc { internal_int_pow, internal_int_pow_int, }; -internal_exp :: pow; +internal_pow :: proc { internal_int_pow, internal_int_pow_int, } +internal_exp :: pow /* */ internal_small_pow :: proc(base: _WORD, exponent: _WORD) -> (result: _WORD) { - exponent := exponent; base := base; - result = _WORD(1); + exponent := exponent; base := base + result = _WORD(1) for exponent != 0 { if exponent & 1 == 1 { - result *= base; + result *= base } - exponent >>= 1; - base *= base; + exponent >>= 1 + base *= base } - return result; + return result } /* @@ -1430,7 +1430,7 @@ internal_small_pow :: proc(base: _WORD, exponent: _WORD) -> (result: _WORD) { Assumes `dest` and `src` not to be `nil` and to have been initialized. */ internal_int_sqrt :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator /* Must be positive. @@ -1445,33 +1445,33 @@ internal_int_sqrt :: proc(dest, src: ^Int, allocator := context.allocator) -> (e /* Set up temporaries. */ - x, y, t1, t2 := &Int{}, &Int{}, &Int{}, &Int{}; - defer internal_destroy(x, y, t1, t2); + x, y, t1, t2 := &Int{}, &Int{}, &Int{}, &Int{} + defer internal_destroy(x, y, t1, t2) - count := #force_inline internal_count_bits(src); + count := #force_inline internal_count_bits(src) - a, b := count >> 1, count & 1; - internal_int_power_of_two(x, a+b, allocator) or_return; + a, b := count >> 1, count & 1 + internal_int_power_of_two(x, a+b, allocator) or_return for { /* y = (x + n // x) // 2 */ - internal_div(t1, src, x) or_return; - internal_add(t2, t1, x) or_return; - internal_shr(y, t2, 1) or_return; + internal_div(t1, src, x) or_return + internal_add(t2, t1, x) or_return + internal_shr(y, t2, 1) or_return if c := internal_cmp(y, x); c == 0 || c == 1 { - internal_swap(dest, x); - return nil; + internal_swap(dest, x) + return nil } - internal_swap(x, y); + internal_swap(x, y) } - internal_swap(dest, x); - return err; + internal_swap(dest, x) + return err } -internal_sqrt :: proc { internal_int_sqrt, }; +internal_sqrt :: proc { internal_int_sqrt, } /* @@ -1484,7 +1484,7 @@ internal_sqrt :: proc { internal_int_sqrt, }; Assumes `dest` and `src` not to be `nil` and have been initialized. */ internal_int_root_n :: proc(dest, src: ^Int, n: int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator /* Fast path for n == 2 @@ -1498,15 +1498,15 @@ internal_int_root_n :: proc(dest, src: ^Int, n: int, allocator := context.alloca /* Set up temporaries. */ - t1, t2, t3, a := &Int{}, &Int{}, &Int{}, &Int{}; - defer internal_destroy(t1, t2, t3); + t1, t2, t3, a := &Int{}, &Int{}, &Int{}, &Int{} + defer internal_destroy(t1, t2, t3) /* If `src` is negative fudge the sign but keep track. */ - a.sign = .Zero_or_Positive; - a.used = src.used; - a.digit = src.digit; + a.sign = .Zero_or_Positive + a.used = src.used + a.digit = src.digit /* If "n" is larger than INT_MAX it is also larger than @@ -1514,63 +1514,63 @@ internal_int_root_n :: proc(dest, src: ^Int, n: int, allocator := context.alloca with an int and hence the root is always < 2 (two). */ if n > max(int) / 2 { - err = set(dest, 1); - dest.sign = a.sign; - return err; + err = set(dest, 1) + dest.sign = a.sign + return err } /* Compute seed: 2^(log_2(src)/n + 2) */ - ilog2 := internal_count_bits(src); + ilog2 := internal_count_bits(src) /* "src" is smaller than max(int), we can cast safely. */ if ilog2 < n { - err = internal_one(dest); - dest.sign = a.sign; - return err; + err = internal_one(dest) + dest.sign = a.sign + return err } - ilog2 /= n; + ilog2 /= n if ilog2 == 0 { - err = internal_one(dest); - dest.sign = a.sign; - return err; + err = internal_one(dest) + dest.sign = a.sign + return err } /* Start value must be larger than root. */ - ilog2 += 2; - internal_int_power_of_two(t2, ilog2) or_return; + ilog2 += 2 + internal_int_power_of_two(t2, ilog2) or_return - c: int; - iterations := 0; + c: int + iterations := 0 for { /* t1 = t2 */ - internal_copy(t1, t2) or_return; + internal_copy(t1, t2) or_return /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */ /* t3 = t1**(b-1) */ - internal_pow(t3, t1, n-1) or_return; + internal_pow(t3, t1, n-1) or_return /* numerator */ /* t2 = t1**b */ - internal_mul(t2, t1, t3) or_return; + internal_mul(t2, t1, t3) or_return /* t2 = t1**b - a */ - internal_sub(t2, t2, a) or_return; + internal_sub(t2, t2, a) or_return /* denominator */ /* t3 = t1**(b-1) * b */ - internal_mul(t3, t3, DIGIT(n)) or_return; + internal_mul(t3, t3, DIGIT(n)) or_return /* t3 = (t1**b - a)/(b * t1**(b-1)) */ - internal_div(t3, t2, t3) or_return; - internal_sub(t2, t1, t3) or_return; + internal_div(t3, t2, t3) or_return + internal_sub(t2, t1, t3) or_return /* Number of rounds is at most log_2(root). If it is more it @@ -1579,65 +1579,65 @@ internal_int_root_n :: proc(dest, src: ^Int, n: int, allocator := context.alloca if ilog2 -= 1; ilog2 == 0 { break; } if internal_cmp(t1, t2) == 0 { break; } - iterations += 1; + iterations += 1 if iterations == MAX_ITERATIONS_ROOT_N { - return .Max_Iterations_Reached; + return .Max_Iterations_Reached } } /* Result can be off by a few so check. */ /* Loop beneath can overshoot by one if found root is smaller than actual root. */ - iterations = 0; + iterations = 0 for { - internal_pow(t2, t1, n) or_return; + internal_pow(t2, t1, n) or_return - c = internal_cmp(t2, a); + c = internal_cmp(t2, a) if c == 0 { - swap(dest, t1); - return nil; + swap(dest, t1) + return nil } else if c == -1 { - internal_add(t1, t1, DIGIT(1)) or_return; + internal_add(t1, t1, DIGIT(1)) or_return } else { - break; + break } - iterations += 1; + iterations += 1 if iterations == MAX_ITERATIONS_ROOT_N { - return .Max_Iterations_Reached; + return .Max_Iterations_Reached } } - iterations = 0; + iterations = 0 /* Correct overshoot from above or from recurrence. */ for { - internal_pow(t2, t1, n) or_return; + internal_pow(t2, t1, n) or_return if internal_cmp(t2, a) != 1 { break; } - internal_sub(t1, t1, DIGIT(1)) or_return; + internal_sub(t1, t1, DIGIT(1)) or_return - iterations += 1; + iterations += 1 if iterations == MAX_ITERATIONS_ROOT_N { - return .Max_Iterations_Reached; + return .Max_Iterations_Reached } } /* Set the result. */ - internal_swap(dest, t1); + internal_swap(dest, t1) /* Set the sign of the result. */ - dest.sign = src.sign; + dest.sign = src.sign - return err; + return err } -internal_root_n :: proc { internal_int_root_n, }; +internal_root_n :: proc { internal_int_root_n, } /* Other internal helpers @@ -1648,51 +1648,51 @@ internal_root_n :: proc { internal_int_root_n, }; Asssumes none of the `integers` to be a `nil`. */ internal_int_destroy :: proc(integers: ..^Int) { - integers := integers; + integers := integers for a in &integers { - raw := transmute(mem.Raw_Dynamic_Array)a.digit; + raw := transmute(mem.Raw_Dynamic_Array)a.digit if raw.cap > 0 { - mem.zero_slice(a.digit[:]); - free(&a.digit[0]); + mem.zero_slice(a.digit[:]) + free(&a.digit[0]) } - a = &Int{}; + a = &Int{} } } -internal_destroy :: proc{ internal_int_destroy, }; +internal_destroy :: proc{ internal_int_destroy, } /* Helpers to set an `Int` to a specific value. */ internal_int_set_from_integer :: proc(dest: ^Int, src: $T, minimize := false, allocator := context.allocator) -> (err: Error) where intrinsics.type_is_integer(T) { - context.allocator = allocator; + context.allocator = allocator - src := src; + src := src - internal_error_if_immutable(dest) or_return; + internal_error_if_immutable(dest) or_return /* Most internal procs asssume an Int to have already been initialize, but as this is one of the procs that initializes, we have to check the following. */ - internal_clear_if_uninitialized_single(dest) or_return; + internal_clear_if_uninitialized_single(dest) or_return - dest.flags = {}; // We're not -Inf, Inf, NaN or Immutable. + dest.flags = {} // We're not -Inf, Inf, NaN or Immutable. - dest.used = 0; - dest.sign = .Zero_or_Positive if src >= 0 else .Negative; - src = internal_abs(src); + dest.used = 0 + dest.sign = .Zero_or_Positive if src >= 0 else .Negative + src = internal_abs(src) #no_bounds_check for src != 0 { - dest.digit[dest.used] = DIGIT(src) & _MASK; - dest.used += 1; - src >>= _DIGIT_BITS; + dest.digit[dest.used] = DIGIT(src) & _MASK + dest.used += 1 + src >>= _DIGIT_BITS } - internal_zero_unused(dest); - return nil; + internal_zero_unused(dest) + return nil } -internal_set :: proc { internal_int_set_from_integer, internal_int_copy }; +internal_set :: proc { internal_int_set_from_integer, internal_int_copy } internal_copy_digits :: #force_inline proc(dest, src: ^Int, digits: int, offset := int(0)) -> (err: Error) { #force_inline internal_error_if_immutable(dest) or_return; @@ -1700,43 +1700,43 @@ internal_copy_digits :: #force_inline proc(dest, src: ^Int, digits: int, offset /* If dest == src, do nothing */ - return #force_inline _private_copy_digits(dest, src, digits, offset); + return #force_inline _private_copy_digits(dest, src, digits, offset) } /* Copy one `Int` to another. */ internal_int_copy :: proc(dest, src: ^Int, minimize := false, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator /* If dest == src, do nothing */ if (dest == src) { return nil; } - internal_error_if_immutable(dest) or_return; + internal_error_if_immutable(dest) or_return /* Grow `dest` to fit `src`. If `dest` is not yet initialized, it will be using `allocator`. */ - needed := src.used if minimize else max(src.used, _DEFAULT_DIGIT_COUNT); + needed := src.used if minimize else max(src.used, _DEFAULT_DIGIT_COUNT) - internal_grow(dest, needed, minimize) or_return; + internal_grow(dest, needed, minimize) or_return /* Copy everything over and zero high digits. */ - internal_copy_digits(dest, src, src.used); + internal_copy_digits(dest, src, src.used) - dest.used = src.used; - dest.sign = src.sign; - dest.flags = src.flags &~ {.Immutable}; + dest.used = src.used + dest.sign = src.sign + dest.flags = src.flags &~ {.Immutable} - internal_zero_unused(dest); - return nil; + internal_zero_unused(dest) + return nil } -internal_copy :: proc { internal_int_copy, }; +internal_copy :: proc { internal_int_copy, } /* In normal code, you can also write `a, b = b, a`. @@ -1744,80 +1744,80 @@ internal_copy :: proc { internal_int_copy, }; This helper swaps completely. */ internal_int_swap :: #force_inline proc(a, b: ^Int) { - a := a; b := b; + a := a; b := b - a.used, b.used = b.used, a.used; - a.sign, b.sign = b.sign, a.sign; - a.digit, b.digit = b.digit, a.digit; + a.used, b.used = b.used, a.used + a.sign, b.sign = b.sign, a.sign + a.digit, b.digit = b.digit, a.digit } -internal_swap :: proc { internal_int_swap, }; +internal_swap :: proc { internal_int_swap, } /* Set `dest` to |`src`|. */ internal_int_abs :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator /* If `dest == src`, just fix `dest`'s sign. */ if (dest == src) { - dest.sign = .Zero_or_Positive; - return nil; + dest.sign = .Zero_or_Positive + return nil } /* Copy `src` to `dest` */ - internal_copy(dest, src) or_return; + internal_copy(dest, src) or_return /* Fix sign. */ - dest.sign = .Zero_or_Positive; - return nil; + dest.sign = .Zero_or_Positive + return nil } internal_platform_abs :: proc(n: $T) -> T where intrinsics.type_is_integer(T) { - return n if n >= 0 else -n; + return n if n >= 0 else -n } -internal_abs :: proc{ internal_int_abs, internal_platform_abs, }; +internal_abs :: proc{ internal_int_abs, internal_platform_abs, } /* Set `dest` to `-src`. */ internal_int_neg :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator /* If `dest == src`, just fix `dest`'s sign. */ - sign := Sign.Negative; + sign := Sign.Negative if #force_inline internal_is_zero(src) || #force_inline internal_is_negative(src) { - sign = .Zero_or_Positive; + sign = .Zero_or_Positive } if dest == src { - dest.sign = sign; - return nil; + dest.sign = sign + return nil } /* Copy `src` to `dest` */ - internal_copy(dest, src) or_return; + internal_copy(dest, src) or_return /* Fix sign. */ - dest.sign = sign; - return nil; + dest.sign = sign + return nil } -internal_neg :: proc { internal_int_neg, }; +internal_neg :: proc { internal_int_neg, } /* hac 14.61, pp608. */ internal_int_inverse_modulo :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator /* For all n in N and n > 0, n = 0 mod 1. */ @@ -1833,15 +1833,15 @@ internal_int_inverse_modulo :: proc(dest, a, b: ^Int, allocator := context.alloc */ if internal_is_odd(b) { return _private_inverse_modulo_odd(dest, a, b); } - return _private_inverse_modulo(dest, a, b); + return _private_inverse_modulo(dest, a, b) } -internal_invmod :: proc{ internal_int_inverse_modulo, }; +internal_invmod :: proc{ internal_int_inverse_modulo, } /* Helpers to extract values from the `Int`. */ internal_int_bitfield_extract_single :: proc(a: ^Int, offset: int) -> (bit: _WORD, err: Error) { - return #force_inline int_bitfield_extract(a, offset, 1); + return #force_inline int_bitfield_extract(a, offset, 1) } internal_int_bitfield_extract :: proc(a: ^Int, offset, count: int) -> (res: _WORD, err: Error) #no_bounds_check { @@ -1849,10 +1849,10 @@ internal_int_bitfield_extract :: proc(a: ^Int, offset, count: int) -> (res: _WOR Early out for single bit. */ if count == 1 { - limb := offset / _DIGIT_BITS; + limb := offset / _DIGIT_BITS if limb < 0 || limb >= a.used { return 0, .Invalid_Argument; } - i := _WORD(1 << _WORD((offset % _DIGIT_BITS))); - return 1 if ((_WORD(a.digit[limb]) & i) != 0) else 0, nil; + i := _WORD(1 << _WORD((offset % _DIGIT_BITS))) + return 1 if ((_WORD(a.digit[limb]) & i) != 0) else 0, nil } if count > _WORD_BITS || count < 1 { return 0, .Invalid_Argument; } @@ -1869,34 +1869,34 @@ internal_int_bitfield_extract :: proc(a: ^Int, offset, count: int) -> (res: _WOR e.g. offset: 40, count: 120 = bits 40..59, 0..59, 0..39 */ - limb := offset / _DIGIT_BITS; - bits_left := count; - bits_offset := offset % _DIGIT_BITS; + limb := offset / _DIGIT_BITS + bits_left := count + bits_offset := offset % _DIGIT_BITS - num_bits := min(bits_left, _DIGIT_BITS - bits_offset); + num_bits := min(bits_left, _DIGIT_BITS - bits_offset) - shift := offset % _DIGIT_BITS; - mask := (_WORD(1) << uint(num_bits)) - 1; - res = (_WORD(a.digit[limb]) >> uint(shift)) & mask; + shift := offset % _DIGIT_BITS + mask := (_WORD(1) << uint(num_bits)) - 1 + res = (_WORD(a.digit[limb]) >> uint(shift)) & mask - bits_left -= num_bits; + bits_left -= num_bits if bits_left == 0 { return res, nil; } - res_shift := num_bits; - num_bits = min(bits_left, _DIGIT_BITS); - mask = (1 << uint(num_bits)) - 1; + res_shift := num_bits + num_bits = min(bits_left, _DIGIT_BITS) + mask = (1 << uint(num_bits)) - 1 - res |= (_WORD(a.digit[limb + 1]) & mask) << uint(res_shift); + res |= (_WORD(a.digit[limb + 1]) & mask) << uint(res_shift) - bits_left -= num_bits; + bits_left -= num_bits if bits_left == 0 { return res, nil; } - mask = (1 << uint(bits_left)) - 1; - res_shift += _DIGIT_BITS; + mask = (1 << uint(bits_left)) - 1 + res_shift += _DIGIT_BITS - res |= (_WORD(a.digit[limb + 2]) & mask) << uint(res_shift); + res |= (_WORD(a.digit[limb + 2]) & mask) << uint(res_shift) - return res, nil; + return res, nil } /* @@ -1906,169 +1906,169 @@ internal_int_bitfield_extract :: proc(a: ^Int, offset, count: int) -> (res: _WOR Assumes `a` not to be `nil`, and to have already been initialized. */ internal_int_shrink :: proc(a: ^Int) -> (err: Error) { - needed := max(_MIN_DIGIT_COUNT, a.used); + needed := max(_MIN_DIGIT_COUNT, a.used) if a.used != needed { return internal_grow(a, needed, true); } - return nil; + return nil } -internal_shrink :: proc { internal_int_shrink, }; +internal_shrink :: proc { internal_int_shrink, } internal_int_grow :: proc(a: ^Int, digits: int, allow_shrink := false, allocator := context.allocator) -> (err: Error) { - raw := transmute(mem.Raw_Dynamic_Array)a.digit; + raw := transmute(mem.Raw_Dynamic_Array)a.digit /* We need at least _MIN_DIGIT_COUNT or a.used digits, whichever is bigger. The caller is asking for `digits`. Let's be accomodating. */ - needed := max(_MIN_DIGIT_COUNT, a.used, digits); + needed := max(_MIN_DIGIT_COUNT, a.used, digits) if !allow_shrink { - needed = max(needed, raw.cap); + needed = max(needed, raw.cap) } /* If not yet iniialized, initialize the `digit` backing with the allocator we were passed. */ if raw.cap == 0 { - a.digit = make([dynamic]DIGIT, needed, allocator); + a.digit = make([dynamic]DIGIT, needed, allocator) } else if raw.cap != needed { /* `[dynamic]DIGIT` already knows what allocator was used for it, so resize will do the right thing. */ - resize(&a.digit, needed); + resize(&a.digit, needed) } /* Let's see if the allocation/resize worked as expected. */ if len(a.digit) != needed { - return .Out_Of_Memory; + return .Out_Of_Memory } - return nil; + return nil } -internal_grow :: proc { internal_int_grow, }; +internal_grow :: proc { internal_int_grow, } /* Clear `Int` and resize it to the default size. Assumes `a` not to be `nil`. */ internal_int_clear :: proc(a: ^Int, minimize := false, allocator := context.allocator) -> (err: Error) { - raw := transmute(mem.Raw_Dynamic_Array)a.digit; + raw := transmute(mem.Raw_Dynamic_Array)a.digit if raw.cap != 0 { - mem.zero_slice(a.digit[:a.used]); + mem.zero_slice(a.digit[:a.used]) } - a.sign = .Zero_or_Positive; - a.used = 0; + a.sign = .Zero_or_Positive + a.used = 0 - return #force_inline internal_grow(a, a.used, minimize, allocator); + return #force_inline internal_grow(a, a.used, minimize, allocator) } -internal_clear :: proc { internal_int_clear, }; -internal_zero :: internal_clear; +internal_clear :: proc { internal_int_clear, } +internal_zero :: internal_clear /* Set the `Int` to 1 and optionally shrink it to the minimum backing size. */ internal_int_one :: proc(a: ^Int, minimize := false, allocator := context.allocator) -> (err: Error) { - return internal_copy(a, INT_ONE, minimize, allocator); + return internal_copy(a, INT_ONE, minimize, allocator) } -internal_one :: proc { internal_int_one, }; +internal_one :: proc { internal_int_one, } /* Set the `Int` to -1 and optionally shrink it to the minimum backing size. */ internal_int_minus_one :: proc(a: ^Int, minimize := false, allocator := context.allocator) -> (err: Error) { - return internal_copy(a, INT_MINUS_ONE, minimize, allocator); + return internal_copy(a, INT_MINUS_ONE, minimize, allocator) } -internal_minus_one :: proc { internal_int_minus_one, }; +internal_minus_one :: proc { internal_int_minus_one, } /* Set the `Int` to Inf and optionally shrink it to the minimum backing size. */ internal_int_inf :: proc(a: ^Int, minimize := false, allocator := context.allocator) -> (err: Error) { - return internal_copy(a, INT_INF, minimize, allocator); + return internal_copy(a, INT_INF, minimize, allocator) } -internal_inf :: proc { internal_int_inf, }; +internal_inf :: proc { internal_int_inf, } /* Set the `Int` to -Inf and optionally shrink it to the minimum backing size. */ internal_int_minus_inf :: proc(a: ^Int, minimize := false, allocator := context.allocator) -> (err: Error) { - return internal_copy(a, INT_MINUS_INF, minimize, allocator); + return internal_copy(a, INT_MINUS_INF, minimize, allocator) } -internal_minus_inf :: proc { internal_int_inf, }; +internal_minus_inf :: proc { internal_int_inf, } /* Set the `Int` to NaN and optionally shrink it to the minimum backing size. */ internal_int_nan :: proc(a: ^Int, minimize := false, allocator := context.allocator) -> (err: Error) { - return internal_copy(a, INT_NAN, minimize, allocator); + return internal_copy(a, INT_NAN, minimize, allocator) } -internal_nan :: proc { internal_int_nan, }; +internal_nan :: proc { internal_int_nan, } internal_int_power_of_two :: proc(a: ^Int, power: int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator if power < 0 || power > _MAX_BIT_COUNT { return .Invalid_Argument; } /* Grow to accomodate the single bit. */ - a.used = (power / _DIGIT_BITS) + 1; - internal_grow(a, a.used) or_return; + a.used = (power / _DIGIT_BITS) + 1 + internal_grow(a, a.used) or_return /* Zero the entirety. */ - mem.zero_slice(a.digit[:]); + mem.zero_slice(a.digit[:]) /* Set the bit. */ - a.digit[power / _DIGIT_BITS] = 1 << uint((power % _DIGIT_BITS)); - return nil; + a.digit[power / _DIGIT_BITS] = 1 << uint((power % _DIGIT_BITS)) + return nil } internal_int_get_u128 :: proc(a: ^Int) -> (res: u128, err: Error) { - return internal_int_get(a, u128); + return internal_int_get(a, u128) } -internal_get_u128 :: proc { internal_int_get_u128, }; +internal_get_u128 :: proc { internal_int_get_u128, } internal_int_get_i128 :: proc(a: ^Int) -> (res: i128, err: Error) { - return internal_int_get(a, i128); + return internal_int_get(a, i128) } -internal_get_i128 :: proc { internal_int_get_i128, }; +internal_get_i128 :: proc { internal_int_get_i128, } internal_int_get_u64 :: proc(a: ^Int) -> (res: u64, err: Error) { - return internal_int_get(a, u64); + return internal_int_get(a, u64) } -internal_get_u64 :: proc { internal_int_get_u64, }; +internal_get_u64 :: proc { internal_int_get_u64, } internal_int_get_i64 :: proc(a: ^Int) -> (res: i64, err: Error) { - return internal_int_get(a, i64); + return internal_int_get(a, i64) } -internal_get_i64 :: proc { internal_int_get_i64, }; +internal_get_i64 :: proc { internal_int_get_i64, } internal_int_get_u32 :: proc(a: ^Int) -> (res: u32, err: Error) { - return internal_int_get(a, u32); + return internal_int_get(a, u32) } -internal_get_u32 :: proc { internal_int_get_u32, }; +internal_get_u32 :: proc { internal_int_get_u32, } internal_int_get_i32 :: proc(a: ^Int) -> (res: i32, err: Error) { - return internal_int_get(a, i32); + return internal_int_get(a, i32) } -internal_get_i32 :: proc { internal_int_get_i32, }; +internal_get_i32 :: proc { internal_int_get_i32, } /* TODO: Think about using `count_bits` to check if the value could be returned completely, and maybe return max(T), .Integer_Overflow if not? */ internal_int_get :: proc(a: ^Int, $T: typeid) -> (res: T, err: Error) where intrinsics.type_is_integer(T) { - size_in_bits := int(size_of(T) * 8); - i := int((size_in_bits + _DIGIT_BITS - 1) / _DIGIT_BITS); - i = min(int(a.used), i); + size_in_bits := int(size_of(T) * 8) + i := int((size_in_bits + _DIGIT_BITS - 1) / _DIGIT_BITS) + i = min(int(a.used), i) #no_bounds_check for ; i >= 0; i -= 1 { - res <<= uint(0) if size_in_bits <= _DIGIT_BITS else _DIGIT_BITS; - res |= T(a.digit[i]); + res <<= uint(0) if size_in_bits <= _DIGIT_BITS else _DIGIT_BITS + res |= T(a.digit[i]) if size_in_bits <= _DIGIT_BITS { - break; + break }; } @@ -2076,31 +2076,31 @@ internal_int_get :: proc(a: ^Int, $T: typeid) -> (res: T, err: Error) where intr /* Mask off sign bit. */ - res ~= 1 << uint(size_in_bits - 1); + res ~= 1 << uint(size_in_bits - 1) /* Set the sign. */ if a.sign == .Negative { res = -res; } } - return; + return } -internal_get :: proc { internal_int_get, }; +internal_get :: proc { internal_int_get, } internal_int_get_float :: proc(a: ^Int) -> (res: f64, err: Error) { /* log2(max(f64)) is approximately 1020, or 17 legs with the 64-bit storage. */ - legs :: 1020 / _DIGIT_BITS; - l := min(a.used, legs); - fac := f64(1 << _DIGIT_BITS); - d := 0.0; + legs :: 1020 / _DIGIT_BITS + l := min(a.used, legs) + fac := f64(1 << _DIGIT_BITS) + d := 0.0 #no_bounds_check for i := l; i >= 0; i -= 1 { - d = (d * fac) + f64(a.digit[i]); + d = (d * fac) + f64(a.digit[i]) } - res = -d if a.sign == .Negative else d; - return; + res = -d if a.sign == .Negative else d + return } /* @@ -2114,278 +2114,278 @@ internal_int_get_float :: proc(a: ^Int) -> (res: f64, err: Error) { 2's complement `and`, returns `dest = a & b;` */ internal_int_and :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator - used := max(a.used, b.used) + 1; + used := max(a.used, b.used) + 1 /* Grow the destination to accomodate the result. */ - internal_grow(dest, used) or_return; + internal_grow(dest, used) or_return - neg_a := #force_inline internal_is_negative(a); - neg_b := #force_inline internal_is_negative(b); - neg := neg_a && neg_b; + neg_a := #force_inline internal_is_negative(a) + neg_b := #force_inline internal_is_negative(b) + neg := neg_a && neg_b - ac, bc, cc := DIGIT(1), DIGIT(1), DIGIT(1); + ac, bc, cc := DIGIT(1), DIGIT(1), DIGIT(1) #no_bounds_check for i := 0; i < used; i += 1 { - x, y: DIGIT; + x, y: DIGIT /* Convert to 2's complement if negative. */ if neg_a { - ac += _MASK if i >= a.used else (~a.digit[i] & _MASK); - x = ac & _MASK; - ac >>= _DIGIT_BITS; + ac += _MASK if i >= a.used else (~a.digit[i] & _MASK) + x = ac & _MASK + ac >>= _DIGIT_BITS } else { - x = 0 if i >= a.used else a.digit[i]; + x = 0 if i >= a.used else a.digit[i] } /* Convert to 2's complement if negative. */ if neg_b { - bc += _MASK if i >= b.used else (~b.digit[i] & _MASK); - y = bc & _MASK; - bc >>= _DIGIT_BITS; + bc += _MASK if i >= b.used else (~b.digit[i] & _MASK) + y = bc & _MASK + bc >>= _DIGIT_BITS } else { - y = 0 if i >= b.used else b.digit[i]; + y = 0 if i >= b.used else b.digit[i] } - dest.digit[i] = x & y; + dest.digit[i] = x & y /* Convert to to sign-magnitude if negative. */ if neg { - cc += ~dest.digit[i] & _MASK; - dest.digit[i] = cc & _MASK; - cc >>= _DIGIT_BITS; + cc += ~dest.digit[i] & _MASK + dest.digit[i] = cc & _MASK + cc >>= _DIGIT_BITS } } - dest.used = used; - dest.sign = .Negative if neg else .Zero_or_Positive; - return internal_clamp(dest); + dest.used = used + dest.sign = .Negative if neg else .Zero_or_Positive + return internal_clamp(dest) } -internal_and :: proc { internal_int_and, }; +internal_and :: proc { internal_int_and, } /* 2's complement `or`, returns `dest = a | b;` */ internal_int_or :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator - used := max(a.used, b.used) + 1; + used := max(a.used, b.used) + 1 /* Grow the destination to accomodate the result. */ - internal_grow(dest, used) or_return; + internal_grow(dest, used) or_return - neg_a := #force_inline internal_is_negative(a); - neg_b := #force_inline internal_is_negative(b); - neg := neg_a || neg_b; + neg_a := #force_inline internal_is_negative(a) + neg_b := #force_inline internal_is_negative(b) + neg := neg_a || neg_b - ac, bc, cc := DIGIT(1), DIGIT(1), DIGIT(1); + ac, bc, cc := DIGIT(1), DIGIT(1), DIGIT(1) #no_bounds_check for i := 0; i < used; i += 1 { - x, y: DIGIT; + x, y: DIGIT /* Convert to 2's complement if negative. */ if neg_a { - ac += _MASK if i >= a.used else (~a.digit[i] & _MASK); - x = ac & _MASK; - ac >>= _DIGIT_BITS; + ac += _MASK if i >= a.used else (~a.digit[i] & _MASK) + x = ac & _MASK + ac >>= _DIGIT_BITS } else { - x = 0 if i >= a.used else a.digit[i]; + x = 0 if i >= a.used else a.digit[i] } /* Convert to 2's complement if negative. */ if neg_b { - bc += _MASK if i >= b.used else (~b.digit[i] & _MASK); - y = bc & _MASK; - bc >>= _DIGIT_BITS; + bc += _MASK if i >= b.used else (~b.digit[i] & _MASK) + y = bc & _MASK + bc >>= _DIGIT_BITS } else { - y = 0 if i >= b.used else b.digit[i]; + y = 0 if i >= b.used else b.digit[i] } - dest.digit[i] = x | y; + dest.digit[i] = x | y /* Convert to to sign-magnitude if negative. */ if neg { - cc += ~dest.digit[i] & _MASK; - dest.digit[i] = cc & _MASK; - cc >>= _DIGIT_BITS; + cc += ~dest.digit[i] & _MASK + dest.digit[i] = cc & _MASK + cc >>= _DIGIT_BITS } } - dest.used = used; - dest.sign = .Negative if neg else .Zero_or_Positive; - return internal_clamp(dest); + dest.used = used + dest.sign = .Negative if neg else .Zero_or_Positive + return internal_clamp(dest) } -internal_or :: proc { internal_int_or, }; +internal_or :: proc { internal_int_or, } /* 2's complement `xor`, returns `dest = a ~ b;` */ internal_int_xor :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator - used := max(a.used, b.used) + 1; + used := max(a.used, b.used) + 1 /* Grow the destination to accomodate the result. */ - internal_grow(dest, used) or_return; + internal_grow(dest, used) or_return - neg_a := #force_inline internal_is_negative(a); - neg_b := #force_inline internal_is_negative(b); - neg := neg_a != neg_b; + neg_a := #force_inline internal_is_negative(a) + neg_b := #force_inline internal_is_negative(b) + neg := neg_a != neg_b - ac, bc, cc := DIGIT(1), DIGIT(1), DIGIT(1); + ac, bc, cc := DIGIT(1), DIGIT(1), DIGIT(1) #no_bounds_check for i := 0; i < used; i += 1 { - x, y: DIGIT; + x, y: DIGIT /* Convert to 2's complement if negative. */ if neg_a { - ac += _MASK if i >= a.used else (~a.digit[i] & _MASK); - x = ac & _MASK; - ac >>= _DIGIT_BITS; + ac += _MASK if i >= a.used else (~a.digit[i] & _MASK) + x = ac & _MASK + ac >>= _DIGIT_BITS } else { - x = 0 if i >= a.used else a.digit[i]; + x = 0 if i >= a.used else a.digit[i] } /* Convert to 2's complement if negative. */ if neg_b { - bc += _MASK if i >= b.used else (~b.digit[i] & _MASK); - y = bc & _MASK; - bc >>= _DIGIT_BITS; + bc += _MASK if i >= b.used else (~b.digit[i] & _MASK) + y = bc & _MASK + bc >>= _DIGIT_BITS } else { - y = 0 if i >= b.used else b.digit[i]; + y = 0 if i >= b.used else b.digit[i] } - dest.digit[i] = x ~ y; + dest.digit[i] = x ~ y /* Convert to to sign-magnitude if negative. */ if neg { - cc += ~dest.digit[i] & _MASK; - dest.digit[i] = cc & _MASK; - cc >>= _DIGIT_BITS; + cc += ~dest.digit[i] & _MASK + dest.digit[i] = cc & _MASK + cc >>= _DIGIT_BITS } } - dest.used = used; - dest.sign = .Negative if neg else .Zero_or_Positive; - return internal_clamp(dest); + dest.used = used + dest.sign = .Negative if neg else .Zero_or_Positive + return internal_clamp(dest) } -internal_xor :: proc { internal_int_xor, }; +internal_xor :: proc { internal_int_xor, } /* dest = ~src */ internal_int_complement :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator /* Temporarily fix sign. */ - old_sign := src.sign; + old_sign := src.sign - neg := #force_inline internal_is_zero(src) || #force_inline internal_is_positive(src); + neg := #force_inline internal_is_zero(src) || #force_inline internal_is_positive(src) - src.sign = .Negative if neg else .Zero_or_Positive; + src.sign = .Negative if neg else .Zero_or_Positive - err = #force_inline internal_sub(dest, src, 1); + err = #force_inline internal_sub(dest, src, 1) /* Restore sign. */ - src.sign = old_sign; + src.sign = old_sign - return err; + return err } -internal_complement :: proc { internal_int_complement, }; +internal_complement :: proc { internal_int_complement, } /* quotient, remainder := numerator >> bits; `remainder` is allowed to be passed a `nil`, in which case `mod` won't be computed. */ internal_int_shrmod :: proc(quotient, remainder, numerator: ^Int, bits: int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator - bits := bits; + bits := bits if bits < 0 { return .Invalid_Argument; } - internal_copy(quotient, numerator) or_return; + internal_copy(quotient, numerator) or_return /* Shift right by a certain bit count (store quotient and optional remainder.) `numerator` should not be used after this. */ if remainder != nil { - internal_int_mod_bits(remainder, numerator, bits) or_return; + internal_int_mod_bits(remainder, numerator, bits) or_return } /* Shift by as many digits in the bit count. */ if bits >= _DIGIT_BITS { - internal_shr_digit(quotient, bits / _DIGIT_BITS) or_return; + internal_shr_digit(quotient, bits / _DIGIT_BITS) or_return } /* Shift any bit count < _DIGIT_BITS. */ - bits %= _DIGIT_BITS; + bits %= _DIGIT_BITS if bits != 0 { - mask := DIGIT(1 << uint(bits)) - 1; - shift := DIGIT(_DIGIT_BITS - bits); - carry := DIGIT(0); + mask := DIGIT(1 << uint(bits)) - 1 + shift := DIGIT(_DIGIT_BITS - bits) + carry := DIGIT(0) #no_bounds_check for x := quotient.used - 1; x >= 0; x -= 1 { /* Get the lower bits of this word in a temp. */ - fwd_carry := quotient.digit[x] & mask; + fwd_carry := quotient.digit[x] & mask /* Shift the current word and mix in the carry bits from the previous word. */ - quotient.digit[x] = (quotient.digit[x] >> uint(bits)) | (carry << shift); + quotient.digit[x] = (quotient.digit[x] >> uint(bits)) | (carry << shift) /* Update carry from forward carry. */ - carry = fwd_carry; + carry = fwd_carry } } - return internal_clamp(numerator); + return internal_clamp(numerator) } -internal_shrmod :: proc { internal_int_shrmod, }; +internal_shrmod :: proc { internal_int_shrmod, } internal_int_shr :: proc(dest, source: ^Int, bits: int, allocator := context.allocator) -> (err: Error) { - return #force_inline internal_shrmod(dest, nil, source, bits, allocator); + return #force_inline internal_shrmod(dest, nil, source, bits, allocator) } -internal_shr :: proc { internal_int_shr, }; +internal_shr :: proc { internal_int_shr, } /* Shift right by `digits` * _DIGIT_BITS bits. */ internal_int_shr_digit :: proc(quotient: ^Int, digits: int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator if digits <= 0 { return nil; } @@ -2404,88 +2404,88 @@ internal_int_shr_digit :: proc(quotient: ^Int, digits: int, allocator := context */ #no_bounds_check for x := 0; x < (quotient.used - digits); x += 1 { - quotient.digit[x] = quotient.digit[x + digits]; + quotient.digit[x] = quotient.digit[x + digits] } - quotient.used -= digits; - internal_zero_unused(quotient); - return internal_clamp(quotient); + quotient.used -= digits + internal_zero_unused(quotient) + return internal_clamp(quotient) } -internal_shr_digit :: proc { internal_int_shr_digit, }; +internal_shr_digit :: proc { internal_int_shr_digit, } /* Shift right by a certain bit count with sign extension. */ internal_int_shr_signed :: proc(dest, src: ^Int, bits: int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator if src.sign == .Zero_or_Positive { - return internal_shr(dest, src, bits); + return internal_shr(dest, src, bits) } - internal_int_add_digit(dest, src, DIGIT(1)) or_return; - internal_shr(dest, dest, bits) or_return; - return internal_sub(dest, src, DIGIT(1)); + internal_int_add_digit(dest, src, DIGIT(1)) or_return + internal_shr(dest, dest, bits) or_return + return internal_sub(dest, src, DIGIT(1)) } -internal_shr_signed :: proc { internal_int_shr_signed, }; +internal_shr_signed :: proc { internal_int_shr_signed, } /* Shift left by a certain bit count. */ internal_int_shl :: proc(dest, src: ^Int, bits: int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator - bits := bits; + bits := bits if bits < 0 { return .Invalid_Argument; } - internal_copy(dest, src) or_return; + internal_copy(dest, src) or_return /* Grow `dest` to accommodate the additional bits. */ - digits_needed := dest.used + (bits / _DIGIT_BITS) + 1; - internal_grow(dest, digits_needed) or_return; - dest.used = digits_needed; + digits_needed := dest.used + (bits / _DIGIT_BITS) + 1 + internal_grow(dest, digits_needed) or_return + dest.used = digits_needed /* Shift by as many digits in the bit count as we have. */ if bits >= _DIGIT_BITS { - internal_shl_digit(dest, bits / _DIGIT_BITS) or_return; + internal_shl_digit(dest, bits / _DIGIT_BITS) or_return } /* Shift any remaining bit count < _DIGIT_BITS */ - bits %= _DIGIT_BITS; + bits %= _DIGIT_BITS if bits != 0 { - mask := (DIGIT(1) << uint(bits)) - DIGIT(1); - shift := DIGIT(_DIGIT_BITS - bits); - carry := DIGIT(0); + mask := (DIGIT(1) << uint(bits)) - DIGIT(1) + shift := DIGIT(_DIGIT_BITS - bits) + carry := DIGIT(0) #no_bounds_check for x:= 0; x < dest.used; x+= 1 { - fwd_carry := (dest.digit[x] >> shift) & mask; - dest.digit[x] = (dest.digit[x] << uint(bits) | carry) & _MASK; - carry = fwd_carry; + fwd_carry := (dest.digit[x] >> shift) & mask + dest.digit[x] = (dest.digit[x] << uint(bits) | carry) & _MASK + carry = fwd_carry } /* Use final carry. */ if carry != 0 { - dest.digit[dest.used] = carry; - dest.used += 1; + dest.digit[dest.used] = carry + dest.used += 1 } } - return internal_clamp(dest); + return internal_clamp(dest) } -internal_shl :: proc { internal_int_shl, }; +internal_shl :: proc { internal_int_shl, } /* Shift left by `digits` * _DIGIT_BITS bits. */ internal_int_shl_digit :: proc(quotient: ^Int, digits: int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator if digits <= 0 { return nil; } @@ -2493,7 +2493,7 @@ internal_int_shl_digit :: proc(quotient: ^Int, digits: int, allocator := context No need to shift a zero. */ if #force_inline internal_is_zero(quotient) { - return nil; + return nil } /* @@ -2510,14 +2510,14 @@ internal_int_shl_digit :: proc(quotient: ^Int, digits: int, allocator := context except the window goes the other way around. */ #no_bounds_check for x := quotient.used; x > 0; x -= 1 { - quotient.digit[x+digits-1] = quotient.digit[x-1]; + quotient.digit[x+digits-1] = quotient.digit[x-1] } - quotient.used += digits; - mem.zero_slice(quotient.digit[:digits]); - return nil; + quotient.used += digits + mem.zero_slice(quotient.digit[:digits]) + return nil } -internal_shl_digit :: proc { internal_int_shl_digit, }; +internal_shl_digit :: proc { internal_int_shl_digit, } /* Count bits in an `Int`. @@ -2531,13 +2531,13 @@ internal_count_bits :: proc(a: ^Int) -> (count: int) { /* Get the number of DIGITs and use it. */ - count = (a.used - 1) * _DIGIT_BITS; + count = (a.used - 1) * _DIGIT_BITS /* Take the last DIGIT and count the bits in it. */ - clz := int(intrinsics.count_leading_zeros(a.digit[a.used - 1])); - count += (_DIGIT_TYPE_BITS - clz); - return; + clz := int(intrinsics.count_leading_zeros(a.digit[a.used - 1])) + count += (_DIGIT_TYPE_BITS - clz) + return } /* @@ -2555,117 +2555,117 @@ internal_int_count_lsb :: proc(a: ^Int) -> (count: int, err: Error) { /* Scan lower digits until non-zero. */ - x: int; + x: int #no_bounds_check for x = 0; x < a.used && a.digit[x] == 0; x += 1 {} - q := a.digit[x]; - x *= _DIGIT_BITS; - x += internal_count_lsb(q); - return x, nil; + q := a.digit[x] + x *= _DIGIT_BITS + x += internal_count_lsb(q) + return x, nil } internal_platform_count_lsb :: #force_inline proc(a: $T) -> (count: int) where intrinsics.type_is_integer(T) && intrinsics.type_is_unsigned(T) { - return int(intrinsics.count_trailing_zeros(a)) if a > 0 else 0; + return int(intrinsics.count_trailing_zeros(a)) if a > 0 else 0 } -internal_count_lsb :: proc { internal_int_count_lsb, internal_platform_count_lsb, }; +internal_count_lsb :: proc { internal_int_count_lsb, internal_platform_count_lsb, } internal_int_random_digit :: proc(r: ^rnd.Rand = nil) -> (res: DIGIT) { when _DIGIT_BITS == 60 { // DIGIT = u64 - return DIGIT(rnd.uint64(r)) & _MASK; + return DIGIT(rnd.uint64(r)) & _MASK } else when _DIGIT_BITS == 28 { // DIGIT = u32 - return DIGIT(rnd.uint32(r)) & _MASK; + return DIGIT(rnd.uint32(r)) & _MASK } else { - panic("Unsupported DIGIT size."); + panic("Unsupported DIGIT size.") } - return 0; // We shouldn't get here. + return 0 // We shouldn't get here. } internal_int_rand :: proc(dest: ^Int, bits: int, r: ^rnd.Rand = nil, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator - bits := bits; + bits := bits if bits <= 0 { return .Invalid_Argument; } - digits := bits / _DIGIT_BITS; - bits %= _DIGIT_BITS; + digits := bits / _DIGIT_BITS + bits %= _DIGIT_BITS if bits > 0 { - digits += 1; + digits += 1 } #force_inline internal_grow(dest, digits) or_return; for i := 0; i < digits; i += 1 { - dest.digit[i] = int_random_digit(r) & _MASK; + dest.digit[i] = int_random_digit(r) & _MASK } if bits > 0 { - dest.digit[digits - 1] &= ((1 << uint(bits)) - 1); + dest.digit[digits - 1] &= ((1 << uint(bits)) - 1) } - dest.used = digits; - return nil; + dest.used = digits + return nil } -internal_rand :: proc { internal_int_rand, }; +internal_rand :: proc { internal_int_rand, } /* Internal helpers. */ internal_assert_initialized :: proc(a: ^Int, loc := #caller_location) { - assert(internal_is_initialized(a), "`Int` was not properly initialized.", loc); + assert(internal_is_initialized(a), "`Int` was not properly initialized.", loc) } internal_clear_if_uninitialized_single :: proc(arg: ^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator if ! #force_inline internal_is_initialized(arg) { - return #force_inline internal_grow(arg, _DEFAULT_DIGIT_COUNT); + return #force_inline internal_grow(arg, _DEFAULT_DIGIT_COUNT) } - return err; + return err } internal_clear_if_uninitialized_multi :: proc(args: ..^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator for i in args { if ! #force_inline internal_is_initialized(i) { - e := #force_inline internal_grow(i, _DEFAULT_DIGIT_COUNT); + e := #force_inline internal_grow(i, _DEFAULT_DIGIT_COUNT) if e != nil { err = e; } } } - return err; + return err } -internal_clear_if_uninitialized :: proc {internal_clear_if_uninitialized_single, internal_clear_if_uninitialized_multi, }; +internal_clear_if_uninitialized :: proc {internal_clear_if_uninitialized_single, internal_clear_if_uninitialized_multi, } internal_error_if_immutable_single :: proc(arg: ^Int) -> (err: Error) { if arg != nil && .Immutable in arg.flags { return .Assignment_To_Immutable; } - return nil; + return nil } internal_error_if_immutable_multi :: proc(args: ..^Int) -> (err: Error) { for i in args { if i != nil && .Immutable in i.flags { return .Assignment_To_Immutable; } } - return nil; + return nil } -internal_error_if_immutable :: proc {internal_error_if_immutable_single, internal_error_if_immutable_multi, }; +internal_error_if_immutable :: proc {internal_error_if_immutable_single, internal_error_if_immutable_multi, } /* Allocates several `Int`s at once. */ internal_int_init_multi :: proc(integers: ..^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator - integers := integers; + integers := integers for a in &integers { - internal_clear(a) or_return; + internal_clear(a) or_return } - return nil; + return nil } -internal_init_multi :: proc { internal_int_init_multi, }; +internal_init_multi :: proc { internal_int_init_multi, } /* Trim unused digits. @@ -2678,7 +2678,7 @@ internal_clamp :: proc(a: ^Int) -> (err: Error) { if #force_inline internal_is_zero(a) { a.sign = .Zero_or_Positive; } - return nil; + return nil } @@ -2686,21 +2686,21 @@ internal_int_zero_unused :: #force_inline proc(dest: ^Int, old_used := -1) { /* If we don't pass the number of previously used DIGITs, we zero all remaining ones. */ - zero_count: int; + zero_count: int if old_used == -1 { - zero_count = len(dest.digit) - dest.used; + zero_count = len(dest.digit) - dest.used } else { - zero_count = old_used - dest.used; + zero_count = old_used - dest.used } /* Zero remainder. */ if zero_count > 0 && dest.used < len(dest.digit) { - mem.zero_slice(dest.digit[dest.used:][:zero_count]); + mem.zero_slice(dest.digit[dest.used:][:zero_count]) } } -internal_zero_unused :: proc { internal_int_zero_unused, }; +internal_zero_unused :: proc { internal_int_zero_unused, } /* ========================== End of low-level routines ========================== diff --git a/core/math/big/logical.odin b/core/math/big/logical.odin index 64f3b0898..d455d480d 100644 --- a/core/math/big/logical.odin +++ b/core/math/big/logical.odin @@ -22,37 +22,37 @@ package math_big 2's complement `and`, returns `dest = a & b;` */ int_and :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) { - assert_if_nil(dest, a, b); - context.allocator = allocator; + assert_if_nil(dest, a, b) + context.allocator = allocator - internal_clear_if_uninitialized(a, b) or_return; - return #force_inline internal_int_and(dest, a, b); + internal_clear_if_uninitialized(a, b) or_return + return #force_inline internal_int_and(dest, a, b) } -and :: proc { int_and, }; +and :: proc { int_and, } /* 2's complement `or`, returns `dest = a | b;` */ int_or :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) { - assert_if_nil(dest, a, b); - context.allocator = allocator; + assert_if_nil(dest, a, b) + context.allocator = allocator - internal_clear_if_uninitialized(a, b) or_return; - return #force_inline internal_int_or(dest, a, b); + internal_clear_if_uninitialized(a, b) or_return + return #force_inline internal_int_or(dest, a, b) } -or :: proc { int_or, }; +or :: proc { int_or, } /* 2's complement `xor`, returns `dest = a ^ b;` */ int_xor :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) { - assert_if_nil(dest, a, b); - context.allocator = allocator; + assert_if_nil(dest, a, b) + context.allocator = allocator - internal_clear_if_uninitialized(a, b) or_return; - return #force_inline internal_int_xor(dest, a, b); + internal_clear_if_uninitialized(a, b) or_return + return #force_inline internal_int_xor(dest, a, b) } -xor :: proc { int_xor, }; +xor :: proc { int_xor, } /* dest = ~src @@ -61,31 +61,31 @@ int_complement :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: /* Check that `src` and `dest` are usable. */ - assert_if_nil(dest, src); - context.allocator = allocator; + assert_if_nil(dest, src) + context.allocator = allocator - internal_clear_if_uninitialized(dest, src) or_return; - return #force_inline internal_int_complement(dest, src); + internal_clear_if_uninitialized(dest, src) or_return + return #force_inline internal_int_complement(dest, src) } -complement :: proc { int_complement, }; +complement :: proc { int_complement, } /* quotient, remainder := numerator >> bits; `remainder` is allowed to be passed a `nil`, in which case `mod` won't be computed. */ int_shrmod :: proc(quotient, remainder, numerator: ^Int, bits: int, allocator := context.allocator) -> (err: Error) { - assert_if_nil(quotient, numerator); - context.allocator = allocator; + assert_if_nil(quotient, numerator) + context.allocator = allocator if err = internal_clear_if_uninitialized(quotient, numerator); err != nil { return err; } - return #force_inline internal_int_shrmod(quotient, remainder, numerator, bits); + return #force_inline internal_int_shrmod(quotient, remainder, numerator, bits) } -shrmod :: proc { int_shrmod, }; +shrmod :: proc { int_shrmod, } int_shr :: proc(dest, source: ^Int, bits: int, allocator := context.allocator) -> (err: Error) { - return #force_inline shrmod(dest, nil, source, bits, allocator); + return #force_inline shrmod(dest, nil, source, bits, allocator) } -shr :: proc { int_shr, }; +shr :: proc { int_shr, } /* Shift right by `digits` * _DIGIT_BITS bits. @@ -94,38 +94,38 @@ int_shr_digit :: proc(quotient: ^Int, digits: int, allocator := context.allocato /* Check that `quotient` is usable. */ - assert_if_nil(quotient); - context.allocator = allocator; + assert_if_nil(quotient) + context.allocator = allocator - internal_clear_if_uninitialized(quotient) or_return; - return #force_inline internal_int_shr_digit(quotient, digits); + internal_clear_if_uninitialized(quotient) or_return + return #force_inline internal_int_shr_digit(quotient, digits) } -shr_digit :: proc { int_shr_digit, }; +shr_digit :: proc { int_shr_digit, } /* Shift right by a certain bit count with sign extension. */ int_shr_signed :: proc(dest, src: ^Int, bits: int, allocator := context.allocator) -> (err: Error) { - assert_if_nil(dest, src); - context.allocator = allocator; + assert_if_nil(dest, src) + context.allocator = allocator - internal_clear_if_uninitialized(dest, src) or_return; - return #force_inline internal_int_shr_signed(dest, src, bits); + internal_clear_if_uninitialized(dest, src) or_return + return #force_inline internal_int_shr_signed(dest, src, bits) } -shr_signed :: proc { int_shr_signed, }; +shr_signed :: proc { int_shr_signed, } /* Shift left by a certain bit count. */ int_shl :: proc(dest, src: ^Int, bits: int, allocator := context.allocator) -> (err: Error) { - assert_if_nil(dest, src); - context.allocator = allocator; + assert_if_nil(dest, src) + context.allocator = allocator - internal_clear_if_uninitialized(dest, src) or_return; - return #force_inline internal_int_shl(dest, src, bits); + internal_clear_if_uninitialized(dest, src) or_return + return #force_inline internal_int_shl(dest, src, bits) } -shl :: proc { int_shl, }; +shl :: proc { int_shl, } /* @@ -135,10 +135,10 @@ int_shl_digit :: proc(quotient: ^Int, digits: int, allocator := context.allocato /* Check that `quotient` is usable. */ - assert_if_nil(quotient); - context.allocator = allocator; + assert_if_nil(quotient) + context.allocator = allocator - internal_clear_if_uninitialized(quotient) or_return; - return #force_inline internal_int_shl_digit(quotient, digits); + internal_clear_if_uninitialized(quotient) or_return + return #force_inline internal_int_shl_digit(quotient, digits) } shl_digit :: proc { int_shl_digit, };
\ No newline at end of file diff --git a/core/math/big/prime.odin b/core/math/big/prime.odin index f35e02807..b943da83b 100644 --- a/core/math/big/prime.odin +++ b/core/math/big/prime.odin @@ -16,43 +16,43 @@ package math_big Returns true if it is, false if not. */ int_prime_is_divisible :: proc(a: ^Int, allocator := context.allocator) -> (res: bool, err: Error) { - assert_if_nil(a); - context.allocator = allocator; + assert_if_nil(a) + context.allocator = allocator - internal_clear_if_uninitialized(a) or_return; + internal_clear_if_uninitialized(a) or_return for prime in _private_prime_table { - rem := #force_inline int_mod_digit(a, prime) or_return; + rem := #force_inline int_mod_digit(a, prime) or_return if rem == 0 { - return true, nil; + return true, nil } } /* Default to not divisible. */ - return false, nil; + return false, nil } /* Computes xR**-1 == x (mod N) via Montgomery Reduction. */ internal_int_montgomery_reduce :: proc(x, n: ^Int, rho: DIGIT, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator /* Can the fast reduction [comba] method be used? Note that unlike in mul, you're safely allowed *less* than the available columns [255 per default], since carries are fixed up in the inner loop. */ - digs := (n.used * 2) + 1; + digs := (n.used * 2) + 1 if digs < _WARRAY && x.used <= _WARRAY && n.used < _MAX_COMBA { - return _private_montgomery_reduce_comba(x, n, rho); + return _private_montgomery_reduce_comba(x, n, rho) } /* Grow the input as required */ - internal_grow(x, digs) or_return; - x.used = digs; + internal_grow(x, digs) or_return + x.used = digs for ix := 0; ix < n.used; ix += 1 { /* @@ -62,29 +62,29 @@ internal_int_montgomery_reduce :: proc(x, n: ^Int, rho: DIGIT, allocator := cont to reduce the input one digit at a time. */ - mu := DIGIT((_WORD(x.digit[ix]) * _WORD(rho)) & _WORD(_MASK)); + mu := DIGIT((_WORD(x.digit[ix]) * _WORD(rho)) & _WORD(_MASK)) /* a = a + mu * m * b**i Multiply and add in place. */ - u := DIGIT(0); - iy := int(0); + u := DIGIT(0) + iy := int(0) for ; iy < n.used; iy += 1 { /* Compute product and sum. */ - r := (_WORD(mu) * _WORD(n.digit[iy]) + _WORD(u) + _WORD(x.digit[ix + iy])); + r := (_WORD(mu) * _WORD(n.digit[iy]) + _WORD(u) + _WORD(x.digit[ix + iy])) /* Get carry. */ - u = DIGIT(r >> _DIGIT_BITS); + u = DIGIT(r >> _DIGIT_BITS) /* Fix digit. */ - x.digit[ix + iy] = DIGIT(r & _WORD(_MASK)); + x.digit[ix + iy] = DIGIT(r & _WORD(_MASK)) } /* @@ -92,10 +92,10 @@ internal_int_montgomery_reduce :: proc(x, n: ^Int, rho: DIGIT, allocator := cont Propagate carries upwards as required. */ for u != 0 { - x.digit[ix + iy] += u; - u = x.digit[ix + iy] >> _DIGIT_BITS; - x.digit[ix + iy] &= _MASK; - iy += 1; + x.digit[ix + iy] += u + u = x.digit[ix + iy] >> _DIGIT_BITS + x.digit[ix + iy] &= _MASK + iy += 1 } } @@ -106,26 +106,26 @@ internal_int_montgomery_reduce :: proc(x, n: ^Int, rho: DIGIT, allocator := cont x = x/b**n.used. */ - internal_clamp(x); - internal_shr_digit(x, n.used); + internal_clamp(x) + internal_shr_digit(x, n.used) /* if x >= n then x = x - n */ if internal_cmp_mag(x, n) != -1 { - return internal_sub(x, x, n); + return internal_sub(x, x, n) } - return nil; + return nil } int_montgomery_reduce :: proc(x, n: ^Int, rho: DIGIT, allocator := context.allocator) -> (err: Error) { - assert_if_nil(x, n); - context.allocator = allocator; + assert_if_nil(x, n) + context.allocator = allocator - internal_clear_if_uninitialized(x, n) or_return; + internal_clear_if_uninitialized(x, n) or_return - return #force_inline internal_int_montgomery_reduce(x, n, rho); + return #force_inline internal_int_montgomery_reduce(x, n, rho) } /* @@ -135,39 +135,39 @@ int_montgomery_reduce :: proc(x, n: ^Int, rho: DIGIT, allocator := context.alloc the leading bit of b. This saves alot of multiple precision shifting. */ internal_int_montgomery_calc_normalization :: proc(a, b: ^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator /* How many bits of last digit does b use. */ - bits := internal_count_bits(b) % _DIGIT_BITS; + bits := internal_count_bits(b) % _DIGIT_BITS if b.used > 1 { - power := ((b.used - 1) * _DIGIT_BITS) + bits - 1; - internal_int_power_of_two(a, power) or_return; + power := ((b.used - 1) * _DIGIT_BITS) + bits - 1 + internal_int_power_of_two(a, power) or_return } else { - internal_one(a); - bits = 1; + internal_one(a) + bits = 1 } /* Now compute C = A * B mod b. */ for x := bits - 1; x < _DIGIT_BITS; x += 1 { - internal_int_shl1(a, a) or_return; + internal_int_shl1(a, a) or_return if internal_cmp_mag(a, b) != -1 { - internal_sub(a, a, b) or_return; + internal_sub(a, a, b) or_return } } - return nil; + return nil } int_montgomery_calc_normalization :: proc(a, b: ^Int, allocator := context.allocator) -> (err: Error) { - assert_if_nil(a, b); - context.allocator = allocator; + assert_if_nil(a, b) + context.allocator = allocator - internal_clear_if_uninitialized(a, b) or_return; + internal_clear_if_uninitialized(a, b) or_return - return #force_inline internal_int_montgomery_calc_normalization(a, b); + return #force_inline internal_int_montgomery_calc_normalization(a, b) } /* @@ -182,29 +182,29 @@ internal_int_montgomery_setup :: proc(n: ^Int) -> (rho: DIGIT, err: Error) { => 2*X*A - X*X*A*A = 1 => 2*(1) - (1) = 1 */ - b := n.digit[0]; + b := n.digit[0] if b & 1 == 0 { return 0, .Invalid_Argument; } - x := (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ - x *= 2 - (b * x); /* here x*a==1 mod 2**8 */ - x *= 2 - (b * x); /* here x*a==1 mod 2**16 */ + x := (((b + 2) & 4) << 1) + b /* here x*a==1 mod 2**4 */ + x *= 2 - (b * x) /* here x*a==1 mod 2**8 */ + x *= 2 - (b * x) /* here x*a==1 mod 2**16 */ when _WORD_TYPE_BITS == 64 { - x *= 2 - (b * x); /* here x*a==1 mod 2**32 */ - x *= 2 - (b * x); /* here x*a==1 mod 2**64 */ + x *= 2 - (b * x) /* here x*a==1 mod 2**32 */ + x *= 2 - (b * x) /* here x*a==1 mod 2**64 */ } /* rho = -1/m mod b */ - rho = DIGIT(((_WORD(1) << _WORD(_DIGIT_BITS)) - _WORD(x)) & _WORD(_MASK)); - return rho, nil; + rho = DIGIT(((_WORD(1) << _WORD(_DIGIT_BITS)) - _WORD(x)) & _WORD(_MASK)) + return rho, nil } int_montgomery_setup :: proc(n: ^Int, allocator := context.allocator) -> (rho: DIGIT, err: Error) { - assert_if_nil(n); - internal_clear_if_uninitialized(n, allocator) or_return; + assert_if_nil(n) + internal_clear_if_uninitialized(n, allocator) or_return - return #force_inline internal_int_montgomery_setup(n); + return #force_inline internal_int_montgomery_setup(n) } /* @@ -213,44 +213,44 @@ int_montgomery_setup :: proc(n: ^Int, allocator := context.allocator) -> (rho: D number_of_rabin_miller_trials :: proc(bit_size: int) -> (number_of_trials: int) { switch { case bit_size <= 80: - return - 1; /* Use deterministic algorithm for size <= 80 bits */ + return - 1 /* Use deterministic algorithm for size <= 80 bits */ case bit_size >= 81 && bit_size < 96: - return 37; /* max. error = 2^(-96) */ + return 37 /* max. error = 2^(-96) */ case bit_size >= 96 && bit_size < 128: - return 32; /* max. error = 2^(-96) */ + return 32 /* max. error = 2^(-96) */ case bit_size >= 128 && bit_size < 160: - return 40; /* max. error = 2^(-112) */ + return 40 /* max. error = 2^(-112) */ case bit_size >= 160 && bit_size < 256: - return 35; /* max. error = 2^(-112) */ + return 35 /* max. error = 2^(-112) */ case bit_size >= 256 && bit_size < 384: - return 27; /* max. error = 2^(-128) */ + return 27 /* max. error = 2^(-128) */ case bit_size >= 384 && bit_size < 512: - return 16; /* max. error = 2^(-128) */ + return 16 /* max. error = 2^(-128) */ case bit_size >= 512 && bit_size < 768: - return 18; /* max. error = 2^(-160) */ + return 18 /* max. error = 2^(-160) */ case bit_size >= 768 && bit_size < 896: - return 11; /* max. error = 2^(-160) */ + return 11 /* max. error = 2^(-160) */ case bit_size >= 896 && bit_size < 1_024: - return 10; /* max. error = 2^(-160) */ + return 10 /* max. error = 2^(-160) */ case bit_size >= 1_024 && bit_size < 1_536: - return 12; /* max. error = 2^(-192) */ + return 12 /* max. error = 2^(-192) */ case bit_size >= 1_536 && bit_size < 2_048: - return 8; /* max. error = 2^(-192) */ + return 8 /* max. error = 2^(-192) */ case bit_size >= 2_048 && bit_size < 3_072: - return 6; /* max. error = 2^(-192) */ + return 6 /* max. error = 2^(-192) */ case bit_size >= 3_072 && bit_size < 4_096: - return 4; /* max. error = 2^(-192) */ + return 4 /* max. error = 2^(-192) */ case bit_size >= 4_096 && bit_size < 5_120: - return 5; /* max. error = 2^(-256) */ + return 5 /* max. error = 2^(-256) */ case bit_size >= 5_120 && bit_size < 6_144: - return 4; /* max. error = 2^(-256) */ + return 4 /* max. error = 2^(-256) */ case bit_size >= 6_144 && bit_size < 8_192: - return 4; /* max. error = 2^(-256) */ + return 4 /* max. error = 2^(-256) */ case bit_size >= 8_192 && bit_size < 9_216: - return 3; /* max. error = 2^(-256) */ + return 3 /* max. error = 2^(-256) */ case bit_size >= 9_216 && bit_size < 10_240: - return 3; /* max. error = 2^(-256) */ + return 3 /* max. error = 2^(-256) */ case: - return 2; /* For keysizes bigger than 10_240 use always at least 2 Rounds */ + return 2 /* For keysizes bigger than 10_240 use always at least 2 Rounds */ } }
\ No newline at end of file diff --git a/core/math/big/private.odin b/core/math/big/private.odin index d71946ce2..81bae57f0 100644 --- a/core/math/big/private.odin +++ b/core/math/big/private.odin @@ -27,35 +27,35 @@ import "core:mem" many digits of output are created.
*/
_private_int_mul :: proc(dest, a, b: ^Int, digits: int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
/*
Can we use the fast multiplier?
*/
if digits < _WARRAY && min(a.used, b.used) < _MAX_COMBA {
- return #force_inline _private_int_mul_comba(dest, a, b, digits);
+ return #force_inline _private_int_mul_comba(dest, a, b, digits)
}
/*
Set up temporary output `Int`, which we'll swap for `dest` when done.
*/
- t := &Int{};
+ t := &Int{}
- internal_grow(t, max(digits, _DEFAULT_DIGIT_COUNT)) or_return;
- t.used = digits;
+ internal_grow(t, max(digits, _DEFAULT_DIGIT_COUNT)) or_return
+ t.used = digits
/*
Compute the digits of the product directly.
*/
- pa := a.used;
+ pa := a.used
for ix := 0; ix < pa; ix += 1 {
/*
Limit ourselves to `digits` DIGITs of output.
*/
- pb := min(b.used, digits - ix);
- carry := _WORD(0);
- iy := 0;
+ pb := min(b.used, digits - ix)
+ carry := _WORD(0)
+ iy := 0
/*
Compute the column of the output and propagate the carry.
@@ -64,29 +64,29 @@ _private_int_mul :: proc(dest, a, b: ^Int, digits: int, allocator := context.all /*
Compute the column as a _WORD.
*/
- column := _WORD(t.digit[ix + iy]) + _WORD(a.digit[ix]) * _WORD(b.digit[iy]) + carry;
+ column := _WORD(t.digit[ix + iy]) + _WORD(a.digit[ix]) * _WORD(b.digit[iy]) + carry
/*
The new column is the lower part of the result.
*/
- t.digit[ix + iy] = DIGIT(column & _WORD(_MASK));
+ t.digit[ix + iy] = DIGIT(column & _WORD(_MASK))
/*
Get the carry word from the result.
*/
- carry = column >> _DIGIT_BITS;
+ carry = column >> _DIGIT_BITS
}
/*
Set carry if it is placed below digits
*/
if ix + iy < digits {
- t.digit[ix + pb] = DIGIT(carry);
+ t.digit[ix + pb] = DIGIT(carry)
}
}
- internal_swap(dest, t);
- internal_destroy(t);
- return internal_clamp(dest);
+ internal_swap(dest, t)
+ internal_destroy(t)
+ return internal_clamp(dest)
}
@@ -110,121 +110,121 @@ _private_int_mul :: proc(dest, a, b: ^Int, digits: int, allocator := context.all Centro Vito Volterra Universita di Roma Tor Vergata (2006)
*/
_private_int_mul_toom :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
- S1, S2, T1, a0, a1, a2, b0, b1, b2 := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
- defer internal_destroy(S1, S2, T1, a0, a1, a2, b0, b1, b2);
+ S1, S2, T1, a0, a1, a2, b0, b1, b2 := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}
+ defer internal_destroy(S1, S2, T1, a0, a1, a2, b0, b1, b2)
/*
Init temps.
*/
- internal_init_multi(S1, S2, T1) or_return;
+ internal_init_multi(S1, S2, T1) or_return
/*
B
*/
- B := min(a.used, b.used) / 3;
+ B := min(a.used, b.used) / 3
/*
a = a2 * x^2 + a1 * x + a0;
*/
- internal_grow(a0, B) or_return;
- internal_grow(a1, B) or_return;
- internal_grow(a2, a.used - 2 * B) or_return;
+ internal_grow(a0, B) or_return
+ internal_grow(a1, B) or_return
+ internal_grow(a2, a.used - 2 * B) or_return
- a0.used, a1.used = B, B;
- a2.used = a.used - 2 * B;
+ a0.used, a1.used = B, B
+ a2.used = a.used - 2 * B
- internal_copy_digits(a0, a, a0.used) or_return;
- internal_copy_digits(a1, a, a1.used, B) or_return;
- internal_copy_digits(a2, a, a2.used, 2 * B) or_return;
+ internal_copy_digits(a0, a, a0.used) or_return
+ internal_copy_digits(a1, a, a1.used, B) or_return
+ internal_copy_digits(a2, a, a2.used, 2 * B) or_return
- internal_clamp(a0);
- internal_clamp(a1);
- internal_clamp(a2);
+ internal_clamp(a0)
+ internal_clamp(a1)
+ internal_clamp(a2)
/*
b = b2 * x^2 + b1 * x + b0;
*/
- internal_grow(b0, B) or_return;
- internal_grow(b1, B) or_return;
- internal_grow(b2, b.used - 2 * B) or_return;
+ internal_grow(b0, B) or_return
+ internal_grow(b1, B) or_return
+ internal_grow(b2, b.used - 2 * B) or_return
- b0.used, b1.used = B, B;
- b2.used = b.used - 2 * B;
+ b0.used, b1.used = B, B
+ b2.used = b.used - 2 * B
- internal_copy_digits(b0, b, b0.used) or_return;
- internal_copy_digits(b1, b, b1.used, B) or_return;
- internal_copy_digits(b2, b, b2.used, 2 * B) or_return;
+ internal_copy_digits(b0, b, b0.used) or_return
+ internal_copy_digits(b1, b, b1.used, B) or_return
+ internal_copy_digits(b2, b, b2.used, 2 * B) or_return
- internal_clamp(b0);
- internal_clamp(b1);
- internal_clamp(b2);
+ internal_clamp(b0)
+ internal_clamp(b1)
+ internal_clamp(b2)
/*
\\ S1 = (a2+a1+a0) * (b2+b1+b0);
*/
- internal_add(T1, a2, a1) or_return; /* T1 = a2 + a1; */
- internal_add(S2, T1, a0) or_return; /* S2 = T1 + a0; */
- internal_add(dest, b2, b1) or_return; /* dest = b2 + b1; */
- internal_add(S1, dest, b0) or_return; /* S1 = c + b0; */
- internal_mul(S1, S1, S2) or_return; /* S1 = S1 * S2; */
+ internal_add(T1, a2, a1) or_return /* T1 = a2 + a1; */
+ internal_add(S2, T1, a0) or_return /* S2 = T1 + a0; */
+ internal_add(dest, b2, b1) or_return /* dest = b2 + b1; */
+ internal_add(S1, dest, b0) or_return /* S1 = c + b0; */
+ internal_mul(S1, S1, S2) or_return /* S1 = S1 * S2; */
/*
\\S2 = (4*a2+2*a1+a0) * (4*b2+2*b1+b0);
*/
- internal_add(T1, T1, a2) or_return; /* T1 = T1 + a2; */
- internal_int_shl1(T1, T1) or_return; /* T1 = T1 << 1; */
- internal_add(T1, T1, a0) or_return; /* T1 = T1 + a0; */
- internal_add(dest, dest, b2) or_return; /* c = c + b2; */
- internal_int_shl1(dest, dest) or_return; /* c = c << 1; */
- internal_add(dest, dest, b0) or_return; /* c = c + b0; */
- internal_mul(S2, T1, dest) or_return; /* S2 = T1 * c; */
+ internal_add(T1, T1, a2) or_return /* T1 = T1 + a2; */
+ internal_int_shl1(T1, T1) or_return /* T1 = T1 << 1; */
+ internal_add(T1, T1, a0) or_return /* T1 = T1 + a0; */
+ internal_add(dest, dest, b2) or_return /* c = c + b2; */
+ internal_int_shl1(dest, dest) or_return /* c = c << 1; */
+ internal_add(dest, dest, b0) or_return /* c = c + b0; */
+ internal_mul(S2, T1, dest) or_return /* S2 = T1 * c; */
/*
\\S3 = (a2-a1+a0) * (b2-b1+b0);
*/
- internal_sub(a1, a2, a1) or_return; /* a1 = a2 - a1; */
- internal_add(a1, a1, a0) or_return; /* a1 = a1 + a0; */
- internal_sub(b1, b2, b1) or_return; /* b1 = b2 - b1; */
- internal_add(b1, b1, b0) or_return; /* b1 = b1 + b0; */
- internal_mul(a1, a1, b1) or_return; /* a1 = a1 * b1; */
- internal_mul(b1, a2, b2) or_return; /* b1 = a2 * b2; */
+ internal_sub(a1, a2, a1) or_return /* a1 = a2 - a1; */
+ internal_add(a1, a1, a0) or_return /* a1 = a1 + a0; */
+ internal_sub(b1, b2, b1) or_return /* b1 = b2 - b1; */
+ internal_add(b1, b1, b0) or_return /* b1 = b1 + b0; */
+ internal_mul(a1, a1, b1) or_return /* a1 = a1 * b1; */
+ internal_mul(b1, a2, b2) or_return /* b1 = a2 * b2; */
/*
\\S2 = (S2 - S3) / 3;
*/
- internal_sub(S2, S2, a1) or_return; /* S2 = S2 - a1; */
- _private_int_div_3(S2, S2) or_return; /* S2 = S2 / 3; \\ this is an exact division */
- internal_sub(a1, S1, a1) or_return; /* a1 = S1 - a1; */
- internal_int_shr1(a1, a1) or_return; /* a1 = a1 >> 1; */
- internal_mul(a0, a0, b0) or_return; /* a0 = a0 * b0; */
- internal_sub(S1, S1, a0) or_return; /* S1 = S1 - a0; */
- internal_sub(S2, S2, S1) or_return; /* S2 = S2 - S1; */
- internal_int_shr1(S2, S2) or_return; /* S2 = S2 >> 1; */
- internal_sub(S1, S1, a1) or_return; /* S1 = S1 - a1; */
- internal_sub(S1, S1, b1) or_return; /* S1 = S1 - b1; */
- internal_int_shl1(T1, b1) or_return; /* T1 = b1 << 1; */
- internal_sub(S2, S2, T1) or_return; /* S2 = S2 - T1; */
- internal_sub(a1, a1, S2) or_return; /* a1 = a1 - S2; */
+ internal_sub(S2, S2, a1) or_return /* S2 = S2 - a1; */
+ _private_int_div_3(S2, S2) or_return /* S2 = S2 / 3; \\ this is an exact division */
+ internal_sub(a1, S1, a1) or_return /* a1 = S1 - a1; */
+ internal_int_shr1(a1, a1) or_return /* a1 = a1 >> 1; */
+ internal_mul(a0, a0, b0) or_return /* a0 = a0 * b0; */
+ internal_sub(S1, S1, a0) or_return /* S1 = S1 - a0; */
+ internal_sub(S2, S2, S1) or_return /* S2 = S2 - S1; */
+ internal_int_shr1(S2, S2) or_return /* S2 = S2 >> 1; */
+ internal_sub(S1, S1, a1) or_return /* S1 = S1 - a1; */
+ internal_sub(S1, S1, b1) or_return /* S1 = S1 - b1; */
+ internal_int_shl1(T1, b1) or_return /* T1 = b1 << 1; */
+ internal_sub(S2, S2, T1) or_return /* S2 = S2 - T1; */
+ internal_sub(a1, a1, S2) or_return /* a1 = a1 - S2; */
/*
P = b1*x^4+ S2*x^3+ S1*x^2+ a1*x + a0;
*/
- internal_shl_digit(b1, 4 * B) or_return;
- internal_shl_digit(S2, 3 * B) or_return;
- internal_add(b1, b1, S2) or_return;
- internal_shl_digit(S1, 2 * B) or_return;
- internal_add(b1, b1, S1) or_return;
- internal_shl_digit(a1, 1 * B) or_return;
- internal_add(b1, b1, a1) or_return;
- internal_add(dest, b1, a0) or_return;
+ internal_shl_digit(b1, 4 * B) or_return
+ internal_shl_digit(S2, 3 * B) or_return
+ internal_add(b1, b1, S2) or_return
+ internal_shl_digit(S1, 2 * B) or_return
+ internal_add(b1, b1, S1) or_return
+ internal_shl_digit(a1, 1 * B) or_return
+ internal_add(b1, b1, a1) or_return
+ internal_add(dest, b1, a0) or_return
/*
a * b - P
*/
- return nil;
+ return nil
}
/*
@@ -255,76 +255,76 @@ _private_int_mul_toom :: proc(dest, a, b: ^Int, allocator := context.allocator) until a certain size is reached, of around 80 used DIGITs.
*/
_private_int_mul_karatsuba :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
- x0, x1, y0, y1, t1, x0y0, x1y1 := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
- defer internal_destroy(x0, x1, y0, y1, t1, x0y0, x1y1);
+ x0, x1, y0, y1, t1, x0y0, x1y1 := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}
+ defer internal_destroy(x0, x1, y0, y1, t1, x0y0, x1y1)
/*
min # of digits, divided by two.
*/
- B := min(a.used, b.used) >> 1;
+ B := min(a.used, b.used) >> 1
/*
Init all the temps.
*/
- internal_grow(x0, B) or_return;
- internal_grow(x1, a.used - B) or_return;
- internal_grow(y0, B) or_return;
- internal_grow(y1, b.used - B) or_return;
- internal_grow(t1, B * 2) or_return;
- internal_grow(x0y0, B * 2) or_return;
- internal_grow(x1y1, B * 2) or_return;
+ internal_grow(x0, B) or_return
+ internal_grow(x1, a.used - B) or_return
+ internal_grow(y0, B) or_return
+ internal_grow(y1, b.used - B) or_return
+ internal_grow(t1, B * 2) or_return
+ internal_grow(x0y0, B * 2) or_return
+ internal_grow(x1y1, B * 2) or_return
/*
Now shift the digits.
*/
- x0.used, y0.used = B, B;
- x1.used = a.used - B;
- y1.used = b.used - B;
+ x0.used, y0.used = B, B
+ x1.used = a.used - B
+ y1.used = b.used - B
/*
We copy the digits directly instead of using higher level functions
since we also need to shift the digits.
*/
- internal_copy_digits(x0, a, x0.used);
- internal_copy_digits(y0, b, y0.used);
- internal_copy_digits(x1, a, x1.used, B);
- internal_copy_digits(y1, b, y1.used, B);
+ internal_copy_digits(x0, a, x0.used)
+ internal_copy_digits(y0, b, y0.used)
+ internal_copy_digits(x1, a, x1.used, B)
+ internal_copy_digits(y1, b, y1.used, B)
/*
Only need to clamp the lower words since by definition the
upper words x1/y1 must have a known number of digits.
*/
- clamp(x0);
- clamp(y0);
+ clamp(x0)
+ clamp(y0)
/*
Now calc the products x0y0 and x1y1,
after this x0 is no longer required, free temp [x0==t2]!
*/
- internal_mul(x0y0, x0, y0) or_return; /* x0y0 = x0*y0 */
- internal_mul(x1y1, x1, y1) or_return; /* x1y1 = x1*y1 */
- internal_add(t1, x1, x0) or_return; /* now calc x1+x0 and */
- internal_add(x0, y1, y0) or_return; /* t2 = y1 + y0 */
- internal_mul(t1, t1, x0) or_return; /* t1 = (x1 + x0) * (y1 + y0) */
+ internal_mul(x0y0, x0, y0) or_return /* x0y0 = x0*y0 */
+ internal_mul(x1y1, x1, y1) or_return /* x1y1 = x1*y1 */
+ internal_add(t1, x1, x0) or_return /* now calc x1+x0 and */
+ internal_add(x0, y1, y0) or_return /* t2 = y1 + y0 */
+ internal_mul(t1, t1, x0) or_return /* t1 = (x1 + x0) * (y1 + y0) */
/*
Add x0y0.
*/
- internal_add(x0, x0y0, x1y1) or_return; /* t2 = x0y0 + x1y1 */
- internal_sub(t1, t1, x0) or_return; /* t1 = (x1+x0)*(y1+y0) - (x1y1 + x0y0) */
+ internal_add(x0, x0y0, x1y1) or_return /* t2 = x0y0 + x1y1 */
+ internal_sub(t1, t1, x0) or_return /* t1 = (x1+x0)*(y1+y0) - (x1y1 + x0y0) */
/*
shift by B.
*/
- internal_shl_digit(t1, B) or_return; /* t1 = (x0y0 + x1y1 - (x1-x0)*(y1-y0))<<B */
- internal_shl_digit(x1y1, B * 2) or_return; /* x1y1 = x1y1 << 2*B */
+ internal_shl_digit(t1, B) or_return /* t1 = (x0y0 + x1y1 - (x1-x0)*(y1-y0))<<B */
+ internal_shl_digit(x1y1, B * 2) or_return /* x1y1 = x1y1 << 2*B */
- internal_add(t1, x0y0, t1) or_return; /* t1 = x0y0 + t1 */
- internal_add(dest, t1, x1y1) or_return; /* t1 = x0y0 + t1 + x1y1 */
+ internal_add(t1, x0y0, t1) or_return /* t1 = x0y0 + t1 */
+ internal_add(dest, t1, x1y1) or_return /* t1 = x0y0 + t1 + x1y1 */
- return nil;
+ return nil
}
@@ -346,84 +346,84 @@ _private_int_mul_karatsuba :: proc(dest, a, b: ^Int, allocator := context.alloca Based on Algorithm 14.12 on pp.595 of HAC.
*/
_private_int_mul_comba :: proc(dest, a, b: ^Int, digits: int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
/*
Set up array.
*/
- W: [_WARRAY]DIGIT = ---;
+ W: [_WARRAY]DIGIT = ---
/*
Grow the destination as required.
*/
- internal_grow(dest, digits) or_return;
+ internal_grow(dest, digits) or_return
/*
Number of output digits to produce.
*/
- pa := min(digits, a.used + b.used);
+ pa := min(digits, a.used + b.used)
/*
Clear the carry
*/
- _W := _WORD(0);
+ _W := _WORD(0)
- ix: int;
+ ix: int
for ix = 0; ix < pa; ix += 1 {
- tx, ty, iy, iz: int;
+ tx, ty, iy, iz: int
/*
Get offsets into the two bignums.
*/
- ty = min(b.used - 1, ix);
- tx = ix - ty;
+ ty = min(b.used - 1, ix)
+ tx = ix - ty
/*
This is the number of times the loop will iterate, essentially.
while (tx++ < a->used && ty-- >= 0) { ... }
*/
- iy = min(a.used - tx, ty + 1);
+ iy = min(a.used - tx, ty + 1)
/*
Execute loop.
*/
#no_bounds_check for iz = 0; iz < iy; iz += 1 {
- _W += _WORD(a.digit[tx + iz]) * _WORD(b.digit[ty - iz]);
+ _W += _WORD(a.digit[tx + iz]) * _WORD(b.digit[ty - iz])
}
/*
Store term.
*/
- W[ix] = DIGIT(_W) & _MASK;
+ W[ix] = DIGIT(_W) & _MASK
/*
Make next carry.
*/
- _W = _W >> _WORD(_DIGIT_BITS);
+ _W = _W >> _WORD(_DIGIT_BITS)
}
/*
Setup dest.
*/
- old_used := dest.used;
- dest.used = pa;
+ old_used := dest.used
+ dest.used = pa
/*
Now extract the previous digit [below the carry].
*/
- copy_slice(dest.digit[0:], W[:pa]);
+ copy_slice(dest.digit[0:], W[:pa])
/*
Clear unused digits [that existed in the old copy of dest].
*/
- internal_zero_unused(dest, old_used);
+ internal_zero_unused(dest, old_used)
/*
Adjust dest.used based on leading zeroes.
*/
- return internal_clamp(dest);
+ return internal_clamp(dest)
}
/*
@@ -431,42 +431,42 @@ _private_int_mul_comba :: proc(dest, a, b: ^Int, digits: int, allocator := conte [meant to get the higher part of the product]
*/
_private_int_mul_high :: proc(dest, a, b: ^Int, digits: int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
/*
Can we use the fast multiplier?
*/
if a.used + b.used + 1 < _WARRAY && min(a.used, b.used) < _MAX_COMBA {
- return _private_int_mul_high_comba(dest, a, b, digits);
+ return _private_int_mul_high_comba(dest, a, b, digits)
}
- internal_grow(dest, a.used + b.used + 1) or_return;
- dest.used = a.used + b.used + 1;
+ internal_grow(dest, a.used + b.used + 1) or_return
+ dest.used = a.used + b.used + 1
- pa := a.used;
- pb := b.used;
+ pa := a.used
+ pb := b.used
for ix := 0; ix < pa; ix += 1 {
- carry := DIGIT(0);
+ carry := DIGIT(0)
for iy := digits - ix; iy < pb; iy += 1 {
/*
Calculate the double precision result.
*/
- r := _WORD(dest.digit[ix + iy]) + _WORD(a.digit[ix]) * _WORD(b.digit[iy]) + _WORD(carry);
+ r := _WORD(dest.digit[ix + iy]) + _WORD(a.digit[ix]) * _WORD(b.digit[iy]) + _WORD(carry)
/*
Get the lower part.
*/
- dest.digit[ix + iy] = DIGIT(r & _WORD(_MASK));
+ dest.digit[ix + iy] = DIGIT(r & _WORD(_MASK))
/*
Carry the carry.
*/
- carry = DIGIT(r >> _WORD(_DIGIT_BITS));
+ carry = DIGIT(r >> _WORD(_DIGIT_BITS))
}
- dest.digit[ix + pb] = carry;
+ dest.digit[ix + pb] = carry
}
- return internal_clamp(dest);
+ return internal_clamp(dest)
}
/*
@@ -479,140 +479,140 @@ _private_int_mul_high :: proc(dest, a, b: ^Int, digits: int, allocator := contex Based on Algorithm 14.12 on pp.595 of HAC.
*/
_private_int_mul_high_comba :: proc(dest, a, b: ^Int, digits: int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
- W: [_WARRAY]DIGIT = ---;
- _W: _WORD = 0;
+ W: [_WARRAY]DIGIT = ---
+ _W: _WORD = 0
/*
Number of output digits to produce. Grow the destination as required.
*/
- pa := a.used + b.used;
- internal_grow(dest, pa) or_return;
+ pa := a.used + b.used
+ internal_grow(dest, pa) or_return
- ix: int;
+ ix: int
for ix = digits; ix < pa; ix += 1 {
/*
Get offsets into the two bignums.
*/
- ty := min(b.used - 1, ix);
- tx := ix - ty;
+ ty := min(b.used - 1, ix)
+ tx := ix - ty
/*
This is the number of times the loop will iterrate, essentially it's
while (tx++ < a->used && ty-- >= 0) { ... }
*/
- iy := min(a.used - tx, ty + 1);
+ iy := min(a.used - tx, ty + 1)
/*
Execute loop.
*/
for iz := 0; iz < iy; iz += 1 {
- _W += _WORD(a.digit[tx + iz]) * _WORD(b.digit[ty - iz]);
+ _W += _WORD(a.digit[tx + iz]) * _WORD(b.digit[ty - iz])
}
/*
Store term.
*/
- W[ix] = DIGIT(_W) & DIGIT(_MASK);
+ W[ix] = DIGIT(_W) & DIGIT(_MASK)
/*
Make next carry.
*/
- _W = _W >> _WORD(_DIGIT_BITS);
+ _W = _W >> _WORD(_DIGIT_BITS)
}
/*
Setup dest
*/
- old_used := dest.used;
- dest.used = pa;
+ old_used := dest.used
+ dest.used = pa
for ix = digits; ix < pa; ix += 1 {
/*
Now extract the previous digit [below the carry].
*/
- dest.digit[ix] = W[ix];
+ dest.digit[ix] = W[ix]
}
/*
Zero remainder.
*/
- internal_zero_unused(dest, old_used);
+ internal_zero_unused(dest, old_used)
/*
Adjust dest.used based on leading zeroes.
*/
- return internal_clamp(dest);
+ return internal_clamp(dest)
}
/*
Single-digit multiplication with the smaller number as the single-digit.
*/
_private_int_mul_balance :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
- a, b := a, b;
+ context.allocator = allocator
+ a, b := a, b
- a0, tmp, r := &Int{}, &Int{}, &Int{};
- defer internal_destroy(a0, tmp, r);
+ a0, tmp, r := &Int{}, &Int{}, &Int{}
+ defer internal_destroy(a0, tmp, r)
- b_size := min(a.used, b.used);
- n_blocks := max(a.used, b.used) / b_size;
+ b_size := min(a.used, b.used)
+ n_blocks := max(a.used, b.used) / b_size
- internal_grow(a0, b_size + 2) or_return;
- internal_init_multi(tmp, r) or_return;
+ internal_grow(a0, b_size + 2) or_return
+ internal_init_multi(tmp, r) or_return
/*
Make sure that `a` is the larger one.
*/
if a.used < b.used {
- a, b = b, a;
+ a, b = b, a
}
- assert(a.used >= b.used);
+ assert(a.used >= b.used)
- i, j := 0, 0;
+ i, j := 0, 0
for ; i < n_blocks; i += 1 {
/*
Cut a slice off of `a`.
*/
- a0.used = b_size;
- internal_copy_digits(a0, a, a0.used, j);
- j += a0.used;
- internal_clamp(a0);
+ a0.used = b_size
+ internal_copy_digits(a0, a, a0.used, j)
+ j += a0.used
+ internal_clamp(a0)
/*
Multiply with `b`.
*/
- internal_mul(tmp, a0, b) or_return;
+ internal_mul(tmp, a0, b) or_return
/*
Shift `tmp` to the correct position.
*/
- internal_shl_digit(tmp, b_size * i) or_return;
+ internal_shl_digit(tmp, b_size * i) or_return
/*
Add to output. No carry needed.
*/
- internal_add(r, r, tmp) or_return;
+ internal_add(r, r, tmp) or_return
}
/*
The left-overs; there are always left-overs.
*/
if j < a.used {
- a0.used = a.used - j;
- internal_copy_digits(a0, a, a0.used, j);
- j += a0.used;
- internal_clamp(a0);
-
- internal_mul(tmp, a0, b) or_return;
- internal_shl_digit(tmp, b_size * i) or_return;
- internal_add(r, r, tmp) or_return;
+ a0.used = a.used - j
+ internal_copy_digits(a0, a, a0.used, j)
+ j += a0.used
+ internal_clamp(a0)
+
+ internal_mul(tmp, a0, b) or_return
+ internal_shl_digit(tmp, b_size * i) or_return
+ internal_add(r, r, tmp) or_return
}
- internal_swap(dest, r);
- return;
+ internal_swap(dest, r)
+ return
}
/*
@@ -620,68 +620,68 @@ _private_int_mul_balance :: proc(dest, a, b: ^Int, allocator := context.allocato Assumes `dest` and `src` to not be `nil`, and `src` to have been initialized.
*/
_private_int_sqr :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
- pa := src.used;
+ context.allocator = allocator
+ pa := src.used
- t := &Int{}; ix, iy: int;
+ t := &Int{}; ix, iy: int
/*
Grow `t` to maximum needed size, or `_DEFAULT_DIGIT_COUNT`, whichever is bigger.
*/
- internal_grow(t, max((2 * pa) + 1, _DEFAULT_DIGIT_COUNT)) or_return;
- t.used = (2 * pa) + 1;
+ internal_grow(t, max((2 * pa) + 1, _DEFAULT_DIGIT_COUNT)) or_return
+ t.used = (2 * pa) + 1
#no_bounds_check for ix = 0; ix < pa; ix += 1 {
- carry := DIGIT(0);
+ carry := DIGIT(0)
/*
First calculate the digit at 2*ix; calculate double precision result.
*/
- r := _WORD(t.digit[ix+ix]) + (_WORD(src.digit[ix]) * _WORD(src.digit[ix]));
+ r := _WORD(t.digit[ix+ix]) + (_WORD(src.digit[ix]) * _WORD(src.digit[ix]))
/*
Store lower part in result.
*/
- t.digit[ix+ix] = DIGIT(r & _WORD(_MASK));
+ t.digit[ix+ix] = DIGIT(r & _WORD(_MASK))
/*
Get the carry.
*/
- carry = DIGIT(r >> _DIGIT_BITS);
+ carry = DIGIT(r >> _DIGIT_BITS)
#no_bounds_check for iy = ix + 1; iy < pa; iy += 1 {
/*
First calculate the product.
*/
- r = _WORD(src.digit[ix]) * _WORD(src.digit[iy]);
+ r = _WORD(src.digit[ix]) * _WORD(src.digit[iy])
/* Now calculate the double precision result. Nóte we use
* addition instead of *2 since it's easier to optimize
*/
- r = _WORD(t.digit[ix+iy]) + r + r + _WORD(carry);
+ r = _WORD(t.digit[ix+iy]) + r + r + _WORD(carry)
/*
Store lower part.
*/
- t.digit[ix+iy] = DIGIT(r & _WORD(_MASK));
+ t.digit[ix+iy] = DIGIT(r & _WORD(_MASK))
/*
Get carry.
*/
- carry = DIGIT(r >> _DIGIT_BITS);
+ carry = DIGIT(r >> _DIGIT_BITS)
}
/*
Propagate upwards.
*/
#no_bounds_check for carry != 0 {
- r = _WORD(t.digit[ix+iy]) + _WORD(carry);
- t.digit[ix+iy] = DIGIT(r & _WORD(_MASK));
- carry = DIGIT(r >> _WORD(_DIGIT_BITS));
- iy += 1;
+ r = _WORD(t.digit[ix+iy]) + _WORD(carry)
+ t.digit[ix+iy] = DIGIT(r & _WORD(_MASK))
+ carry = DIGIT(r >> _WORD(_DIGIT_BITS))
+ iy += 1
}
}
- err = internal_clamp(t);
- internal_swap(dest, t);
- internal_destroy(t);
- return err;
+ err = internal_clamp(t)
+ internal_swap(dest, t)
+ internal_destroy(t)
+ return err
}
/*
@@ -693,94 +693,94 @@ _private_int_sqr :: proc(dest, src: ^Int, allocator := context.allocator) -> (er Assumes `dest` and `src` not to be `nil` and `src` to have been initialized.
*/
_private_int_sqr_comba :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
- W: [_WARRAY]DIGIT = ---;
+ W: [_WARRAY]DIGIT = ---
/*
Grow the destination as required.
*/
- pa := uint(src.used) + uint(src.used);
- internal_grow(dest, int(pa)) or_return;
+ pa := uint(src.used) + uint(src.used)
+ internal_grow(dest, int(pa)) or_return
/*
Number of output digits to produce.
*/
- W1 := _WORD(0);
- _W : _WORD = ---;
- ix := uint(0);
+ W1 := _WORD(0)
+ _W : _WORD = ---
+ ix := uint(0)
#no_bounds_check for ; ix < pa; ix += 1 {
/*
Clear counter.
*/
- _W = {};
+ _W = {}
/*
Get offsets into the two bignums.
*/
- ty := min(uint(src.used) - 1, ix);
- tx := ix - ty;
+ ty := min(uint(src.used) - 1, ix)
+ tx := ix - ty
/*
This is the number of times the loop will iterate,
essentially while (tx++ < a->used && ty-- >= 0) { ... }
*/
- iy := min(uint(src.used) - tx, ty + 1);
+ iy := min(uint(src.used) - tx, ty + 1)
/*
Now for squaring, tx can never equal ty.
We halve the distance since they approach at a rate of 2x,
and we have to round because odd cases need to be executed.
*/
- iy = min(iy, ((ty - tx) + 1) >> 1 );
+ iy = min(iy, ((ty - tx) + 1) >> 1 )
/*
Execute loop.
*/
#no_bounds_check for iz := uint(0); iz < iy; iz += 1 {
- _W += _WORD(src.digit[tx + iz]) * _WORD(src.digit[ty - iz]);
+ _W += _WORD(src.digit[tx + iz]) * _WORD(src.digit[ty - iz])
}
/*
Double the inner product and add carry.
*/
- _W = _W + _W + W1;
+ _W = _W + _W + W1
/*
Even columns have the square term in them.
*/
if ix & 1 == 0 {
- _W += _WORD(src.digit[ix >> 1]) * _WORD(src.digit[ix >> 1]);
+ _W += _WORD(src.digit[ix >> 1]) * _WORD(src.digit[ix >> 1])
}
/*
Store it.
*/
- W[ix] = DIGIT(_W & _WORD(_MASK));
+ W[ix] = DIGIT(_W & _WORD(_MASK))
/*
Make next carry.
*/
- W1 = _W >> _DIGIT_BITS;
+ W1 = _W >> _DIGIT_BITS
}
/*
Setup dest.
*/
- old_used := dest.used;
- dest.used = src.used + src.used;
+ old_used := dest.used
+ dest.used = src.used + src.used
#no_bounds_check for ix = 0; ix < pa; ix += 1 {
- dest.digit[ix] = W[ix] & _MASK;
+ dest.digit[ix] = W[ix] & _MASK
}
/*
Clear unused digits [that existed in the old copy of dest].
*/
- internal_zero_unused(dest, old_used);
+ internal_zero_unused(dest, old_used)
- return internal_clamp(dest);
+ return internal_clamp(dest)
}
/*
@@ -790,31 +790,31 @@ _private_int_sqr_comba :: proc(dest, src: ^Int, allocator := context.allocator) It is essentially the same algorithm but merely tuned to perform recursive squarings.
*/
_private_int_sqr_karatsuba :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
- x0, x1, t1, t2, x0x0, x1x1 := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
- defer internal_destroy(x0, x1, t1, t2, x0x0, x1x1);
+ x0, x1, t1, t2, x0x0, x1x1 := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}
+ defer internal_destroy(x0, x1, t1, t2, x0x0, x1x1)
/*
Min # of digits, divided by two.
*/
- B := src.used >> 1;
+ B := src.used >> 1
/*
Init temps.
*/
- internal_grow(x0, B) or_return;
- internal_grow(x1, src.used - B) or_return;
- internal_grow(t1, src.used * 2) or_return;
- internal_grow(t2, src.used * 2) or_return;
- internal_grow(x0x0, B * 2 ) or_return;
- internal_grow(x1x1, (src.used - B) * 2) or_return;
+ internal_grow(x0, B) or_return
+ internal_grow(x1, src.used - B) or_return
+ internal_grow(t1, src.used * 2) or_return
+ internal_grow(t2, src.used * 2) or_return
+ internal_grow(x0x0, B * 2 ) or_return
+ internal_grow(x1x1, (src.used - B) * 2) or_return
/*
Now shift the digits.
*/
- x0.used = B;
- x1.used = src.used - B;
+ x0.used = B
+ x1.used = src.used - B
#force_inline internal_copy_digits(x0, src, x0.used);
#force_inline mem.copy_non_overlapping(&x1.digit[0], &src.digit[B], size_of(DIGIT) * x1.used);
@@ -823,30 +823,30 @@ _private_int_sqr_karatsuba :: proc(dest, src: ^Int, allocator := context.allocat /*
Now calc the products x0*x0 and x1*x1.
*/
- internal_sqr(x0x0, x0) or_return;
- internal_sqr(x1x1, x1) or_return;
+ internal_sqr(x0x0, x0) or_return
+ internal_sqr(x1x1, x1) or_return
/*
Now calc (x1+x0)^2
*/
- internal_add(t1, x0, x1) or_return;
- internal_sqr(t1, t1) or_return;
+ internal_add(t1, x0, x1) or_return
+ internal_sqr(t1, t1) or_return
/*
Add x0y0
*/
- internal_add(t2, x0x0, x1x1) or_return;
- internal_sub(t1, t1, t2) or_return;
+ internal_add(t2, x0x0, x1x1) or_return
+ internal_sub(t1, t1, t2) or_return
/*
Shift by B.
*/
- internal_shl_digit(t1, B) or_return;
- internal_shl_digit(x1x1, B * 2) or_return;
- internal_add(t1, t1, x0x0) or_return;
- internal_add(dest, t1, x1x1) or_return;
+ internal_shl_digit(t1, B) or_return
+ internal_shl_digit(x1x1, B * 2) or_return
+ internal_add(t1, t1, x0x0) or_return
+ internal_add(dest, t1, x1x1) or_return
- return #force_inline internal_clamp(dest);
+ return #force_inline internal_clamp(dest)
}
/*
@@ -856,160 +856,160 @@ _private_int_sqr_karatsuba :: proc(dest, src: ^Int, allocator := context.allocat 18th IEEE Symposium on Computer Arithmetic (ARITH'07). IEEE, 2007.
*/
_private_int_sqr_toom :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
- S0, a0, a1, a2 := &Int{}, &Int{}, &Int{}, &Int{};
- defer internal_destroy(S0, a0, a1, a2);
+ S0, a0, a1, a2 := &Int{}, &Int{}, &Int{}, &Int{}
+ defer internal_destroy(S0, a0, a1, a2)
/*
Init temps.
*/
- internal_zero(S0) or_return;
+ internal_zero(S0) or_return
/*
B
*/
- B := src.used / 3;
+ B := src.used / 3
/*
a = a2 * x^2 + a1 * x + a0;
*/
- internal_grow(a0, B) or_return;
- internal_grow(a1, B) or_return;
- internal_grow(a2, src.used - (2 * B)) or_return;
+ internal_grow(a0, B) or_return
+ internal_grow(a1, B) or_return
+ internal_grow(a2, src.used - (2 * B)) or_return
- a0.used = B;
- a1.used = B;
- a2.used = src.used - 2 * B;
+ a0.used = B
+ a1.used = B
+ a2.used = src.used - 2 * B
#force_inline mem.copy_non_overlapping(&a0.digit[0], &src.digit[ 0], size_of(DIGIT) * a0.used);
#force_inline mem.copy_non_overlapping(&a1.digit[0], &src.digit[ B], size_of(DIGIT) * a1.used);
#force_inline mem.copy_non_overlapping(&a2.digit[0], &src.digit[2 * B], size_of(DIGIT) * a2.used);
- internal_clamp(a0);
- internal_clamp(a1);
- internal_clamp(a2);
+ internal_clamp(a0)
+ internal_clamp(a1)
+ internal_clamp(a2)
/** S0 = a0^2; */
- internal_sqr(S0, a0) or_return;
+ internal_sqr(S0, a0) or_return
/** \\S1 = (a2 + a1 + a0)^2 */
/** \\S2 = (a2 - a1 + a0)^2 */
/** \\S1 = a0 + a2; */
/** a0 = a0 + a2; */
- internal_add(a0, a0, a2) or_return;
+ internal_add(a0, a0, a2) or_return
/** \\S2 = S1 - a1; */
/** b = a0 - a1; */
- internal_sub(dest, a0, a1) or_return;
+ internal_sub(dest, a0, a1) or_return
/** \\S1 = S1 + a1; */
/** a0 = a0 + a1; */
- internal_add(a0, a0, a1) or_return;
+ internal_add(a0, a0, a1) or_return
/** \\S1 = S1^2; */
/** a0 = a0^2; */
- internal_sqr(a0, a0) or_return;
+ internal_sqr(a0, a0) or_return
/** \\S2 = S2^2; */
/** b = b^2; */
- internal_sqr(dest, dest) or_return;
+ internal_sqr(dest, dest) or_return
/** \\ S3 = 2 * a1 * a2 */
/** \\S3 = a1 * a2; */
/** a1 = a1 * a2; */
- internal_mul(a1, a1, a2) or_return;
+ internal_mul(a1, a1, a2) or_return
/** \\S3 = S3 << 1; */
/** a1 = a1 << 1; */
- internal_shl(a1, a1, 1) or_return;
+ internal_shl(a1, a1, 1) or_return
/** \\S4 = a2^2; */
/** a2 = a2^2; */
- internal_sqr(a2, a2) or_return;
+ internal_sqr(a2, a2) or_return
/** \\ tmp = (S1 + S2)/2 */
/** \\tmp = S1 + S2; */
/** b = a0 + b; */
- internal_add(dest, a0, dest) or_return;
+ internal_add(dest, a0, dest) or_return
/** \\tmp = tmp >> 1; */
/** b = b >> 1; */
- internal_shr(dest, dest, 1) or_return;
+ internal_shr(dest, dest, 1) or_return
/** \\ S1 = S1 - tmp - S3 */
/** \\S1 = S1 - tmp; */
/** a0 = a0 - b; */
- internal_sub(a0, a0, dest) or_return;
+ internal_sub(a0, a0, dest) or_return
/** \\S1 = S1 - S3; */
/** a0 = a0 - a1; */
- internal_sub(a0, a0, a1) or_return;
+ internal_sub(a0, a0, a1) or_return
/** \\S2 = tmp - S4 -S0 */
/** \\S2 = tmp - S4; */
/** b = b - a2; */
- internal_sub(dest, dest, a2) or_return;
+ internal_sub(dest, dest, a2) or_return
/** \\S2 = S2 - S0; */
/** b = b - S0; */
- internal_sub(dest, dest, S0) or_return;
+ internal_sub(dest, dest, S0) or_return
/** \\P = S4*x^4 + S3*x^3 + S2*x^2 + S1*x + S0; */
/** P = a2*x^4 + a1*x^3 + b*x^2 + a0*x + S0; */
- internal_shl_digit( a2, 4 * B) or_return;
- internal_shl_digit( a1, 3 * B) or_return;
- internal_shl_digit(dest, 2 * B) or_return;
- internal_shl_digit( a0, 1 * B) or_return;
-
- internal_add(a2, a2, a1) or_return;
- internal_add(dest, dest, a2) or_return;
- internal_add(dest, dest, a0) or_return;
- internal_add(dest, dest, S0) or_return;
+ internal_shl_digit( a2, 4 * B) or_return
+ internal_shl_digit( a1, 3 * B) or_return
+ internal_shl_digit(dest, 2 * B) or_return
+ internal_shl_digit( a0, 1 * B) or_return
+
+ internal_add(a2, a2, a1) or_return
+ internal_add(dest, dest, a2) or_return
+ internal_add(dest, dest, a0) or_return
+ internal_add(dest, dest, S0) or_return
/** a^2 - P */
- return #force_inline internal_clamp(dest);
+ return #force_inline internal_clamp(dest)
}
/*
Divide by three (based on routine from MPI and the GMP manual).
*/
_private_int_div_3 :: proc(quotient, numerator: ^Int, allocator := context.allocator) -> (remainder: DIGIT, err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
/*
b = 2^_DIGIT_BITS / 3
*/
- b := _WORD(1) << _WORD(_DIGIT_BITS) / _WORD(3);
+ b := _WORD(1) << _WORD(_DIGIT_BITS) / _WORD(3)
- q := &Int{};
- internal_grow(q, numerator.used) or_return;
- q.used = numerator.used;
- q.sign = numerator.sign;
+ q := &Int{}
+ internal_grow(q, numerator.used) or_return
+ q.used = numerator.used
+ q.sign = numerator.sign
- w, t: _WORD;
+ w, t: _WORD
#no_bounds_check for ix := numerator.used; ix >= 0; ix -= 1 {
- w = (w << _WORD(_DIGIT_BITS)) | _WORD(numerator.digit[ix]);
+ w = (w << _WORD(_DIGIT_BITS)) | _WORD(numerator.digit[ix])
if w >= 3 {
/*
Multiply w by [1/3].
*/
- t = (w * b) >> _WORD(_DIGIT_BITS);
+ t = (w * b) >> _WORD(_DIGIT_BITS)
/*
Now subtract 3 * [w/3] from w, to get the remainder.
*/
- w -= t+t+t;
+ w -= t+t+t
/*
Fixup the remainder as required since the optimization is not exact.
*/
for w >= 3 {
- t += 1;
- w -= 3;
+ t += 1
+ w -= 3
}
} else {
- t = 0;
+ t = 0
}
- q.digit[ix] = DIGIT(t);
+ q.digit[ix] = DIGIT(t)
}
- remainder = DIGIT(w);
+ remainder = DIGIT(w)
/*
[optional] store the quotient.
*/
if quotient != nil {
- err = clamp(q);
- internal_swap(q, quotient);
+ err = clamp(q)
+ internal_swap(q, quotient)
}
- internal_destroy(q);
- return remainder, nil;
+ internal_destroy(q)
+ return remainder, nil
}
/*
@@ -1025,64 +1025,64 @@ _private_int_div_3 :: proc(quotient, numerator: ^Int, allocator := context.alloc The overall algorithm is as described as 14.20 from HAC but fixed to treat these cases.
*/
_private_int_div_school :: proc(quotient, remainder, numerator, denominator: ^Int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
- error_if_immutable(quotient, remainder) or_return;
+ error_if_immutable(quotient, remainder) or_return
- q, x, y, t1, t2 := &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
- defer internal_destroy(q, x, y, t1, t2);
+ q, x, y, t1, t2 := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}
+ defer internal_destroy(q, x, y, t1, t2)
- internal_grow(q, numerator.used + 2) or_return;
- q.used = numerator.used + 2;
+ internal_grow(q, numerator.used + 2) or_return
+ q.used = numerator.used + 2
- internal_init_multi(t1, t2) or_return;
- internal_copy(x, numerator) or_return;
- internal_copy(y, denominator) or_return;
+ internal_init_multi(t1, t2) or_return
+ internal_copy(x, numerator) or_return
+ internal_copy(y, denominator) or_return
/*
Fix the sign.
*/
- neg := numerator.sign != denominator.sign;
- x.sign = .Zero_or_Positive;
- y.sign = .Zero_or_Positive;
+ neg := numerator.sign != denominator.sign
+ x.sign = .Zero_or_Positive
+ y.sign = .Zero_or_Positive
/*
Normalize both x and y, ensure that y >= b/2, [b == 2**MP_DIGIT_BIT]
*/
- norm := internal_count_bits(y) % _DIGIT_BITS;
+ norm := internal_count_bits(y) % _DIGIT_BITS
if norm < _DIGIT_BITS - 1 {
- norm = (_DIGIT_BITS - 1) - norm;
- internal_shl(x, x, norm) or_return;
- internal_shl(y, y, norm) or_return;
+ norm = (_DIGIT_BITS - 1) - norm
+ internal_shl(x, x, norm) or_return
+ internal_shl(y, y, norm) or_return
} else {
- norm = 0;
+ norm = 0
}
/*
Note: HAC does 0 based, so if used==5 then it's 0,1,2,3,4, i.e. use 4
*/
- n := x.used - 1;
- t := y.used - 1;
+ n := x.used - 1
+ t := y.used - 1
/*
while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} }
y = y*b**{n-t}
*/
- internal_shl_digit(y, n - t) or_return;
+ internal_shl_digit(y, n - t) or_return
- c := internal_cmp(x, y);
+ c := internal_cmp(x, y)
for c != -1 {
- q.digit[n - t] += 1;
- internal_sub(x, x, y) or_return;
- c = internal_cmp(x, y);
+ q.digit[n - t] += 1
+ internal_sub(x, x, y) or_return
+ c = internal_cmp(x, y)
}
/*
Reset y by shifting it back down.
*/
- internal_shr_digit(y, n - t);
+ internal_shr_digit(y, n - t)
/*
Step 3. for i from n down to (t + 1).
@@ -1094,16 +1094,16 @@ _private_int_div_school :: proc(quotient, remainder, numerator, denominator: ^In step 3.1 if xi == yt then set q{i-t-1} to b-1, otherwise set q{i-t-1} to (xi*b + x{i-1})/yt
*/
if x.digit[i] == y.digit[t] {
- q.digit[(i - t) - 1] = 1 << (_DIGIT_BITS - 1);
+ q.digit[(i - t) - 1] = 1 << (_DIGIT_BITS - 1)
} else {
- tmp := _WORD(x.digit[i]) << _DIGIT_BITS;
- tmp |= _WORD(x.digit[i - 1]);
- tmp /= _WORD(y.digit[t]);
+ tmp := _WORD(x.digit[i]) << _DIGIT_BITS
+ tmp |= _WORD(x.digit[i - 1])
+ tmp /= _WORD(y.digit[t])
if tmp > _WORD(_MASK) {
- tmp = _WORD(_MASK);
+ tmp = _WORD(_MASK)
}
- q.digit[(i - t) - 1] = DIGIT(tmp & _WORD(_MASK));
+ q.digit[(i - t) - 1] = DIGIT(tmp & _WORD(_MASK))
}
/* while (q{i-t-1} * (yt * b + y{t-1})) >
@@ -1112,53 +1112,53 @@ _private_int_div_school :: proc(quotient, remainder, numerator, denominator: ^In do q{i-t-1} -= 1;
*/
- iter := 0;
+ iter := 0
- q.digit[(i - t) - 1] = (q.digit[(i - t) - 1] + 1) & _MASK;
+ q.digit[(i - t) - 1] = (q.digit[(i - t) - 1] + 1) & _MASK
#no_bounds_check for {
- q.digit[(i - t) - 1] = (q.digit[(i - t) - 1] - 1) & _MASK;
+ q.digit[(i - t) - 1] = (q.digit[(i - t) - 1] - 1) & _MASK
/*
Find left hand.
*/
- internal_zero(t1);
- t1.digit[0] = ((t - 1) < 0) ? 0 : y.digit[t - 1];
- t1.digit[1] = y.digit[t];
- t1.used = 2;
- internal_mul(t1, t1, q.digit[(i - t) - 1]) or_return;
+ internal_zero(t1)
+ t1.digit[0] = ((t - 1) < 0) ? 0 : y.digit[t - 1]
+ t1.digit[1] = y.digit[t]
+ t1.used = 2
+ internal_mul(t1, t1, q.digit[(i - t) - 1]) or_return
/*
Find right hand.
*/
- t2.digit[0] = ((i - 2) < 0) ? 0 : x.digit[i - 2];
- t2.digit[1] = x.digit[i - 1]; /* i >= 1 always holds */
- t2.digit[2] = x.digit[i];
- t2.used = 3;
+ t2.digit[0] = ((i - 2) < 0) ? 0 : x.digit[i - 2]
+ t2.digit[1] = x.digit[i - 1] /* i >= 1 always holds */
+ t2.digit[2] = x.digit[i]
+ t2.used = 3
if t1_t2 := internal_cmp_mag(t1, t2); t1_t2 != 1 {
- break;
+ break
}
iter += 1; if iter > 100 {
- return .Max_Iterations_Reached;
+ return .Max_Iterations_Reached
}
}
/*
Step 3.3 x = x - q{i-t-1} * y * b**{i-t-1}
*/
- int_mul_digit(t1, y, q.digit[(i - t) - 1]) or_return;
- internal_shl_digit(t1, (i - t) - 1) or_return;
- internal_sub(x, x, t1) or_return;
+ int_mul_digit(t1, y, q.digit[(i - t) - 1]) or_return
+ internal_shl_digit(t1, (i - t) - 1) or_return
+ internal_sub(x, x, t1) or_return
/*
if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; }
*/
if x.sign == .Negative {
- internal_copy(t1, y) or_return;
- internal_shl_digit(t1, (i - t) - 1) or_return;
- internal_add(x, x, t1) or_return;
+ internal_copy(t1, y) or_return
+ internal_shl_digit(t1, (i - t) - 1) or_return
+ internal_add(x, x, t1) or_return
- q.digit[(i - t) - 1] = (q.digit[(i - t) - 1] - 1) & _MASK;
+ q.digit[(i - t) - 1] = (q.digit[(i - t) - 1] - 1) & _MASK
}
}
@@ -1166,21 +1166,21 @@ _private_int_div_school :: proc(quotient, remainder, numerator, denominator: ^In Now q is the quotient and x is the remainder, [which we have to normalize]
Get sign before writing to c.
*/
- z, _ := is_zero(x);
- x.sign = .Zero_or_Positive if z else numerator.sign;
+ z, _ := is_zero(x)
+ x.sign = .Zero_or_Positive if z else numerator.sign
if quotient != nil {
- internal_clamp(q);
- internal_swap(q, quotient);
- quotient.sign = .Negative if neg else .Zero_or_Positive;
+ internal_clamp(q)
+ internal_swap(q, quotient)
+ quotient.sign = .Negative if neg else .Zero_or_Positive
}
if remainder != nil {
- internal_shr(x, x, norm) or_return;
- internal_swap(x, remainder);
+ internal_shr(x, x, norm) or_return
+ internal_swap(x, remainder)
}
- return nil;
+ return nil
}
/*
@@ -1193,49 +1193,49 @@ _private_int_div_school :: proc(quotient, remainder, numerator, denominator: ^In pages 19ff. in the above online document.
*/
_private_div_recursion :: proc(quotient, remainder, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
- A1, A2, B1, B0, Q1, Q0, R1, R0, t := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
- defer internal_destroy(A1, A2, B1, B0, Q1, Q0, R1, R0, t);
+ A1, A2, B1, B0, Q1, Q0, R1, R0, t := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}
+ defer internal_destroy(A1, A2, B1, B0, Q1, Q0, R1, R0, t)
- m := a.used - b.used;
- k := m / 2;
+ m := a.used - b.used
+ k := m / 2
if m < MUL_KARATSUBA_CUTOFF {
- return _private_int_div_school(quotient, remainder, a, b);
+ return _private_int_div_school(quotient, remainder, a, b)
}
- internal_init_multi(A1, A2, B1, B0, Q1, Q0, R1, R0, t) or_return;
+ internal_init_multi(A1, A2, B1, B0, Q1, Q0, R1, R0, t) or_return
/*
`B1` = `b` / `beta`^`k`, `B0` = `b` % `beta`^`k`
*/
- internal_shrmod(B1, B0, b, k * _DIGIT_BITS) or_return;
+ internal_shrmod(B1, B0, b, k * _DIGIT_BITS) or_return
/*
(Q1, R1) = RecursiveDivRem(A / beta^(2k), B1)
*/
- internal_shrmod(A1, t, a, 2 * k * _DIGIT_BITS) or_return;
- _private_div_recursion(Q1, R1, A1, B1) or_return;
+ internal_shrmod(A1, t, a, 2 * k * _DIGIT_BITS) or_return
+ _private_div_recursion(Q1, R1, A1, B1) or_return
/*
A1 = (R1 * beta^(2k)) + (A % beta^(2k)) - (Q1 * B0 * beta^k)
*/
- internal_shl_digit(R1, 2 * k) or_return;
- internal_add(A1, R1, t) or_return;
- internal_mul(t, Q1, B0) or_return;
+ internal_shl_digit(R1, 2 * k) or_return
+ internal_add(A1, R1, t) or_return
+ internal_mul(t, Q1, B0) or_return
/*
While A1 < 0 do Q1 = Q1 - 1, A1 = A1 + (beta^k * B)
*/
if internal_cmp(A1, 0) == -1 {
- internal_shl(t, b, k * _DIGIT_BITS) or_return;
+ internal_shl(t, b, k * _DIGIT_BITS) or_return
for {
- internal_decr(Q1) or_return;
- internal_add(A1, A1, t) or_return;
+ internal_decr(Q1) or_return
+ internal_add(A1, A1, t) or_return
if internal_cmp(A1, 0) != -1 {
- break;
+ break
}
}
}
@@ -1243,72 +1243,72 @@ _private_div_recursion :: proc(quotient, remainder, a, b: ^Int, allocator := con /*
(Q0, R0) = RecursiveDivRem(A1 / beta^(k), B1)
*/
- internal_shrmod(A1, t, A1, k * _DIGIT_BITS) or_return;
- _private_div_recursion(Q0, R0, A1, B1) or_return;
+ internal_shrmod(A1, t, A1, k * _DIGIT_BITS) or_return
+ _private_div_recursion(Q0, R0, A1, B1) or_return
/*
A2 = (R0*beta^k) + (A1 % beta^k) - (Q0*B0)
*/
- internal_shl_digit(R0, k) or_return;
- internal_add(A2, R0, t) or_return;
- internal_mul(t, Q0, B0) or_return;
- internal_sub(A2, A2, t) or_return;
+ internal_shl_digit(R0, k) or_return
+ internal_add(A2, R0, t) or_return
+ internal_mul(t, Q0, B0) or_return
+ internal_sub(A2, A2, t) or_return
/*
While A2 < 0 do Q0 = Q0 - 1, A2 = A2 + B.
*/
for internal_cmp(A2, 0) == -1 {
- internal_decr(Q0) or_return;
- internal_add(A2, A2, b) or_return;
+ internal_decr(Q0) or_return
+ internal_add(A2, A2, b) or_return
}
/*
Return q = (Q1*beta^k) + Q0, r = A2.
*/
- internal_shl_digit(Q1, k) or_return;
- internal_add(quotient, Q1, Q0) or_return;
+ internal_shl_digit(Q1, k) or_return
+ internal_add(quotient, Q1, Q0) or_return
- return internal_copy(remainder, A2);
+ return internal_copy(remainder, A2)
}
_private_int_div_recursive :: proc(quotient, remainder, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
- A, B, Q, Q1, R, A_div, A_mod := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
- defer internal_destroy(A, B, Q, Q1, R, A_div, A_mod);
+ A, B, Q, Q1, R, A_div, A_mod := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}
+ defer internal_destroy(A, B, Q, Q1, R, A_div, A_mod)
- internal_init_multi(A, B, Q, Q1, R, A_div, A_mod) or_return;
+ internal_init_multi(A, B, Q, Q1, R, A_div, A_mod) or_return
/*
Most significant bit of a limb.
Assumes _DIGIT_MAX < (sizeof(DIGIT) * sizeof(u8)).
*/
- msb := (_DIGIT_MAX + DIGIT(1)) >> 1;
- sigma := 0;
- msb_b := b.digit[b.used - 1];
+ msb := (_DIGIT_MAX + DIGIT(1)) >> 1
+ sigma := 0
+ msb_b := b.digit[b.used - 1]
for msb_b < msb {
- sigma += 1;
- msb_b <<= 1;
+ sigma += 1
+ msb_b <<= 1
}
/*
Use that sigma to normalize B.
*/
- internal_shl(B, b, sigma) or_return;
- internal_shl(A, a, sigma) or_return;
+ internal_shl(B, b, sigma) or_return
+ internal_shl(A, a, sigma) or_return
/*
Fix the sign.
*/
- neg := a.sign != b.sign;
- A.sign = .Zero_or_Positive; B.sign = .Zero_or_Positive;
+ neg := a.sign != b.sign
+ A.sign = .Zero_or_Positive; B.sign = .Zero_or_Positive
/*
If the magnitude of "A" is not more more than twice that of "B" we can work
on them directly, otherwise we need to work at "A" in chunks.
*/
- n := B.used;
- m := A.used - B.used;
+ n := B.used
+ m := A.used - B.used
/*
Q = 0. We already ensured that when we called `internal_init_multi`.
@@ -1317,56 +1317,56 @@ _private_int_div_recursive :: proc(quotient, remainder, a, b: ^Int, allocator := /*
(q, r) = RecursiveDivRem(A / (beta^(m-n)), B)
*/
- j := (m - n) * _DIGIT_BITS;
- internal_shrmod(A_div, A_mod, A, j) or_return;
- _private_div_recursion(Q1, R, A_div, B) or_return;
+ j := (m - n) * _DIGIT_BITS
+ internal_shrmod(A_div, A_mod, A, j) or_return
+ _private_div_recursion(Q1, R, A_div, B) or_return
/*
Q = (Q*beta!(n)) + q
*/
- internal_shl(Q, Q, n * _DIGIT_BITS) or_return;
- internal_add(Q, Q, Q1) or_return;
+ internal_shl(Q, Q, n * _DIGIT_BITS) or_return
+ internal_add(Q, Q, Q1) or_return
/*
A = (r * beta^(m-n)) + (A % beta^(m-n))
*/
- internal_shl(R, R, (m - n) * _DIGIT_BITS) or_return;
- internal_add(A, R, A_mod) or_return;
+ internal_shl(R, R, (m - n) * _DIGIT_BITS) or_return
+ internal_add(A, R, A_mod) or_return
/*
m = m - n
*/
- m -= n;
+ m -= n
}
/*
(q, r) = RecursiveDivRem(A, B)
*/
- _private_div_recursion(Q1, R, A, B) or_return;
+ _private_div_recursion(Q1, R, A, B) or_return
/*
Q = (Q * beta^m) + q, R = r
*/
- internal_shl(Q, Q, m * _DIGIT_BITS) or_return;
- internal_add(Q, Q, Q1) or_return;
+ internal_shl(Q, Q, m * _DIGIT_BITS) or_return
+ internal_add(Q, Q, Q1) or_return
/*
Get sign before writing to dest.
*/
- R.sign = .Zero_or_Positive if internal_is_zero(Q) else a.sign;
+ R.sign = .Zero_or_Positive if internal_is_zero(Q) else a.sign
if quotient != nil {
- swap(quotient, Q);
- quotient.sign = .Negative if neg else .Zero_or_Positive;
+ swap(quotient, Q)
+ quotient.sign = .Negative if neg else .Zero_or_Positive
}
if remainder != nil {
/*
De-normalize the remainder.
*/
- internal_shrmod(R, nil, R, sigma) or_return;
- swap(remainder, R);
+ internal_shrmod(R, nil, R, sigma) or_return
+ swap(remainder, R)
}
- return nil;
+ return nil
}
/*
@@ -1375,53 +1375,53 @@ _private_int_div_recursive :: proc(quotient, remainder, a, b: ^Int, allocator := @(deprecated="Use `_int_div_school`, it's 3.5x faster.")
_private_int_div_small :: proc(quotient, remainder, numerator, denominator: ^Int) -> (err: Error) {
- ta, tb, tq, q := &Int{}, &Int{}, &Int{}, &Int{};
- c: int;
- defer internal_destroy(ta, tb, tq, q);
+ ta, tb, tq, q := &Int{}, &Int{}, &Int{}, &Int{}
+ c: int
+ defer internal_destroy(ta, tb, tq, q)
for {
- internal_one(tq) or_return;
+ internal_one(tq) or_return
- num_bits, _ := count_bits(numerator);
- den_bits, _ := count_bits(denominator);
- n := num_bits - den_bits;
+ num_bits, _ := count_bits(numerator)
+ den_bits, _ := count_bits(denominator)
+ n := num_bits - den_bits
- abs(ta, numerator) or_return;
- abs(tb, denominator) or_return;
- shl(tb, tb, n) or_return;
- shl(tq, tq, n) or_return;
+ abs(ta, numerator) or_return
+ abs(tb, denominator) or_return
+ shl(tb, tb, n) or_return
+ shl(tq, tq, n) or_return
for n >= 0 {
if c, _ = cmp_mag(ta, tb); c == 0 || c == 1 {
// ta -= tb
- sub(ta, ta, tb) or_return;
+ sub(ta, ta, tb) or_return
// q += tq
- add( q, q, tq) or_return;
+ add( q, q, tq) or_return
}
- shr1(tb, tb) or_return;
- shr1(tq, tq) or_return;
+ shr1(tb, tb) or_return
+ shr1(tq, tq) or_return
- n -= 1;
+ n -= 1
}
/*
Now q == quotient and ta == remainder.
*/
- neg := numerator.sign != denominator.sign;
+ neg := numerator.sign != denominator.sign
if quotient != nil {
- swap(quotient, q);
- z, _ := is_zero(quotient);
- quotient.sign = .Negative if neg && !z else .Zero_or_Positive;
+ swap(quotient, q)
+ z, _ := is_zero(quotient)
+ quotient.sign = .Negative if neg && !z else .Zero_or_Positive
}
if remainder != nil {
- swap(remainder, ta);
- z, _ := is_zero(numerator);
- remainder.sign = .Zero_or_Positive if z else numerator.sign;
+ swap(remainder, ta)
+ z, _ := is_zero(numerator)
+ remainder.sign = .Zero_or_Positive if z else numerator.sign
}
- break;
+ break
}
- return err;
+ return err
}
@@ -1430,65 +1430,65 @@ _private_int_div_small :: proc(quotient, remainder, numerator, denominator: ^Int Binary split factorial algo due to: http://www.luschny.de/math/factorial/binarysplitfact.html
*/
_private_int_factorial_binary_split :: proc(res: ^Int, n: int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
- inner, outer, start, stop, temp := &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
- defer internal_destroy(inner, outer, start, stop, temp);
+ inner, outer, start, stop, temp := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}
+ defer internal_destroy(inner, outer, start, stop, temp)
- internal_one(inner, false) or_return;
- internal_one(outer, false) or_return;
+ internal_one(inner, false) or_return
+ internal_one(outer, false) or_return
- bits_used := int(_DIGIT_TYPE_BITS - intrinsics.count_leading_zeros(n));
+ bits_used := int(_DIGIT_TYPE_BITS - intrinsics.count_leading_zeros(n))
for i := bits_used; i >= 0; i -= 1 {
- start := (n >> (uint(i) + 1)) + 1 | 1;
- stop := (n >> uint(i)) + 1 | 1;
- _private_int_recursive_product(temp, start, stop, 0) or_return;
- internal_mul(inner, inner, temp) or_return;
- internal_mul(outer, outer, inner) or_return;
+ start := (n >> (uint(i) + 1)) + 1 | 1
+ stop := (n >> uint(i)) + 1 | 1
+ _private_int_recursive_product(temp, start, stop, 0) or_return
+ internal_mul(inner, inner, temp) or_return
+ internal_mul(outer, outer, inner) or_return
}
- shift := n - intrinsics.count_ones(n);
+ shift := n - intrinsics.count_ones(n)
- return internal_shl(res, outer, int(shift));
+ return internal_shl(res, outer, int(shift))
}
/*
Recursive product used by binary split factorial algorithm.
*/
_private_int_recursive_product :: proc(res: ^Int, start, stop: int, level := int(0), allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
- t1, t2 := &Int{}, &Int{};
- defer internal_destroy(t1, t2);
+ t1, t2 := &Int{}, &Int{}
+ defer internal_destroy(t1, t2)
if level > FACTORIAL_BINARY_SPLIT_MAX_RECURSIONS {
- return .Max_Iterations_Reached;
+ return .Max_Iterations_Reached
}
- num_factors := (stop - start) >> 1;
+ num_factors := (stop - start) >> 1
if num_factors == 2 {
- internal_set(t1, start, false) or_return;
+ internal_set(t1, start, false) or_return
when true {
- internal_grow(t2, t1.used + 1, false) or_return;
- internal_add(t2, t1, 2) or_return;
+ internal_grow(t2, t1.used + 1, false) or_return
+ internal_add(t2, t1, 2) or_return
} else {
- internal_add(t2, t1, 2) or_return;
+ internal_add(t2, t1, 2) or_return
}
- return internal_mul(res, t1, t2);
+ return internal_mul(res, t1, t2)
}
if num_factors > 1 {
- mid := (start + num_factors) | 1;
- _private_int_recursive_product(t1, start, mid, level + 1) or_return;
- _private_int_recursive_product(t2, mid, stop, level + 1) or_return;
- return internal_mul(res, t1, t2);
+ mid := (start + num_factors) | 1
+ _private_int_recursive_product(t1, start, mid, level + 1) or_return
+ _private_int_recursive_product(t2, mid, stop, level + 1) or_return
+ return internal_mul(res, t1, t2)
}
if num_factors == 1 {
- return #force_inline internal_set(res, start, true);
+ return #force_inline internal_set(res, start, true)
}
- return #force_inline internal_one(res, true);
+ return #force_inline internal_one(res, true)
}
/*
@@ -1507,10 +1507,10 @@ _private_int_recursive_product :: proc(res: ^Int, start, stop: int, level := int If neither result is wanted, we have nothing to do.
*/
_private_int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
if res_gcd == nil && res_lcm == nil {
- return nil;
+ return nil
}
/*
@@ -1521,76 +1521,76 @@ _private_int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int, allocator := context. GCD(0, 0) and LCM(0, 0) are both 0.
*/
if res_gcd != nil {
- internal_zero(res_gcd) or_return;
+ internal_zero(res_gcd) or_return
}
if res_lcm != nil {
- internal_zero(res_lcm) or_return;
+ internal_zero(res_lcm) or_return
}
- return nil;
+ return nil
} else if a.used == 0 {
/*
We can early out with GCD = B and LCM = 0
*/
if res_gcd != nil {
- internal_abs(res_gcd, b) or_return;
+ internal_abs(res_gcd, b) or_return
}
if res_lcm != nil {
- internal_zero(res_lcm) or_return;
+ internal_zero(res_lcm) or_return
}
- return nil;
+ return nil
} else if b.used == 0 {
/*
We can early out with GCD = A and LCM = 0
*/
if res_gcd != nil {
- internal_abs(res_gcd, a) or_return;
+ internal_abs(res_gcd, a) or_return
}
if res_lcm != nil {
- internal_zero(res_lcm) or_return;
+ internal_zero(res_lcm) or_return
}
- return nil;
+ return nil
}
- temp_gcd_res := &Int{};
- defer internal_destroy(temp_gcd_res);
+ temp_gcd_res := &Int{}
+ defer internal_destroy(temp_gcd_res)
/*
If neither `a` or `b` was zero, we need to compute `gcd`.
Get copies of `a` and `b` we can modify.
*/
- u, v := &Int{}, &Int{};
- defer internal_destroy(u, v);
- internal_copy(u, a) or_return;
- internal_copy(v, b) or_return;
+ u, v := &Int{}, &Int{}
+ defer internal_destroy(u, v)
+ internal_copy(u, a) or_return
+ internal_copy(v, b) or_return
/*
Must be positive for the remainder of the algorithm.
*/
- u.sign = .Zero_or_Positive; v.sign = .Zero_or_Positive;
+ u.sign = .Zero_or_Positive; v.sign = .Zero_or_Positive
/*
B1. Find the common power of two for `u` and `v`.
*/
- u_lsb, _ := internal_count_lsb(u);
- v_lsb, _ := internal_count_lsb(v);
- k := min(u_lsb, v_lsb);
+ u_lsb, _ := internal_count_lsb(u)
+ v_lsb, _ := internal_count_lsb(v)
+ k := min(u_lsb, v_lsb)
if k > 0 {
/*
Divide the power of two out.
*/
- internal_shr(u, u, k) or_return;
- internal_shr(v, v, k) or_return;
+ internal_shr(u, u, k) or_return
+ internal_shr(v, v, k) or_return
}
/*
Divide any remaining factors of two out.
*/
if u_lsb != k {
- internal_shr(u, u, u_lsb - k) or_return;
+ internal_shr(u, u, u_lsb - k) or_return
}
if v_lsb != k {
- internal_shr(v, v, v_lsb - k) or_return;
+ internal_shr(v, v, v_lsb - k) or_return
}
for v.used != 0 {
@@ -1601,34 +1601,34 @@ _private_int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int, allocator := context. /*
Swap `u` and `v` to make sure `v` is >= `u`.
*/
- internal_swap(u, v);
+ internal_swap(u, v)
}
/*
Subtract smallest from largest.
*/
- internal_sub(v, v, u) or_return;
+ internal_sub(v, v, u) or_return
/*
Divide out all factors of two.
*/
- b, _ := internal_count_lsb(v);
- internal_shr(v, v, b) or_return;
+ b, _ := internal_count_lsb(v)
+ internal_shr(v, v, b) or_return
}
/*
Multiply by 2**k which we divided out at the beginning.
*/
- internal_shl(temp_gcd_res, u, k) or_return;
- temp_gcd_res.sign = .Zero_or_Positive;
+ internal_shl(temp_gcd_res, u, k) or_return
+ temp_gcd_res.sign = .Zero_or_Positive
/*
We've computed `gcd`, either the long way, or because one of the inputs was zero.
If we don't want `lcm`, we're done.
*/
if res_lcm == nil {
- internal_swap(temp_gcd_res, res_gcd);
- return nil;
+ internal_swap(temp_gcd_res, res_gcd)
+ return nil
}
/*
@@ -1639,25 +1639,25 @@ _private_int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int, allocator := context. /*
Store quotient in `t2` such that `t2 * b` is the LCM.
*/
- internal_div(res_lcm, a, temp_gcd_res) or_return;
- err = internal_mul(res_lcm, res_lcm, b);
+ internal_div(res_lcm, a, temp_gcd_res) or_return
+ err = internal_mul(res_lcm, res_lcm, b)
} else {
/*
Store quotient in `t2` such that `t2 * a` is the LCM.
*/
- internal_div(res_lcm, a, temp_gcd_res) or_return;
- err = internal_mul(res_lcm, res_lcm, b);
+ internal_div(res_lcm, a, temp_gcd_res) or_return
+ err = internal_mul(res_lcm, res_lcm, b)
}
if res_gcd != nil {
- internal_swap(temp_gcd_res, res_gcd);
+ internal_swap(temp_gcd_res, res_gcd)
}
/*
Fix the sign to positive and return.
*/
- res_lcm.sign = .Zero_or_Positive;
- return err;
+ res_lcm.sign = .Zero_or_Positive
+ return err
}
/*
@@ -1665,24 +1665,24 @@ _private_int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int, allocator := context. Assumes `a` not to be `nil` and to have been initialized.
*/
_private_int_log :: proc(a: ^Int, base: DIGIT, allocator := context.allocator) -> (res: int, err: Error) {
- bracket_low, bracket_high, bracket_mid, t, bi_base := &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
- defer internal_destroy(bracket_low, bracket_high, bracket_mid, t, bi_base);
+ bracket_low, bracket_high, bracket_mid, t, bi_base := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}
+ defer internal_destroy(bracket_low, bracket_high, bracket_mid, t, bi_base)
- ic := #force_inline internal_cmp(a, base);
+ ic := #force_inline internal_cmp(a, base)
if ic == -1 || ic == 0 {
- return 1 if ic == 0 else 0, nil;
+ return 1 if ic == 0 else 0, nil
}
defer if err != nil {
- res = -1;
+ res = -1
}
- internal_set(bi_base, base, true, allocator) or_return;
- internal_clear(bracket_mid, false, allocator) or_return;
- internal_clear(t, false, allocator) or_return;
- internal_one(bracket_low, false, allocator) or_return;
- internal_set(bracket_high, base, false, allocator) or_return;
+ internal_set(bi_base, base, true, allocator) or_return
+ internal_clear(bracket_mid, false, allocator) or_return
+ internal_clear(t, false, allocator) or_return
+ internal_one(bracket_low, false, allocator) or_return
+ internal_set(bracket_high, base, false, allocator) or_return
- low := 0; high := 1;
+ low := 0; high := 1
/*
A kind of Giant-step/baby-step algorithm.
@@ -1696,39 +1696,39 @@ _private_int_log :: proc(a: ^Int, base: DIGIT, allocator := context.allocator) - Iterate until `a` is bracketed between low + high.
*/
if #force_inline internal_cmp(bracket_high, a) != -1 {
- break;
+ break
}
- low = high;
+ low = high
#force_inline internal_copy(bracket_low, bracket_high) or_return;
- high <<= 1;
+ high <<= 1
#force_inline internal_sqr(bracket_high, bracket_high) or_return;
}
for (high - low) > 1 {
- mid := (high + low) >> 1;
+ mid := (high + low) >> 1
#force_inline internal_pow(t, bi_base, mid - low) or_return;
#force_inline internal_mul(bracket_mid, bracket_low, t) or_return;
- mc := #force_inline internal_cmp(a, bracket_mid);
+ mc := #force_inline internal_cmp(a, bracket_mid)
switch mc {
case -1:
- high = mid;
- internal_swap(bracket_mid, bracket_high);
+ high = mid
+ internal_swap(bracket_mid, bracket_high)
case 0:
- return mid, nil;
+ return mid, nil
case 1:
- low = mid;
- internal_swap(bracket_mid, bracket_low);
+ low = mid
+ internal_swap(bracket_mid, bracket_low)
}
}
- fc := #force_inline internal_cmp(bracket_high, a);
- res = high if fc == 0 else low;
+ fc := #force_inline internal_cmp(bracket_high, a)
+ res = high if fc == 0 else low
- return;
+ return
}
@@ -1741,37 +1741,37 @@ _private_int_log :: proc(a: ^Int, base: DIGIT, allocator := context.allocator) - Based on Algorithm 14.32 on pp.601 of HAC.
*/
_private_montgomery_reduce_comba :: proc(x, n: ^Int, rho: DIGIT, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
- W: [_WARRAY]_WORD = ---;
+ context.allocator = allocator
+ W: [_WARRAY]_WORD = ---
if x.used > _WARRAY { return .Invalid_Argument; }
/*
Get old used count.
*/
- old_used := x.used;
+ old_used := x.used
/*
Grow `x` as required.
*/
- internal_grow(x, n.used + 1) or_return;
+ internal_grow(x, n.used + 1) or_return
/*
First we have to get the digits of the input into an array of double precision words W[...]
Copy the digits of `x` into W[0..`x.used` - 1]
*/
- ix: int;
+ ix: int
for ix = 0; ix < x.used; ix += 1 {
- W[ix] = _WORD(x.digit[ix]);
+ W[ix] = _WORD(x.digit[ix])
}
/*
Zero the high words of W[a->used..m->used*2].
*/
- zero_upper := (n.used * 2) + 1;
+ zero_upper := (n.used * 2) + 1
if ix < zero_upper {
for ix = x.used; ix < zero_upper; ix += 1 {
- W[ix] = {};
+ W[ix] = {}
}
}
@@ -1786,7 +1786,7 @@ _private_montgomery_reduce_comba :: proc(x, n: ^Int, rho: DIGIT, allocator := co by casting the value down to a DIGIT. Note this requires
that W[ix-1] have the carry cleared (see after the inner loop)
*/
- mu := ((W[ix] & _WORD(_MASK)) * _WORD(rho)) & _WORD(_MASK);
+ mu := ((W[ix] & _WORD(_MASK)) * _WORD(rho)) & _WORD(_MASK)
/*
`a = a + mu * m * b**i`
@@ -1805,13 +1805,13 @@ _private_montgomery_reduce_comba :: proc(x, n: ^Int, rho: DIGIT, allocator := co first m->used words of W[] have the carries fixed.
*/
for iy := 0; iy < n.used; iy += 1 {
- W[ix + iy] += mu * _WORD(n.digit[iy]);
+ W[ix + iy] += mu * _WORD(n.digit[iy])
}
/*
Now fix carry for next digit, W[ix+1].
*/
- W[ix + 1] += (W[ix] >> _DIGIT_BITS);
+ W[ix + 1] += (W[ix] >> _DIGIT_BITS)
}
/*
@@ -1820,7 +1820,7 @@ _private_montgomery_reduce_comba :: proc(x, n: ^Int, rho: DIGIT, allocator := co */
for ; ix < n.used * 2; ix += 1 {
- W[ix + 1] += (W[ix] >> _DIGIT_BITS);
+ W[ix + 1] += (W[ix] >> _DIGIT_BITS)
}
/* copy out, A = A/b**n
@@ -1831,69 +1831,69 @@ _private_montgomery_reduce_comba :: proc(x, n: ^Int, rho: DIGIT, allocator := co */
for ix = 0; ix < (n.used + 1); ix += 1 {
- x.digit[ix] = DIGIT(W[n.used + ix] & _WORD(_MASK));
+ x.digit[ix] = DIGIT(W[n.used + ix] & _WORD(_MASK))
}
/*
Set the max used.
*/
- x.used = n.used + 1;
+ x.used = n.used + 1
/*
Zero old_used digits, if the input a was larger than m->used+1 we'll have to clear the digits.
*/
- internal_zero_unused(x, old_used);
- internal_clamp(x);
+ internal_zero_unused(x, old_used)
+ internal_clamp(x)
/*
if A >= m then A = A - m
*/
if internal_cmp_mag(x, n) != -1 {
- return internal_sub(x, x, n);
+ return internal_sub(x, x, n)
}
- return nil;
+ return nil
}
/*
hac 14.61, pp608
*/
_private_inverse_modulo :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
- x, y, u, v, A, B, C, D := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
- defer internal_destroy(x, y, u, v, A, B, C, D);
+ context.allocator = allocator
+ x, y, u, v, A, B, C, D := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}
+ defer internal_destroy(x, y, u, v, A, B, C, D)
/*
`b` cannot be negative.
*/
if b.sign == .Negative || internal_is_zero(b) {
- return .Invalid_Argument;
+ return .Invalid_Argument
}
/*
init temps.
*/
- internal_init_multi(x, y, u, v, A, B, C, D) or_return;
+ internal_init_multi(x, y, u, v, A, B, C, D) or_return
/*
`x` = `a` % `b`, `y` = `b`
*/
- internal_mod(x, a, b) or_return;
- internal_copy(y, b) or_return;
+ internal_mod(x, a, b) or_return
+ internal_copy(y, b) or_return
/*
2. [modified] if x,y are both even then return an error!
*/
if internal_is_even(x) && internal_is_even(y) {
- return .Invalid_Argument;
+ return .Invalid_Argument
}
/*
3. u=x, v=y, A=1, B=0, C=0, D=1
*/
- internal_copy(u, x) or_return;
- internal_copy(v, y) or_return;
- internal_one(A) or_return;
- internal_one(D) or_return;
+ internal_copy(u, x) or_return
+ internal_copy(v, y) or_return
+ internal_one(A) or_return
+ internal_one(D) or_return
for {
/*
@@ -1903,7 +1903,7 @@ _private_inverse_modulo :: proc(dest, a, b: ^Int, allocator := context.allocator /*
4.1 `u` = `u` / 2
*/
- internal_int_shr1(u, u) or_return;
+ internal_int_shr1(u, u) or_return
/*
4.2 if `A` or `B` is odd then:
@@ -1912,14 +1912,14 @@ _private_inverse_modulo :: proc(dest, a, b: ^Int, allocator := context.allocator /*
`A` = (`A`+`y`) / 2, `B` = (`B`-`x`) / 2
*/
- internal_add(A, A, y) or_return;
- internal_add(B, B, x) or_return;
+ internal_add(A, A, y) or_return
+ internal_add(B, B, x) or_return
}
/*
`A` = `A` / 2, `B` = `B` / 2
*/
- internal_int_shr1(A, A) or_return;
- internal_int_shr1(B, B) or_return;
+ internal_int_shr1(A, A) or_return
+ internal_int_shr1(B, B) or_return
}
/*
@@ -1929,7 +1929,7 @@ _private_inverse_modulo :: proc(dest, a, b: ^Int, allocator := context.allocator /*
5.1 `v` = `v` / 2
*/
- internal_int_shr1(v, v) or_return;
+ internal_int_shr1(v, v) or_return
/*
5.2 if `C` or `D` is odd then:
@@ -1938,14 +1938,14 @@ _private_inverse_modulo :: proc(dest, a, b: ^Int, allocator := context.allocator /*
`C` = (`C`+`y`) / 2, `D` = (`D`-`x`) / 2
*/
- internal_add(C, C, y) or_return;
- internal_add(D, D, x) or_return;
+ internal_add(C, C, y) or_return
+ internal_add(D, D, x) or_return
}
/*
`C` = `C` / 2, `D` = `D` / 2
*/
- internal_int_shr1(C, C) or_return;
- internal_int_shr1(D, D) or_return;
+ internal_int_shr1(C, C) or_return
+ internal_int_shr1(D, D) or_return
}
/*
@@ -1955,21 +1955,21 @@ _private_inverse_modulo :: proc(dest, a, b: ^Int, allocator := context.allocator /*
`u` = `u` - `v`, `A` = `A` - `C`, `B` = `B` - `D`
*/
- internal_sub(u, u, v) or_return;
- internal_sub(A, A, C) or_return;
- internal_sub(B, B, D) or_return;
+ internal_sub(u, u, v) or_return
+ internal_sub(A, A, C) or_return
+ internal_sub(B, B, D) or_return
} else {
/* v - v - u, C = C - A, D = D - B */
- internal_sub(v, v, u) or_return;
- internal_sub(C, C, A) or_return;
- internal_sub(D, D, B) or_return;
+ internal_sub(v, v, u) or_return
+ internal_sub(C, C, A) or_return
+ internal_sub(D, D, B) or_return
}
/*
If not zero goto step 4
*/
if internal_is_zero(u) {
- break;
+ break
}
}
@@ -1981,29 +1981,29 @@ _private_inverse_modulo :: proc(dest, a, b: ^Int, allocator := context.allocator If `v` != `1` then there is no inverse.
*/
if internal_cmp(v, 1) != 0 {
- return .Invalid_Argument;
+ return .Invalid_Argument
}
/*
If its too low.
*/
if internal_cmp(C, 0) == -1 {
- internal_add(C, C, b) or_return;
+ internal_add(C, C, b) or_return
}
/*
Too big.
*/
if internal_cmp(C, 0) != -1 {
- internal_sub(C, C, b) or_return;
+ internal_sub(C, C, b) or_return
}
/*
`C` is now the inverse.
*/
- swap(dest, C);
+ swap(dest, C)
- return;
+ return
}
/*
@@ -2013,11 +2013,11 @@ _private_inverse_modulo :: proc(dest, a, b: ^Int, allocator := context.allocator as per HAC Note 14.64 on pp. 610.
*/
_private_inverse_modulo_odd :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
- x, y, u, v, B, D := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
- defer internal_destroy(x, y, u, v, B, D);
+ context.allocator = allocator
+ x, y, u, v, B, D := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}
+ defer internal_destroy(x, y, u, v, B, D)
- sign: Sign;
+ sign: Sign
/*
2. [modified] `b` must be odd.
@@ -2027,17 +2027,17 @@ _private_inverse_modulo_odd :: proc(dest, a, b: ^Int, allocator := context.alloc /*
Init all our temps.
*/
- internal_init_multi(x, y, u, v, B, D) or_return;
+ internal_init_multi(x, y, u, v, B, D) or_return
/*
`x` == modulus, `y` == value to invert.
*/
- internal_copy(x, b) or_return;
+ internal_copy(x, b) or_return
/*
We need `y` = `|a|`.
*/
- internal_mod(y, a, b) or_return;
+ internal_mod(y, a, b) or_return
/*
If one of `x`, `y` is zero return an error!
@@ -2047,10 +2047,10 @@ _private_inverse_modulo_odd :: proc(dest, a, b: ^Int, allocator := context.alloc /*
3. `u` = `x`, `v` = `y`, `A` = 1, `B` = 0, `C` = 0, `D` = 1
*/
- internal_copy(u, x) or_return;
- internal_copy(v, y) or_return;
+ internal_copy(u, x) or_return
+ internal_copy(v, y) or_return
- internal_one(D) or_return;
+ internal_one(D) or_return
for {
/*
@@ -2060,7 +2060,7 @@ _private_inverse_modulo_odd :: proc(dest, a, b: ^Int, allocator := context.alloc /*
4.1 `u` = `u` / 2
*/
- internal_int_shr1(u, u) or_return;
+ internal_int_shr1(u, u) or_return
/*
4.2 if `B` is odd then:
@@ -2069,13 +2069,13 @@ _private_inverse_modulo_odd :: proc(dest, a, b: ^Int, allocator := context.alloc /*
`B` = (`B` - `x`) / 2
*/
- internal_sub(B, B, x) or_return;
+ internal_sub(B, B, x) or_return
}
/*
`B` = `B` / 2
*/
- internal_int_shr1(B, B) or_return;
+ internal_int_shr1(B, B) or_return
}
/*
@@ -2085,7 +2085,7 @@ _private_inverse_modulo_odd :: proc(dest, a, b: ^Int, allocator := context.alloc /*
5.1 `v` = `v` / 2
*/
- internal_int_shr1(v, v) or_return;
+ internal_int_shr1(v, v) or_return
/*
5.2 if `D` is odd then:
@@ -2094,12 +2094,12 @@ _private_inverse_modulo_odd :: proc(dest, a, b: ^Int, allocator := context.alloc /*
`D` = (`D` - `x`) / 2
*/
- internal_sub(D, D, x) or_return;
+ internal_sub(D, D, x) or_return
}
/*
`D` = `D` / 2
*/
- internal_int_shr1(D, D) or_return;
+ internal_int_shr1(D, D) or_return
}
/*
@@ -2109,14 +2109,14 @@ _private_inverse_modulo_odd :: proc(dest, a, b: ^Int, allocator := context.alloc /*
`u` = `u` - `v`, `B` = `B` - `D`
*/
- internal_sub(u, u, v) or_return;
- internal_sub(B, B, D) or_return;
+ internal_sub(u, u, v) or_return
+ internal_sub(B, B, D) or_return
} else {
/*
`v` - `v` - `u`, `D` = `D` - `B`
*/
- internal_sub(v, v, u) or_return;
- internal_sub(D, D, B) or_return;
+ internal_sub(v, v, u) or_return
+ internal_sub(D, D, B) or_return
}
/*
@@ -2133,27 +2133,27 @@ _private_inverse_modulo_odd :: proc(dest, a, b: ^Int, allocator := context.alloc if `v` != 1 then there is no inverse
*/
if internal_cmp(v, 1) != 0 {
- return .Invalid_Argument;
+ return .Invalid_Argument
}
/*
`b` is now the inverse.
*/
- sign = a.sign;
+ sign = a.sign
for internal_int_is_negative(D) {
- internal_add(D, D, b) or_return;
+ internal_add(D, D, b) or_return
}
/*
Too big.
*/
for internal_cmp_mag(D, b) != -1 {
- internal_sub(D, D, b) or_return;
+ internal_sub(D, D, b) or_return
}
- swap(dest, D);
- dest.sign = sign;
- return nil;
+ swap(dest, D)
+ dest.sign = sign
+ return nil
}
@@ -2163,14 +2163,14 @@ _private_inverse_modulo_odd :: proc(dest, a, b: ^Int, allocator := context.alloc Also assumes `base` is a power of two.
*/
_private_log_power_of_two :: proc(a: ^Int, base: DIGIT) -> (log: int, err: Error) {
- base := base;
- y: int;
+ base := base
+ y: int
for y = 0; base & 1 == 0; {
- y += 1;
- base >>= 1;
+ y += 1
+ base >>= 1
}
- log = internal_count_bits(a);
- return (log - 1) / y, err;
+ log = internal_count_bits(a)
+ return (log - 1) / y, err
}
/*
@@ -2178,17 +2178,17 @@ _private_log_power_of_two :: proc(a: ^Int, base: DIGIT) -> (log: int, err: Error Assumes `src` and `dest` to not be `nil` and have been initialized.
*/
_private_copy_digits :: proc(dest, src: ^Int, digits: int, offset := int(0)) -> (err: Error) {
- digits := digits;
+ digits := digits
/*
If dest == src, do nothing
*/
if dest == src {
- return nil;
+ return nil
}
- digits = min(digits, len(src.digit), len(dest.digit));
- mem.copy_non_overlapping(&dest.digit[0], &src.digit[offset], size_of(DIGIT) * digits);
- return nil;
+ digits = min(digits, len(src.digit), len(dest.digit))
+ mem.copy_non_overlapping(&dest.digit[0], &src.digit[offset], size_of(DIGIT) * digits)
+ return nil
}
/*
@@ -2208,7 +2208,7 @@ _private_int_rem_128 := [?]DIGIT{ 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
-};
+}
#assert(128 * size_of(DIGIT) == size_of(_private_int_rem_128));
_private_int_rem_105 := [?]DIGIT{
@@ -2219,7 +2219,7 @@ _private_int_rem_105 := [?]DIGIT{ 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1,
1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1,
-};
+}
#assert(105 * size_of(DIGIT) == size_of(_private_int_rem_105));
_private_prime_table := [?]DIGIT{
@@ -2258,7 +2258,7 @@ _private_prime_table := [?]DIGIT{ 0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,
0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,
0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653,
-};
+}
#assert(256 * size_of(DIGIT) == size_of(_private_prime_table));
when MATH_BIG_FORCE_64_BIT || (!MATH_BIG_FORCE_32_BIT && size_of(rawptr) == 8) {
@@ -2298,7 +2298,7 @@ when MATH_BIG_FORCE_64_BIT || (!MATH_BIG_FORCE_32_BIT && size_of(rawptr) == 8) { /* f(32): */ 263_130_836_933_693_530_167_218_012_160_000_000,
/* f(33): */ 8_683_317_618_811_886_495_518_194_401_280_000_000,
/* f(34): */ 295_232_799_039_604_140_847_618_609_643_520_000_000,
- };
+ }
} else {
_factorial_table := [21]_WORD{
/* f(00): */ 1,
@@ -2322,7 +2322,7 @@ when MATH_BIG_FORCE_64_BIT || (!MATH_BIG_FORCE_32_BIT && size_of(rawptr) == 8) { /* f(18): */ 6_402_373_705_728_000,
/* f(19): */ 121_645_100_408_832_000,
/* f(20): */ 2_432_902_008_176_640_000,
- };
+ }
};
/*
diff --git a/core/math/big/public.odin b/core/math/big/public.odin index 542725289..f3dd096b6 100644 --- a/core/math/big/public.odin +++ b/core/math/big/public.odin @@ -21,14 +21,14 @@ package math_big High-level addition. Handles sign.
*/
int_add :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(dest, a, b);
- context.allocator = allocator;
+ assert_if_nil(dest, a, b)
+ context.allocator = allocator
- internal_clear_if_uninitialized(dest, a, b) or_return;
+ internal_clear_if_uninitialized(dest, a, b) or_return
/*
All parameters have been initialized.
*/
- return #force_inline internal_int_add_signed(dest, a, b);
+ return #force_inline internal_int_add_signed(dest, a, b)
}
/*
@@ -38,33 +38,33 @@ int_add :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error dest = a + digit;
*/
int_add_digit :: proc(dest, a: ^Int, digit: DIGIT, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(dest, a);
- context.allocator = allocator;
+ assert_if_nil(dest, a)
+ context.allocator = allocator
- internal_clear_if_uninitialized(a) or_return;
+ internal_clear_if_uninitialized(a) or_return
/*
Grow destination as required.
*/
- grow(dest, a.used + 1) or_return;
+ grow(dest, a.used + 1) or_return
/*
All parameters have been initialized.
*/
- return #force_inline internal_int_add_digit(dest, a, digit);
+ return #force_inline internal_int_add_digit(dest, a, digit)
}
/*
High-level subtraction, dest = number - decrease. Handles signs.
*/
int_sub :: proc(dest, number, decrease: ^Int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(dest, number, decrease);
- context.allocator = allocator;
+ assert_if_nil(dest, number, decrease)
+ context.allocator = allocator
- internal_clear_if_uninitialized(dest, number, decrease) or_return;
+ internal_clear_if_uninitialized(dest, number, decrease) or_return
/*
All parameters have been initialized.
*/
- return #force_inline internal_int_sub_signed(dest, number, decrease);
+ return #force_inline internal_int_sub_signed(dest, number, decrease)
}
/*
@@ -74,19 +74,19 @@ int_sub :: proc(dest, number, decrease: ^Int, allocator := context.allocator) -> dest = a - digit;
*/
int_sub_digit :: proc(dest, a: ^Int, digit: DIGIT, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(dest, a);
- context.allocator = allocator;
+ assert_if_nil(dest, a)
+ context.allocator = allocator
- internal_clear_if_uninitialized(a) or_return;
+ internal_clear_if_uninitialized(a) or_return
/*
Grow destination as required.
*/
- grow(dest, a.used + 1) or_return;
+ grow(dest, a.used + 1) or_return
/*
All parameters have been initialized.
*/
- return #force_inline internal_int_sub_digit(dest, a, digit);
+ return #force_inline internal_int_sub_digit(dest, a, digit)
}
/*
@@ -94,64 +94,64 @@ int_sub_digit :: proc(dest, a: ^Int, digit: DIGIT, allocator := context.allocato dest = src >> 1
*/
int_halve :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(dest, src);
- context.allocator = allocator;
+ assert_if_nil(dest, src)
+ context.allocator = allocator
- internal_clear_if_uninitialized(dest, src) or_return;
+ internal_clear_if_uninitialized(dest, src) or_return
/*
Grow destination as required.
*/
if dest != src { grow(dest, src.used + 1) or_return }
- return #force_inline internal_int_shr1(dest, src);
+ return #force_inline internal_int_shr1(dest, src)
}
-halve :: proc { int_halve, };
-shr1 :: halve;
+halve :: proc { int_halve, }
+shr1 :: halve
/*
dest = src * 2
dest = src << 1
*/
int_double :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(dest, src);
- context.allocator = allocator;
+ assert_if_nil(dest, src)
+ context.allocator = allocator
- internal_clear_if_uninitialized(dest, src) or_return;
+ internal_clear_if_uninitialized(dest, src) or_return
/*
Grow destination as required.
*/
if dest != src { grow(dest, src.used + 1) or_return; }
- return #force_inline internal_int_shl1(dest, src);
+ return #force_inline internal_int_shl1(dest, src)
}
-double :: proc { int_double, };
-shl1 :: double;
+double :: proc { int_double, }
+shl1 :: double
/*
Multiply by a DIGIT.
*/
int_mul_digit :: proc(dest, src: ^Int, multiplier: DIGIT, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(dest, src);
- context.allocator = allocator;
+ assert_if_nil(dest, src)
+ context.allocator = allocator
- internal_clear_if_uninitialized(src, dest) or_return;
+ internal_clear_if_uninitialized(src, dest) or_return
- return #force_inline internal_int_mul_digit(dest, src, multiplier);
+ return #force_inline internal_int_mul_digit(dest, src, multiplier)
}
/*
High level multiplication (handles sign).
*/
int_mul :: proc(dest, src, multiplier: ^Int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(dest, src, multiplier);
- context.allocator = allocator;
+ assert_if_nil(dest, src, multiplier)
+ context.allocator = allocator
- internal_clear_if_uninitialized(dest, src, multiplier) or_return;
+ internal_clear_if_uninitialized(dest, src, multiplier) or_return
- return #force_inline internal_int_mul(dest, src, multiplier);
+ return #force_inline internal_int_mul(dest, src, multiplier)
}
-mul :: proc { int_mul, int_mul_digit, };
+mul :: proc { int_mul, int_mul_digit, }
sqr :: proc(dest, src: ^Int) -> (err: Error) { return mul(dest, src, src); }
@@ -160,46 +160,46 @@ sqr :: proc(dest, src: ^Int) -> (err: Error) { return mul(dest, src, src); } Both the quotient and remainder are optional and may be passed a nil.
*/
int_divmod :: proc(quotient, remainder, numerator, denominator: ^Int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
/*
Early out if neither of the results is wanted.
*/
if quotient == nil && remainder == nil { return nil; }
- internal_clear_if_uninitialized(numerator, denominator) or_return;
+ internal_clear_if_uninitialized(numerator, denominator) or_return
- return #force_inline internal_divmod(quotient, remainder, numerator, denominator);
+ return #force_inline internal_divmod(quotient, remainder, numerator, denominator)
}
int_divmod_digit :: proc(quotient, numerator: ^Int, denominator: DIGIT, allocator := context.allocator) -> (remainder: DIGIT, err: Error) {
- assert_if_nil(quotient, numerator);
- context.allocator = allocator;
+ assert_if_nil(quotient, numerator)
+ context.allocator = allocator
- internal_clear_if_uninitialized(numerator) or_return;
+ internal_clear_if_uninitialized(numerator) or_return
- return #force_inline internal_divmod(quotient, numerator, denominator);
+ return #force_inline internal_divmod(quotient, numerator, denominator)
}
-divmod :: proc{ int_divmod, int_divmod_digit, };
+divmod :: proc{ int_divmod, int_divmod_digit, }
int_div :: proc(quotient, numerator, denominator: ^Int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(quotient, numerator, denominator);
- context.allocator = allocator;
+ assert_if_nil(quotient, numerator, denominator)
+ context.allocator = allocator
- internal_clear_if_uninitialized(numerator, denominator) or_return;
+ internal_clear_if_uninitialized(numerator, denominator) or_return
- return #force_inline internal_divmod(quotient, nil, numerator, denominator);
+ return #force_inline internal_divmod(quotient, nil, numerator, denominator)
}
int_div_digit :: proc(quotient, numerator: ^Int, denominator: DIGIT, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(quotient, numerator);
- context.allocator = allocator;
+ assert_if_nil(quotient, numerator)
+ context.allocator = allocator
- internal_clear_if_uninitialized(numerator) or_return;
+ internal_clear_if_uninitialized(numerator) or_return
- _ = #force_inline internal_divmod(quotient, numerator, denominator) or_return;
- return;
+ _ = #force_inline internal_divmod(quotient, numerator, denominator) or_return
+ return
}
-div :: proc { int_div, int_div_digit, };
+div :: proc { int_div, int_div_digit, }
/*
remainder = numerator % denominator.
@@ -207,80 +207,80 @@ div :: proc { int_div, int_div_digit, }; denominator < remainder <= 0 if denominator < 0
*/
int_mod :: proc(remainder, numerator, denominator: ^Int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(remainder, numerator, denominator);
- context.allocator = allocator;
+ assert_if_nil(remainder, numerator, denominator)
+ context.allocator = allocator
- internal_clear_if_uninitialized(numerator, denominator) or_return;
+ internal_clear_if_uninitialized(numerator, denominator) or_return
- return #force_inline internal_int_mod(remainder, numerator, denominator);
+ return #force_inline internal_int_mod(remainder, numerator, denominator)
}
int_mod_digit :: proc(numerator: ^Int, denominator: DIGIT, allocator := context.allocator) -> (remainder: DIGIT, err: Error) {
- return #force_inline internal_divmod(nil, numerator, denominator, allocator);
+ return #force_inline internal_divmod(nil, numerator, denominator, allocator)
}
-mod :: proc { int_mod, int_mod_digit, };
+mod :: proc { int_mod, int_mod_digit, }
/*
remainder = (number + addend) % modulus.
*/
int_addmod :: proc(remainder, number, addend, modulus: ^Int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(remainder, number, addend);
- context.allocator = allocator;
+ assert_if_nil(remainder, number, addend)
+ context.allocator = allocator
- internal_clear_if_uninitialized(number, addend, modulus) or_return;
+ internal_clear_if_uninitialized(number, addend, modulus) or_return
- return #force_inline internal_addmod(remainder, number, addend, modulus);
+ return #force_inline internal_addmod(remainder, number, addend, modulus)
}
-addmod :: proc { int_addmod, };
+addmod :: proc { int_addmod, }
/*
remainder = (number - decrease) % modulus.
*/
int_submod :: proc(remainder, number, decrease, modulus: ^Int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(remainder, number, decrease);
- context.allocator = allocator;
+ assert_if_nil(remainder, number, decrease)
+ context.allocator = allocator
- internal_clear_if_uninitialized(number, decrease, modulus) or_return;
+ internal_clear_if_uninitialized(number, decrease, modulus) or_return
- return #force_inline internal_submod(remainder, number, decrease, modulus);
+ return #force_inline internal_submod(remainder, number, decrease, modulus)
}
-submod :: proc { int_submod, };
+submod :: proc { int_submod, }
/*
remainder = (number * multiplicand) % modulus.
*/
int_mulmod :: proc(remainder, number, multiplicand, modulus: ^Int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(remainder, number, multiplicand);
- context.allocator = allocator;
+ assert_if_nil(remainder, number, multiplicand)
+ context.allocator = allocator
- internal_clear_if_uninitialized(number, multiplicand, modulus) or_return;
+ internal_clear_if_uninitialized(number, multiplicand, modulus) or_return
- return #force_inline internal_mulmod(remainder, number, multiplicand, modulus);
+ return #force_inline internal_mulmod(remainder, number, multiplicand, modulus)
}
-mulmod :: proc { int_mulmod, };
+mulmod :: proc { int_mulmod, }
/*
remainder = (number * number) % modulus.
*/
int_sqrmod :: proc(remainder, number, modulus: ^Int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(remainder, number, modulus);
- context.allocator = allocator;
+ assert_if_nil(remainder, number, modulus)
+ context.allocator = allocator
- internal_clear_if_uninitialized(number, modulus) or_return;
+ internal_clear_if_uninitialized(number, modulus) or_return
- return #force_inline internal_sqrmod(remainder, number, modulus);
+ return #force_inline internal_sqrmod(remainder, number, modulus)
}
-sqrmod :: proc { int_sqrmod, };
+sqrmod :: proc { int_sqrmod, }
int_factorial :: proc(res: ^Int, n: int, allocator := context.allocator) -> (err: Error) {
if n < 0 || n > FACTORIAL_MAX_N { return .Invalid_Argument; }
- assert_if_nil(res);
+ assert_if_nil(res)
- return #force_inline internal_int_factorial(res, n, allocator);
+ return #force_inline internal_int_factorial(res, n, allocator)
}
-factorial :: proc { int_factorial, };
+factorial :: proc { int_factorial, }
/*
@@ -299,8 +299,8 @@ factorial :: proc { int_factorial, }; */
int_choose_digit :: proc(res: ^Int, n, k: int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(res);
- context.allocator = allocator;
+ assert_if_nil(res)
+ context.allocator = allocator
if n < 0 || n > FACTORIAL_MAX_N { return .Invalid_Argument; }
if k > n { return internal_zero(res); }
@@ -308,8 +308,8 @@ int_choose_digit :: proc(res: ^Int, n, k: int, allocator := context.allocator) - /*
res = n! / (k! * (n - k)!)
*/
- n_fac, k_fac, n_minus_k_fac := &Int{}, &Int{}, &Int{};
- defer internal_destroy(n_fac, k_fac, n_minus_k_fac);
+ n_fac, k_fac, n_minus_k_fac := &Int{}, &Int{}, &Int{}
+ defer internal_destroy(n_fac, k_fac, n_minus_k_fac)
#force_inline internal_int_factorial(n_minus_k_fac, n - k) or_return;
#force_inline internal_int_factorial(k_fac, k) or_return;
@@ -318,112 +318,112 @@ int_choose_digit :: proc(res: ^Int, n, k: int, allocator := context.allocator) - #force_inline internal_int_factorial(n_fac, n) or_return;
#force_inline internal_div(res, n_fac, k_fac) or_return;
- return;
+ return
}
-choose :: proc { int_choose_digit, };
+choose :: proc { int_choose_digit, }
/*
Function computing both GCD and (if target isn't `nil`) also LCM.
*/
int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
if res_gcd == nil && res_lcm == nil { return nil; }
- assert_if_nil(a, b);
- context.allocator = allocator;
+ assert_if_nil(a, b)
+ context.allocator = allocator
- internal_clear_if_uninitialized(a, b) or_return;
- return #force_inline internal_int_gcd_lcm(res_gcd, res_lcm, a, b);
+ internal_clear_if_uninitialized(a, b) or_return
+ return #force_inline internal_int_gcd_lcm(res_gcd, res_lcm, a, b)
}
-gcd_lcm :: proc { int_gcd_lcm, };
+gcd_lcm :: proc { int_gcd_lcm, }
/*
Greatest Common Divisor.
*/
int_gcd :: proc(res, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
- return #force_inline int_gcd_lcm(res, nil, a, b, allocator);
+ return #force_inline int_gcd_lcm(res, nil, a, b, allocator)
}
-gcd :: proc { int_gcd, };
+gcd :: proc { int_gcd, }
/*
Least Common Multiple.
*/
int_lcm :: proc(res, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
- return #force_inline int_gcd_lcm(nil, res, a, b, allocator);
+ return #force_inline int_gcd_lcm(nil, res, a, b, allocator)
}
-lcm :: proc { int_lcm, };
+lcm :: proc { int_lcm, }
/*
remainder = numerator % (1 << bits)
*/
int_mod_bits :: proc(remainder, numerator: ^Int, bits: int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(remainder, numerator);
- context.allocator = allocator;
+ assert_if_nil(remainder, numerator)
+ context.allocator = allocator
- internal_clear_if_uninitialized(remainder, numerator) or_return;
+ internal_clear_if_uninitialized(remainder, numerator) or_return
if bits < 0 { return .Invalid_Argument; }
- return #force_inline internal_int_mod_bits(remainder, numerator, bits);
+ return #force_inline internal_int_mod_bits(remainder, numerator, bits)
}
-mod_bits :: proc { int_mod_bits, };
+mod_bits :: proc { int_mod_bits, }
/*
Logs and roots and such.
*/
int_log :: proc(a: ^Int, base: DIGIT, allocator := context.allocator) -> (res: int, err: Error) {
- assert_if_nil(a);
- context.allocator = allocator;
+ assert_if_nil(a)
+ context.allocator = allocator
- internal_clear_if_uninitialized(a) or_return;
+ internal_clear_if_uninitialized(a) or_return
- return #force_inline internal_int_log(a, base);
+ return #force_inline internal_int_log(a, base)
}
digit_log :: proc(a: DIGIT, base: DIGIT) -> (log: int, err: Error) {
- return #force_inline internal_digit_log(a, base);
+ return #force_inline internal_digit_log(a, base)
}
-log :: proc { int_log, digit_log, };
+log :: proc { int_log, digit_log, }
/*
Calculate `dest = base^power` using a square-multiply algorithm.
*/
int_pow :: proc(dest, base: ^Int, power: int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(dest, base);
- context.allocator = allocator;
+ assert_if_nil(dest, base)
+ context.allocator = allocator
- internal_clear_if_uninitialized(dest, base) or_return;
+ internal_clear_if_uninitialized(dest, base) or_return
- return #force_inline internal_int_pow(dest, base, power);
+ return #force_inline internal_int_pow(dest, base, power)
}
/*
Calculate `dest = base^power` using a square-multiply algorithm.
*/
int_pow_int :: proc(dest: ^Int, base, power: int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(dest);
+ assert_if_nil(dest)
- return #force_inline internal_pow(dest, base, power, allocator);
+ return #force_inline internal_pow(dest, base, power, allocator)
}
-pow :: proc { int_pow, int_pow_int, small_pow, };
-exp :: pow;
+pow :: proc { int_pow, int_pow_int, small_pow, }
+exp :: pow
small_pow :: proc(base: _WORD, exponent: _WORD) -> (result: _WORD) {
- return #force_inline internal_small_pow(base, exponent);
+ return #force_inline internal_small_pow(base, exponent)
}
/*
This function is less generic than `root_n`, simpler and faster.
*/
int_sqrt :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(dest, src);
- context.allocator = allocator;
+ assert_if_nil(dest, src)
+ context.allocator = allocator
- internal_clear_if_uninitialized(dest, src) or_return;
+ internal_clear_if_uninitialized(dest, src) or_return
- return #force_inline internal_int_sqrt(dest, src);
+ return #force_inline internal_int_sqrt(dest, src)
}
-sqrt :: proc { int_sqrt, };
+sqrt :: proc { int_sqrt, }
/*
@@ -434,22 +434,22 @@ sqrt :: proc { int_sqrt, }; which will find the root in `log(n)` time where each step involves a fair bit.
*/
int_root_n :: proc(dest, src: ^Int, n: int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
/*
Fast path for n == 2.
*/
if n == 2 { return sqrt(dest, src); }
- assert_if_nil(dest, src);
+ assert_if_nil(dest, src)
/*
Initialize dest + src if needed.
*/
- internal_clear_if_uninitialized(dest, src) or_return;
+ internal_clear_if_uninitialized(dest, src) or_return
- return #force_inline internal_int_root_n(dest, src, n);
+ return #force_inline internal_int_root_n(dest, src, n)
}
-root_n :: proc { int_root_n, };
+root_n :: proc { int_root_n, }
/*
Comparison routines.
@@ -458,103 +458,103 @@ root_n :: proc { int_root_n, }; int_is_initialized :: proc(a: ^Int) -> bool {
if a == nil { return false; }
- return #force_inline internal_int_is_initialized(a);
+ return #force_inline internal_int_is_initialized(a)
}
int_is_zero :: proc(a: ^Int, allocator := context.allocator) -> (zero: bool, err: Error) {
- assert_if_nil(a);
- context.allocator = allocator;
+ assert_if_nil(a)
+ context.allocator = allocator
- internal_clear_if_uninitialized(a) or_return;
+ internal_clear_if_uninitialized(a) or_return
- return #force_inline internal_is_zero(a), nil;
+ return #force_inline internal_is_zero(a), nil
}
int_is_positive :: proc(a: ^Int, allocator := context.allocator) -> (positive: bool, err: Error) {
- assert_if_nil(a);
- context.allocator = allocator;
+ assert_if_nil(a)
+ context.allocator = allocator
- internal_clear_if_uninitialized(a) or_return;
+ internal_clear_if_uninitialized(a) or_return
- return #force_inline internal_is_positive(a), nil;
+ return #force_inline internal_is_positive(a), nil
}
int_is_negative :: proc(a: ^Int, allocator := context.allocator) -> (negative: bool, err: Error) {
- assert_if_nil(a);
- context.allocator = allocator;
+ assert_if_nil(a)
+ context.allocator = allocator
- internal_clear_if_uninitialized(a) or_return;
+ internal_clear_if_uninitialized(a) or_return
- return #force_inline internal_is_negative(a), nil;
+ return #force_inline internal_is_negative(a), nil
}
int_is_even :: proc(a: ^Int, allocator := context.allocator) -> (even: bool, err: Error) {
- assert_if_nil(a);
- context.allocator = allocator;
+ assert_if_nil(a)
+ context.allocator = allocator
- internal_clear_if_uninitialized(a) or_return;
+ internal_clear_if_uninitialized(a) or_return
- return #force_inline internal_is_even(a), nil;
+ return #force_inline internal_is_even(a), nil
}
int_is_odd :: proc(a: ^Int, allocator := context.allocator) -> (odd: bool, err: Error) {
- assert_if_nil(a);
- context.allocator = allocator;
+ assert_if_nil(a)
+ context.allocator = allocator
- internal_clear_if_uninitialized(a) or_return;
+ internal_clear_if_uninitialized(a) or_return
- return #force_inline internal_is_odd(a), nil;
+ return #force_inline internal_is_odd(a), nil
}
platform_int_is_power_of_two :: #force_inline proc(a: int) -> bool {
- return ((a) != 0) && (((a) & ((a) - 1)) == 0);
+ return ((a) != 0) && (((a) & ((a) - 1)) == 0)
}
int_is_power_of_two :: proc(a: ^Int, allocator := context.allocator) -> (res: bool, err: Error) {
- assert_if_nil(a);
- context.allocator = allocator;
+ assert_if_nil(a)
+ context.allocator = allocator
- internal_clear_if_uninitialized(a) or_return;
+ internal_clear_if_uninitialized(a) or_return
- return #force_inline internal_is_power_of_two(a), nil;
+ return #force_inline internal_is_power_of_two(a), nil
}
/*
Compare two `Int`s, signed.
*/
int_compare :: proc(a, b: ^Int, allocator := context.allocator) -> (comparison: int, err: Error) {
- assert_if_nil(a, b);
- context.allocator = allocator;
+ assert_if_nil(a, b)
+ context.allocator = allocator
- internal_clear_if_uninitialized(a, b) or_return;
+ internal_clear_if_uninitialized(a, b) or_return
- return #force_inline internal_cmp(a, b), nil;
+ return #force_inline internal_cmp(a, b), nil
}
-int_cmp :: int_compare;
+int_cmp :: int_compare
/*
Compare an `Int` to an unsigned number upto the size of the backing type.
*/
int_compare_digit :: proc(a: ^Int, b: DIGIT, allocator := context.allocator) -> (comparison: int, err: Error) {
- assert_if_nil(a);
- context.allocator = allocator;
+ assert_if_nil(a)
+ context.allocator = allocator
- internal_clear_if_uninitialized(a) or_return;
+ internal_clear_if_uninitialized(a) or_return
- return #force_inline internal_cmp_digit(a, b), nil;
+ return #force_inline internal_cmp_digit(a, b), nil
}
-int_cmp_digit :: int_compare_digit;
+int_cmp_digit :: int_compare_digit
/*
Compare the magnitude of two `Int`s, unsigned.
*/
int_compare_magnitude :: proc(a, b: ^Int, allocator := context.allocator) -> (res: int, err: Error) {
- assert_if_nil(a, b);
- context.allocator = allocator;
+ assert_if_nil(a, b)
+ context.allocator = allocator
- internal_clear_if_uninitialized(a, b) or_return;
+ internal_clear_if_uninitialized(a, b) or_return
- return #force_inline internal_cmp_mag(a, b), nil;
+ return #force_inline internal_cmp_mag(a, b), nil
}
/*
@@ -564,10 +564,10 @@ int_compare_magnitude :: proc(a, b: ^Int, allocator := context.allocator) -> (re Assumes `a` not to be `nil` and to have been initialized.
*/
int_is_square :: proc(a: ^Int, allocator := context.allocator) -> (square: bool, err: Error) {
- assert_if_nil(a);
- context.allocator = allocator;
+ assert_if_nil(a)
+ context.allocator = allocator
- internal_clear_if_uninitialized(a) or_return;
+ internal_clear_if_uninitialized(a) or_return
- return #force_inline internal_int_is_square(a);
+ return #force_inline internal_int_is_square(a)
}
\ No newline at end of file diff --git a/core/math/big/radix.odin b/core/math/big/radix.odin index acf0bacbd..8908f7775 100644 --- a/core/math/big/radix.odin +++ b/core/math/big/radix.odin @@ -22,15 +22,15 @@ import "core:mem" This version of `itoa` allocates one behalf of the caller. The caller must free the string. */ int_itoa_string :: proc(a: ^Int, radix := i8(-1), zero_terminate := false, allocator := context.allocator) -> (res: string, err: Error) { - assert_if_nil(a); - context.allocator = allocator; + assert_if_nil(a) + context.allocator = allocator - a := a; radix := radix; - clear_if_uninitialized(a) or_return; + a := a; radix := radix + clear_if_uninitialized(a) or_return /* Radix defaults to 10. */ - radix = radix if radix > 0 else 10; + radix = radix if radix > 0 else 10 /* TODO: If we want to write a prefix for some of the radixes, we can oversize the buffer. @@ -41,39 +41,39 @@ int_itoa_string :: proc(a: ^Int, radix := i8(-1), zero_terminate := false, alloc Calculate the size of the buffer we need, and Exit if calculating the size returned an error. */ - size := radix_size(a, radix, zero_terminate) or_return; + size := radix_size(a, radix, zero_terminate) or_return /* Allocate the buffer we need. */ - buffer := make([]u8, size); + buffer := make([]u8, size) /* Write the digits out into the buffer. */ - written: int; - written, err = int_itoa_raw(a, radix, buffer, size, zero_terminate); + written: int + written, err = int_itoa_raw(a, radix, buffer, size, zero_terminate) - return string(buffer[:written]), err; + return string(buffer[:written]), err } /* This version of `itoa` allocates one behalf of the caller. The caller must free the string. */ int_itoa_cstring :: proc(a: ^Int, radix := i8(-1), allocator := context.allocator) -> (res: cstring, err: Error) { - assert_if_nil(a); - context.allocator = allocator; + assert_if_nil(a) + context.allocator = allocator - a := a; radix := radix; - clear_if_uninitialized(a) or_return; + a := a; radix := radix + clear_if_uninitialized(a) or_return /* Radix defaults to 10. */ - radix = radix if radix > 0 else 10; + radix = radix if radix > 0 else 10 - s: string; - s, err = int_itoa_string(a, radix, true); - return cstring(raw_data(s)), err; + s: string + s, err = int_itoa_string(a, radix, true) + return cstring(raw_data(s)), err } /* @@ -97,57 +97,57 @@ int_itoa_cstring :: proc(a: ^Int, radix := i8(-1), allocator := context.allocato and having to perform a buffer overflow check each character. */ int_itoa_raw :: proc(a: ^Int, radix: i8, buffer: []u8, size := int(-1), zero_terminate := false) -> (written: int, err: Error) { - assert_if_nil(a); - a := a; radix := radix; size := size; - clear_if_uninitialized(a) or_return; + assert_if_nil(a) + a := a; radix := radix; size := size + clear_if_uninitialized(a) or_return /* Radix defaults to 10. */ - radix = radix if radix > 0 else 10; + radix = radix if radix > 0 else 10 if radix < 2 || radix > 64 { - return 0, .Invalid_Argument; + return 0, .Invalid_Argument } /* We weren't given a size. Let's compute it. */ if size == -1 { - size = radix_size(a, radix, zero_terminate) or_return; + size = radix_size(a, radix, zero_terminate) or_return } /* Early exit if the buffer we were given is too small. */ - available := len(buffer); + available := len(buffer) if available < size { - return 0, .Buffer_Overflow; + return 0, .Buffer_Overflow } /* Fast path for when `Int` == 0 or the entire `Int` fits in a single radix digit. */ - z, _ := is_zero(a); + z, _ := is_zero(a) if z || (a.used == 1 && a.digit[0] < DIGIT(radix)) { if zero_terminate { - available -= 1; - buffer[available] = 0; + available -= 1 + buffer[available] = 0 } - available -= 1; - buffer[available] = RADIX_TABLE[a.digit[0]]; + available -= 1 + buffer[available] = RADIX_TABLE[a.digit[0]] if n, _ := is_neg(a); n { - available -= 1; - buffer[available] = '-'; + available -= 1 + buffer[available] = '-' } /* If we overestimated the size, we need to move the buffer left. */ - written = len(buffer) - available; + written = len(buffer) - available if written < size { - diff := size - written; - mem.copy(&buffer[0], &buffer[diff], written); + diff := size - written + mem.copy(&buffer[0], &buffer[diff], written) } - return written, nil; + return written, nil } /* @@ -155,32 +155,32 @@ int_itoa_raw :: proc(a: ^Int, radix: i8, buffer: []u8, size := int(-1), zero_ter */ if a.used == 1 || a.used == 2 { if zero_terminate { - available -= 1; - buffer[available] = 0; + available -= 1 + buffer[available] = 0 } - val := _WORD(a.digit[1]) << _DIGIT_BITS + _WORD(a.digit[0]); + val := _WORD(a.digit[1]) << _DIGIT_BITS + _WORD(a.digit[0]) for val > 0 { - q := val / _WORD(radix); - available -= 1; - buffer[available] = RADIX_TABLE[val - (q * _WORD(radix))]; + q := val / _WORD(radix) + available -= 1 + buffer[available] = RADIX_TABLE[val - (q * _WORD(radix))] - val = q; + val = q } if n, _ := is_neg(a); n { - available -= 1; - buffer[available] = '-'; + available -= 1 + buffer[available] = '-' } /* If we overestimated the size, we need to move the buffer left. */ - written = len(buffer) - available; + written = len(buffer) - available if written < size { - diff := size - written; - mem.copy(&buffer[0], &buffer[diff], written); + diff := size - written + mem.copy(&buffer[0], &buffer[diff], written) } - return written, nil; + return written, nil } /* @@ -188,57 +188,57 @@ int_itoa_raw :: proc(a: ^Int, radix: i8, buffer: []u8, size := int(-1), zero_ter */ if is_power_of_two(int(radix)) { if zero_terminate { - available -= 1; - buffer[available] = 0; + available -= 1 + buffer[available] = 0 } - shift, count: int; + shift, count: int // mask := _WORD(radix - 1); - shift, err = log(DIGIT(radix), 2); - count, err = count_bits(a); - digit: _WORD; + shift, err = log(DIGIT(radix), 2) + count, err = count_bits(a) + digit: _WORD for offset := 0; offset < count; offset += shift { - bits_to_get := int(min(count - offset, shift)); + bits_to_get := int(min(count - offset, shift)) - digit, err = int_bitfield_extract(a, offset, bits_to_get); + digit, err = int_bitfield_extract(a, offset, bits_to_get) if err != nil { - return len(buffer) - available, .Invalid_Argument; + return len(buffer) - available, .Invalid_Argument } - available -= 1; - buffer[available] = RADIX_TABLE[digit]; + available -= 1 + buffer[available] = RADIX_TABLE[digit] } if n, _ := is_neg(a); n { - available -= 1; - buffer[available] = '-'; + available -= 1 + buffer[available] = '-' } /* If we overestimated the size, we need to move the buffer left. */ - written = len(buffer) - available; + written = len(buffer) - available if written < size { - diff := size - written; - mem.copy(&buffer[0], &buffer[diff], written); + diff := size - written + mem.copy(&buffer[0], &buffer[diff], written) } - return written, nil; + return written, nil } - return _itoa_raw_full(a, radix, buffer, zero_terminate); + return _itoa_raw_full(a, radix, buffer, zero_terminate) } -itoa :: proc{int_itoa_string, int_itoa_raw}; -int_to_string :: int_itoa_string; -int_to_cstring :: int_itoa_cstring; +itoa :: proc{int_itoa_string, int_itoa_raw} +int_to_string :: int_itoa_string +int_to_cstring :: int_itoa_cstring /* Read a string [ASCII] in a given radix. */ int_atoi :: proc(res: ^Int, input: string, radix := i8(10), allocator := context.allocator) -> (err: Error) { - assert_if_nil(res); - input := input; - context.allocator = allocator; + assert_if_nil(res) + input := input + context.allocator = allocator /* Make sure the radix is ok. @@ -249,92 +249,92 @@ int_atoi :: proc(res: ^Int, input: string, radix := i8(10), allocator := context /* Set the integer to the default of zero. */ - internal_zero(res) or_return; + internal_zero(res) or_return /* We'll interpret an empty string as zero. */ if len(input) == 0 { - return nil; + return nil } /* If the leading digit is a minus set the sign to negative. Given the above early out, the length should be at least 1. */ - sign := Sign.Zero_or_Positive; + sign := Sign.Zero_or_Positive if input[0] == '-' { - input = input[1:]; - sign = .Negative; + input = input[1:] + sign = .Negative } /* Process each digit of the string. */ - ch: rune; + ch: rune for len(input) > 0 { /* if the radix <= 36 the conversion is case insensitive * this allows numbers like 1AB and 1ab to represent the same value * [e.g. in hex] */ - ch = rune(input[0]); + ch = rune(input[0]) if radix <= 36 && ch >= 'a' && ch <= 'z' { - ch -= 32; // 'a' - 'A' + ch -= 32 // 'a' - 'A' } - pos := ch - '+'; + pos := ch - '+' if RADIX_TABLE_REVERSE_SIZE <= pos { - break; + break } - y := RADIX_TABLE_REVERSE[pos]; + y := RADIX_TABLE_REVERSE[pos] /* if the char was found in the map * and is less than the given radix add it * to the number, otherwise exit the loop. */ if y >= u8(radix) { - break; + break } - internal_mul(res, res, DIGIT(radix)) or_return; - internal_add(res, res, DIGIT(y)) or_return; + internal_mul(res, res, DIGIT(radix)) or_return + internal_add(res, res, DIGIT(y)) or_return - input = input[1:]; + input = input[1:] } /* If an illegal character was found, fail. */ if len(input) > 0 && ch != 0 && ch != '\r' && ch != '\n' { - return .Invalid_Argument; + return .Invalid_Argument } /* Set the sign only if res != 0. */ if res.used > 0 { - res.sign = sign; + res.sign = sign } - return nil; + return nil } -atoi :: proc { int_atoi, }; +atoi :: proc { int_atoi, } /* We size for `string` by default. */ radix_size :: proc(a: ^Int, radix: i8, zero_terminate := false, allocator := context.allocator) -> (size: int, err: Error) { - a := a; - assert_if_nil(a); + a := a + assert_if_nil(a) if radix < 2 || radix > 64 { return -1, .Invalid_Argument; } - clear_if_uninitialized(a) or_return; + clear_if_uninitialized(a) or_return if internal_is_zero(a) { if zero_terminate { - return 2, nil; + return 2, nil } - return 1, nil; + return 1, nil } if internal_is_power_of_two(a) { @@ -345,37 +345,37 @@ radix_size :: proc(a: ^Int, radix: i8, zero_terminate := false, allocator := con used = a.used, sign = .Zero_or_Positive, digit = a.digit, - }; + } - size = internal_log(t, DIGIT(radix)) or_return; + size = internal_log(t, DIGIT(radix)) or_return } else { - la, k := &Int{}, &Int{}; - defer internal_destroy(la, k); + la, k := &Int{}, &Int{} + defer internal_destroy(la, k) /* la = floor(log_2(a)) + 1 */ - bit_count := internal_count_bits(a); - internal_set(la, bit_count) or_return; + bit_count := internal_count_bits(a) + internal_set(la, bit_count) or_return /* k = floor(2^29/log_2(radix)) + 1 */ - lb := _log_bases; - internal_set(k, lb[radix]) or_return; + lb := _log_bases + internal_set(k, lb[radix]) or_return /* n = floor((la * k) / 2^29) + 1 */ - internal_mul(k, la, k) or_return; - internal_shr(k, k, _RADIX_SIZE_SCALE) or_return; + internal_mul(k, la, k) or_return + internal_shr(k, k, _RADIX_SIZE_SCALE) or_return /* The "+1" here is the "+1" in "floor((la * k) / 2^29) + 1" */ /* n = n + 1 + EOS + sign */ - size_, _ := internal_get(k, u128); - size = int(size_); + size_, _ := internal_get(k, u128) + size = int(size_) } /* log truncates to zero, so we need to add one more, and one for `-` if negative. */ - size += 2 if a.sign == .Negative else 1; - size += 1 if zero_terminate else 0; - return size, nil; + size += 2 if a.sign == .Negative else 1 + size += 1 if zero_terminate else 0 + return size, nil } /* @@ -392,7 +392,7 @@ radix_size :: proc(a: ^Int, radix: i8, zero_terminate := false, allocator := con for 64 bit "int". */ -_RADIX_SIZE_SCALE :: 29; +_RADIX_SIZE_SCALE :: 29 _log_bases :: [65]u32{ 0, 0, 0x20000001, 0x14309399, 0x10000001, 0xdc81a35, 0xc611924, 0xb660c9e, 0xaaaaaab, 0xa1849cd, @@ -407,12 +407,12 @@ _log_bases :: [65]u32{ 0x5ab7d68, 0x5a42df0, 0x59d1506, 0x5962ffe, 0x58f7c57, 0x588f7bc, 0x582a000, 0x57c7319, 0x5766f1d, 0x5709243, 0x56adad9, 0x565474d, 0x55fd61f, 0x55a85e8, 0x5555556, -}; +} /* Characters used in radix conversions. */ -RADIX_TABLE := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; +RADIX_TABLE := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/" RADIX_TABLE_REVERSE := [RADIX_TABLE_REVERSE_SIZE]u8{ 0x3e, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x01, 0x02, 0x03, 0x04, /* +,-./01234 */ 0x05, 0x06, 0x07, 0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, /* 56789:;<=> */ @@ -422,59 +422,59 @@ RADIX_TABLE_REVERSE := [RADIX_TABLE_REVERSE_SIZE]u8{ 0xff, 0xff, 0xff, 0xff, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, /* ]^_`abcdef */ 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, /* ghijklmnop */ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, /* qrstuvwxyz */ -}; -RADIX_TABLE_REVERSE_SIZE :: 80; +} +RADIX_TABLE_REVERSE_SIZE :: 80 /* Stores a bignum as a ASCII string in a given radix (2..64) The buffer must be appropriately sized. This routine doesn't check. */ _itoa_raw_full :: proc(a: ^Int, radix: i8, buffer: []u8, zero_terminate := false, allocator := context.allocator) -> (written: int, err: Error) { - assert_if_nil(a); - context.allocator = allocator; + assert_if_nil(a) + context.allocator = allocator - temp, denominator := &Int{}, &Int{}; + temp, denominator := &Int{}, &Int{} - internal_copy(temp, a) or_return; - internal_set(denominator, radix) or_return; + internal_copy(temp, a) or_return + internal_set(denominator, radix) or_return - available := len(buffer); + available := len(buffer) if zero_terminate { - available -= 1; - buffer[available] = 0; + available -= 1 + buffer[available] = 0 } if a.sign == .Negative { - temp.sign = .Zero_or_Positive; + temp.sign = .Zero_or_Positive } - remainder: DIGIT; + remainder: DIGIT for { if remainder, err = #force_inline internal_divmod(temp, temp, DIGIT(radix)); err != nil { - internal_destroy(temp, denominator); - return len(buffer) - available, err; + internal_destroy(temp, denominator) + return len(buffer) - available, err } - available -= 1; - buffer[available] = RADIX_TABLE[remainder]; + available -= 1 + buffer[available] = RADIX_TABLE[remainder] if temp.used == 0 { - break; + break } } if a.sign == .Negative { - available -= 1; - buffer[available] = '-'; + available -= 1 + buffer[available] = '-' } - internal_destroy(temp, denominator); + internal_destroy(temp, denominator) /* If we overestimated the size, we need to move the buffer left. */ - written = len(buffer) - available; + written = len(buffer) - available if written < len(buffer) { - diff := len(buffer) - written; - mem.copy(&buffer[0], &buffer[diff], written); + diff := len(buffer) - written + mem.copy(&buffer[0], &buffer[diff], written) } - return written, nil; + return written, nil }
\ No newline at end of file diff --git a/core/math/big/test.odin b/core/math/big/test.odin index ea3c6be49..609b8ce10 100644 --- a/core/math/big/test.odin +++ b/core/math/big/test.odin @@ -25,24 +25,24 @@ PyRes :: struct { } @export test_initialize_constants :: proc "c" () -> (res: u64) { - context = runtime.default_context(); - res = u64(initialize_constants()); + context = runtime.default_context() + res = u64(initialize_constants()) //assert(MUL_KARATSUBA_CUTOFF >= 40); - return res; + return res } @export test_error_string :: proc "c" (err: Error) -> (res: cstring) { - context = runtime.default_context(); - es := Error_String; - return strings.clone_to_cstring(es[err], context.temp_allocator); + context = runtime.default_context() + es := Error_String + return strings.clone_to_cstring(es[err], context.temp_allocator) } @export test_add :: proc "c" (a, b: cstring) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - aa, bb, sum := &Int{}, &Int{}, &Int{}; - defer internal_destroy(aa, bb, sum); + aa, bb, sum := &Int{}, &Int{}, &Int{} + defer internal_destroy(aa, bb, sum) if err = atoi(aa, string(a), 16); err != nil { return PyRes{res=":add:atoi(a):", err=err}; } if err = atoi(bb, string(b), 16); err != nil { return PyRes{res=":add:atoi(b):", err=err}; } @@ -52,18 +52,18 @@ PyRes :: struct { if err = #force_inline internal_add(sum, aa, bb); err != nil { return PyRes{res=":add:add(sum,a,b):", err=err}; } } - r: cstring; - r, err = int_itoa_cstring(sum, 16, context.temp_allocator); + r: cstring + r, err = int_itoa_cstring(sum, 16, context.temp_allocator) if err != nil { return PyRes{res=":add:itoa(sum):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } @export test_sub :: proc "c" (a, b: cstring) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - aa, bb, sum := &Int{}, &Int{}, &Int{}; - defer internal_destroy(aa, bb, sum); + aa, bb, sum := &Int{}, &Int{}, &Int{} + defer internal_destroy(aa, bb, sum) if err = atoi(aa, string(a), 16); err != nil { return PyRes{res=":sub:atoi(a):", err=err}; } if err = atoi(bb, string(b), 16); err != nil { return PyRes{res=":sub:atoi(b):", err=err}; } @@ -73,63 +73,63 @@ PyRes :: struct { if err = #force_inline internal_sub(sum, aa, bb); err != nil { return PyRes{res=":sub:sub(sum,a,b):", err=err}; } } - r: cstring; - r, err = int_itoa_cstring(sum, 16, context.temp_allocator); + r: cstring + r, err = int_itoa_cstring(sum, 16, context.temp_allocator) if err != nil { return PyRes{res=":sub:itoa(sum):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } @export test_mul :: proc "c" (a, b: cstring) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - aa, bb, product := &Int{}, &Int{}, &Int{}; - defer internal_destroy(aa, bb, product); + aa, bb, product := &Int{}, &Int{}, &Int{} + defer internal_destroy(aa, bb, product) if err = atoi(aa, string(a), 16); err != nil { return PyRes{res=":mul:atoi(a):", err=err}; } if err = atoi(bb, string(b), 16); err != nil { return PyRes{res=":mul:atoi(b):", err=err}; } if err = #force_inline internal_mul(product, aa, bb); err != nil { return PyRes{res=":mul:mul(product,a,b):", err=err}; } - r: cstring; - r, err = int_itoa_cstring(product, 16, context.temp_allocator); + r: cstring + r, err = int_itoa_cstring(product, 16, context.temp_allocator) if err != nil { return PyRes{res=":mul:itoa(product):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } @export test_sqr :: proc "c" (a: cstring) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - aa, square := &Int{}, &Int{}; - defer internal_destroy(aa, square); + aa, square := &Int{}, &Int{} + defer internal_destroy(aa, square) if err = atoi(aa, string(a), 16); err != nil { return PyRes{res=":sqr:atoi(a):", err=err}; } if err = #force_inline internal_sqr(square, aa); err != nil { return PyRes{res=":sqr:sqr(square,a):", err=err}; } - r: cstring; - r, err = int_itoa_cstring(square, 16, context.temp_allocator); + r: cstring + r, err = int_itoa_cstring(square, 16, context.temp_allocator) if err != nil { return PyRes{res=":sqr:itoa(square):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } /* NOTE(Jeroen): For simplicity, we don't return the quotient and the remainder, just the quotient. */ @export test_div :: proc "c" (a, b: cstring) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - aa, bb, quotient := &Int{}, &Int{}, &Int{}; - defer internal_destroy(aa, bb, quotient); + aa, bb, quotient := &Int{}, &Int{}, &Int{} + defer internal_destroy(aa, bb, quotient) if err = atoi(aa, string(a), 16); err != nil { return PyRes{res=":div:atoi(a):", err=err}; } if err = atoi(bb, string(b), 16); err != nil { return PyRes{res=":div:atoi(b):", err=err}; } if err = #force_inline internal_div(quotient, aa, bb); err != nil { return PyRes{res=":div:div(quotient,a,b):", err=err}; } - r: cstring; - r, err = int_itoa_cstring(quotient, 16, context.temp_allocator); + r: cstring + r, err = int_itoa_cstring(quotient, 16, context.temp_allocator) if err != nil { return PyRes{res=":div:itoa(quotient):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } @@ -137,254 +137,254 @@ PyRes :: struct { res = log(a, base) */ @export test_log :: proc "c" (a: cstring, base := DIGIT(2)) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; - l: int; + context = runtime.default_context() + err: Error + l: int - aa := &Int{}; - defer internal_destroy(aa); + aa := &Int{} + defer internal_destroy(aa) if err = atoi(aa, string(a), 16); err != nil { return PyRes{res=":log:atoi(a):", err=err}; } if l, err = #force_inline internal_log(aa, base); err != nil { return PyRes{res=":log:log(a, base):", err=err}; } #force_inline internal_zero(aa); - aa.digit[0] = DIGIT(l) & _MASK; - aa.digit[1] = DIGIT(l) >> _DIGIT_BITS; - aa.used = 2; - clamp(aa); + aa.digit[0] = DIGIT(l) & _MASK + aa.digit[1] = DIGIT(l) >> _DIGIT_BITS + aa.used = 2 + clamp(aa) - r: cstring; - r, err = int_itoa_cstring(aa, 16, context.temp_allocator); + r: cstring + r, err = int_itoa_cstring(aa, 16, context.temp_allocator) if err != nil { return PyRes{res=":log:itoa(res):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } /* dest = base^power */ @export test_pow :: proc "c" (base: cstring, power := int(2)) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - dest, bb := &Int{}, &Int{}; - defer internal_destroy(dest, bb); + dest, bb := &Int{}, &Int{} + defer internal_destroy(dest, bb) if err = atoi(bb, string(base), 16); err != nil { return PyRes{res=":pow:atoi(base):", err=err}; } if err = #force_inline internal_pow(dest, bb, power); err != nil { return PyRes{res=":pow:pow(dest, base, power):", err=err}; } - r: cstring; - r, err = int_itoa_cstring(dest, 16, context.temp_allocator); + r: cstring + r, err = int_itoa_cstring(dest, 16, context.temp_allocator) if err != nil { return PyRes{res=":log:itoa(res):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } /* dest = sqrt(src) */ @export test_sqrt :: proc "c" (source: cstring) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - src := &Int{}; - defer internal_destroy(src); + src := &Int{} + defer internal_destroy(src) if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":sqrt:atoi(src):", err=err}; } if err = #force_inline internal_sqrt(src, src); err != nil { return PyRes{res=":sqrt:sqrt(src):", err=err}; } - r: cstring; - r, err = int_itoa_cstring(src, 16, context.temp_allocator); + r: cstring + r, err = int_itoa_cstring(src, 16, context.temp_allocator) if err != nil { return PyRes{res=":log:itoa(res):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } /* dest = root_n(src, power) */ @export test_root_n :: proc "c" (source: cstring, power: int) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - src := &Int{}; - defer internal_destroy(src); + src := &Int{} + defer internal_destroy(src) if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":root_n:atoi(src):", err=err}; } if err = #force_inline internal_root_n(src, src, power); err != nil { return PyRes{res=":root_n:root_n(src):", err=err}; } - r: cstring; - r, err = int_itoa_cstring(src, 16, context.temp_allocator); + r: cstring + r, err = int_itoa_cstring(src, 16, context.temp_allocator) if err != nil { return PyRes{res=":root_n:itoa(res):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } /* dest = shr_digit(src, digits) */ @export test_shr_digit :: proc "c" (source: cstring, digits: int) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - src := &Int{}; - defer internal_destroy(src); + src := &Int{} + defer internal_destroy(src) if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":shr_digit:atoi(src):", err=err}; } if err = #force_inline internal_shr_digit(src, digits); err != nil { return PyRes{res=":shr_digit:shr_digit(src):", err=err}; } - r: cstring; - r, err = int_itoa_cstring(src, 16, context.temp_allocator); + r: cstring + r, err = int_itoa_cstring(src, 16, context.temp_allocator) if err != nil { return PyRes{res=":shr_digit:itoa(res):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } /* dest = shl_digit(src, digits) */ @export test_shl_digit :: proc "c" (source: cstring, digits: int) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - src := &Int{}; - defer internal_destroy(src); + src := &Int{} + defer internal_destroy(src) if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":shl_digit:atoi(src):", err=err}; } if err = #force_inline internal_shl_digit(src, digits); err != nil { return PyRes{res=":shl_digit:shr_digit(src):", err=err}; } - r: cstring; - r, err = int_itoa_cstring(src, 16, context.temp_allocator); + r: cstring + r, err = int_itoa_cstring(src, 16, context.temp_allocator) if err != nil { return PyRes{res=":shl_digit:itoa(res):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } /* dest = shr(src, bits) */ @export test_shr :: proc "c" (source: cstring, bits: int) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - src := &Int{}; - defer internal_destroy(src); + src := &Int{} + defer internal_destroy(src) if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":shr:atoi(src):", err=err}; } if err = #force_inline internal_shr(src, src, bits); err != nil { return PyRes{res=":shr:shr(src, bits):", err=err}; } - r: cstring; - r, err = int_itoa_cstring(src, 16, context.temp_allocator); + r: cstring + r, err = int_itoa_cstring(src, 16, context.temp_allocator) if err != nil { return PyRes{res=":shr:itoa(res):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } /* dest = shr_signed(src, bits) */ @export test_shr_signed :: proc "c" (source: cstring, bits: int) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - src := &Int{}; - defer internal_destroy(src); + src := &Int{} + defer internal_destroy(src) if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":shr_signed:atoi(src):", err=err}; } if err = #force_inline internal_shr_signed(src, src, bits); err != nil { return PyRes{res=":shr_signed:shr_signed(src, bits):", err=err}; } - r: cstring; - r, err = int_itoa_cstring(src, 16, context.temp_allocator); + r: cstring + r, err = int_itoa_cstring(src, 16, context.temp_allocator) if err != nil { return PyRes{res=":shr_signed:itoa(res):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } /* dest = shl(src, bits) */ @export test_shl :: proc "c" (source: cstring, bits: int) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - src := &Int{}; - defer internal_destroy(src); + src := &Int{} + defer internal_destroy(src) if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":shl:atoi(src):", err=err}; } if err = #force_inline internal_shl(src, src, bits); err != nil { return PyRes{res=":shl:shl(src, bits):", err=err}; } - r: cstring; - r, err = int_itoa_cstring(src, 16, context.temp_allocator); + r: cstring + r, err = int_itoa_cstring(src, 16, context.temp_allocator) if err != nil { return PyRes{res=":shl:itoa(res):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } /* dest = factorial(n) */ @export test_factorial :: proc "c" (n: int) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - dest := &Int{}; - defer internal_destroy(dest); + dest := &Int{} + defer internal_destroy(dest) if err = #force_inline internal_int_factorial(dest, n); err != nil { return PyRes{res=":factorial:factorial(n):", err=err}; } - r: cstring; - r, err = int_itoa_cstring(dest, 16, context.temp_allocator); + r: cstring + r, err = int_itoa_cstring(dest, 16, context.temp_allocator) if err != nil { return PyRes{res=":factorial:itoa(res):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } /* dest = gcd(a, b) */ @export test_gcd :: proc "c" (a, b: cstring) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - ai, bi, dest := &Int{}, &Int{}, &Int{}; - defer internal_destroy(ai, bi, dest); + ai, bi, dest := &Int{}, &Int{}, &Int{} + defer internal_destroy(ai, bi, dest) if err = atoi(ai, string(a), 16); err != nil { return PyRes{res=":gcd:atoi(a):", err=err}; } if err = atoi(bi, string(b), 16); err != nil { return PyRes{res=":gcd:atoi(b):", err=err}; } if err = #force_inline internal_int_gcd_lcm(dest, nil, ai, bi); err != nil { return PyRes{res=":gcd:gcd(a, b):", err=err}; } - r: cstring; - r, err = int_itoa_cstring(dest, 16, context.temp_allocator); + r: cstring + r, err = int_itoa_cstring(dest, 16, context.temp_allocator) if err != nil { return PyRes{res=":gcd:itoa(res):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } /* dest = lcm(a, b) */ @export test_lcm :: proc "c" (a, b: cstring) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - ai, bi, dest := &Int{}, &Int{}, &Int{}; - defer internal_destroy(ai, bi, dest); + ai, bi, dest := &Int{}, &Int{}, &Int{} + defer internal_destroy(ai, bi, dest) if err = atoi(ai, string(a), 16); err != nil { return PyRes{res=":lcm:atoi(a):", err=err}; } if err = atoi(bi, string(b), 16); err != nil { return PyRes{res=":lcm:atoi(b):", err=err}; } if err = #force_inline internal_int_gcd_lcm(nil, dest, ai, bi); err != nil { return PyRes{res=":lcm:lcm(a, b):", err=err}; } - r: cstring; - r, err = int_itoa_cstring(dest, 16, context.temp_allocator); + r: cstring + r, err = int_itoa_cstring(dest, 16, context.temp_allocator) if err != nil { return PyRes{res=":lcm:itoa(res):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } /* dest = lcm(a, b) */ @export test_is_square :: proc "c" (a: cstring) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; - square: bool; + context = runtime.default_context() + err: Error + square: bool - ai := &Int{}; - defer internal_destroy(ai); + ai := &Int{} + defer internal_destroy(ai) if err = atoi(ai, string(a), 16); err != nil { return PyRes{res=":is_square:atoi(a):", err=err}; } if square, err = #force_inline internal_int_is_square(ai); err != nil { return PyRes{res=":is_square:is_square(a):", err=err}; } if square { - return PyRes{"True", nil}; + return PyRes{"True", nil} } - return PyRes{"False", nil}; + return PyRes{"False", nil} }
\ No newline at end of file diff --git a/core/math/big/tune.odin b/core/math/big/tune.odin index 700a5e74a..c34f73b37 100644 --- a/core/math/big/tune.odin +++ b/core/math/big/tune.odin @@ -24,58 +24,58 @@ Category :: enum { sqr, bitfield_extract, rm_trials, -}; +} Event :: struct { ticks: time.Duration, count: int, cycles: u64, } -Timings := [Category]Event{}; +Timings := [Category]Event{} print_timings :: proc() { duration :: proc(d: time.Duration) -> (res: string) { switch { case d < time.Microsecond: - return fmt.tprintf("%v ns", time.duration_nanoseconds(d)); + return fmt.tprintf("%v ns", time.duration_nanoseconds(d)) case d < time.Millisecond: - return fmt.tprintf("%v µs", time.duration_microseconds(d)); + return fmt.tprintf("%v µs", time.duration_microseconds(d)) case: - return fmt.tprintf("%v ms", time.duration_milliseconds(d)); + return fmt.tprintf("%v ms", time.duration_milliseconds(d)) } } for v in Timings { if v.count > 0 { - fmt.println("\nTimings:"); - break; + fmt.println("\nTimings:") + break } } for v, i in Timings { if v.count > 0 { - avg_ticks := time.Duration(f64(v.ticks) / f64(v.count)); - avg_cycles := f64(v.cycles) / f64(v.count); + avg_ticks := time.Duration(f64(v.ticks) / f64(v.count)) + avg_cycles := f64(v.cycles) / f64(v.count) - fmt.printf("\t%v: %s / %v cycles (avg), %s / %v cycles (total, %v calls)\n", i, duration(avg_ticks), avg_cycles, duration(v.ticks), v.cycles, v.count); + fmt.printf("\t%v: %s / %v cycles (avg), %s / %v cycles (total, %v calls)\n", i, duration(avg_ticks), avg_cycles, duration(v.ticks), v.cycles, v.count) } } } @(deferred_in_out=_SCOPE_END) SCOPED_TIMING :: #force_inline proc(c: Category) -> (ticks: time.Tick, cycles: u64) { - cycles = time.read_cycle_counter(); - ticks = time.tick_now(); - return; + cycles = time.read_cycle_counter() + ticks = time.tick_now() + return } _SCOPE_END :: #force_inline proc(c: Category, ticks: time.Tick, cycles: u64) { - cycles_now := time.read_cycle_counter(); - ticks_now := time.tick_now(); + cycles_now := time.read_cycle_counter() + ticks_now := time.tick_now() - Timings[c].ticks = time.tick_diff(ticks, ticks_now); - Timings[c].cycles = cycles_now - cycles; - Timings[c].count += 1; + Timings[c].ticks = time.tick_diff(ticks, ticks_now) + Timings[c].cycles = cycles_now - cycles + Timings[c].count += 1 } SCOPED_COUNT_ADD :: #force_inline proc(c: Category, count: int) { - Timings[c].count += count; + Timings[c].count += count } diff --git a/core/math/bits/bits.odin b/core/math/bits/bits.odin index 91b773504..c65c2fa2b 100644 --- a/core/math/bits/bits.odin +++ b/core/math/bits/bits.odin @@ -2,66 +2,66 @@ package math_bits import "core:intrinsics" -U8_MIN :: 0; -U16_MIN :: 0; -U32_MIN :: 0; -U64_MIN :: 0; +U8_MIN :: 0 +U16_MIN :: 0 +U32_MIN :: 0 +U64_MIN :: 0 -U8_MAX :: 1 << 8 - 1; -U16_MAX :: 1 << 16 - 1; -U32_MAX :: 1 << 32 - 1; -U64_MAX :: 1 << 64 - 1; +U8_MAX :: 1 << 8 - 1 +U16_MAX :: 1 << 16 - 1 +U32_MAX :: 1 << 32 - 1 +U64_MAX :: 1 << 64 - 1 -I8_MIN :: - 1 << 7; -I16_MIN :: - 1 << 15; -I32_MIN :: - 1 << 31; -I64_MIN :: - 1 << 63; +I8_MIN :: - 1 << 7 +I16_MIN :: - 1 << 15 +I32_MIN :: - 1 << 31 +I64_MIN :: - 1 << 63 -I8_MAX :: 1 << 7 - 1; -I16_MAX :: 1 << 15 - 1; -I32_MAX :: 1 << 31 - 1; -I64_MAX :: 1 << 63 - 1; +I8_MAX :: 1 << 7 - 1 +I16_MAX :: 1 << 15 - 1 +I32_MAX :: 1 << 31 - 1 +I64_MAX :: 1 << 63 - 1 -count_ones :: intrinsics.count_ones; -count_zeros :: intrinsics.count_zeros; -trailing_zeros :: intrinsics.count_trailing_zeros; -leading_zeros :: intrinsics.count_leading_zeros; -count_trailing_zeros :: intrinsics.count_trailing_zeros; -count_leading_zeros :: intrinsics.count_leading_zeros; -reverse_bits :: intrinsics.reverse_bits; -byte_swap :: intrinsics.byte_swap; +count_ones :: intrinsics.count_ones +count_zeros :: intrinsics.count_zeros +trailing_zeros :: intrinsics.count_trailing_zeros +leading_zeros :: intrinsics.count_leading_zeros +count_trailing_zeros :: intrinsics.count_trailing_zeros +count_leading_zeros :: intrinsics.count_leading_zeros +reverse_bits :: intrinsics.reverse_bits +byte_swap :: intrinsics.byte_swap -overflowing_add :: intrinsics.overflow_add; -overflowing_sub :: intrinsics.overflow_sub; -overflowing_mul :: intrinsics.overflow_mul; +overflowing_add :: intrinsics.overflow_add +overflowing_sub :: intrinsics.overflow_sub +overflowing_mul :: intrinsics.overflow_mul rotate_left8 :: proc(x: u8, k: int) -> u8 { - n :: 8; - s := uint(k) & (n-1); - return x <<s | x>>(n-s); + n :: 8 + s := uint(k) & (n-1) + return x <<s | x>>(n-s) } rotate_left16 :: proc(x: u16, k: int) -> u16 { - n :: 16; - s := uint(k) & (n-1); - return x <<s | x>>(n-s); + n :: 16 + s := uint(k) & (n-1) + return x <<s | x>>(n-s) } rotate_left32 :: proc(x: u32, k: int) -> u32 { - n :: 32; - s := uint(k) & (n-1); - return x <<s | x>>(n-s); + n :: 32 + s := uint(k) & (n-1) + return x <<s | x>>(n-s) } rotate_left64 :: proc(x: u64, k: int) -> u64 { - n :: 64; - s := uint(k) & (n-1); - return x <<s | x>>(n-s); + n :: 64 + s := uint(k) & (n-1) + return x <<s | x>>(n-s) } rotate_left :: proc(x: uint, k: int) -> uint { - n :: 8*size_of(uint); - s := uint(k) & (n-1); - return x <<s | x>>(n-s); + n :: 8*size_of(uint) + s := uint(k) & (n-1) + return x <<s | x>>(n-s) } from_be_u8 :: proc(i: u8) -> u8 { return i; } @@ -92,205 +92,205 @@ to_le_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == "little" { return i; } len_u8 :: proc(x: u8) -> int { - return int(len_u8_table[x]); + return int(len_u8_table[x]) } len_u16 :: proc(x: u16) -> (n: int) { - x := x; + x := x if x >= 1<<8 { - x >>= 8; - n = 8; + x >>= 8 + n = 8 } - return n + int(len_u8_table[x]); + return n + int(len_u8_table[x]) } len_u32 :: proc(x: u32) -> (n: int) { - x := x; + x := x if x >= 1<<16 { - x >>= 16; - n = 16; + x >>= 16 + n = 16 } if x >= 1<<8 { - x >>= 8; - n += 8; + x >>= 8 + n += 8 } - return n + int(len_u8_table[x]); + return n + int(len_u8_table[x]) } len_u64 :: proc(x: u64) -> (n: int) { - x := x; + x := x if x >= 1<<32 { - x >>= 32; - n = 32; + x >>= 32 + n = 32 } if x >= 1<<16 { - x >>= 16; - n += 16; + x >>= 16 + n += 16 } if x >= 1<<8 { - x >>= 8; - n += 8; + x >>= 8 + n += 8 } - return n + int(len_u8_table[x]); + return n + int(len_u8_table[x]) } len_uint :: proc(x: uint) -> (n: int) { when size_of(uint) == size_of(u64) { - return len_u64(u64(x)); + return len_u64(u64(x)) } else { - return len_u32(u32(x)); + return len_u32(u32(x)) } } // returns the minimum number of bits required to represent x -len :: proc{len_u8, len_u16, len_u32, len_u64, len_uint}; +len :: proc{len_u8, len_u16, len_u32, len_u64, len_uint} add_u32 :: proc(x, y, carry: u32) -> (sum, carry_out: u32) { - yc := y + carry; - sum = x + yc; + yc := y + carry + sum = x + yc if sum < x || yc < y { - carry_out = 1; + carry_out = 1 } - return; + return } add_u64 :: proc(x, y, carry: u64) -> (sum, carry_out: u64) { - yc := y + carry; - sum = x + yc; + yc := y + carry + sum = x + yc if sum < x || yc < y { - carry_out = 1; + carry_out = 1 } - return; + return } add_uint :: proc(x, y, carry: uint) -> (sum, carry_out: uint) { - yc := y + carry; - sum = x + yc; + yc := y + carry + sum = x + yc if sum < x || yc < y { - carry_out = 1; + carry_out = 1 } - return; + return } -add :: proc{add_u32, add_u64, add_uint}; +add :: proc{add_u32, add_u64, add_uint} sub_u32 :: proc(x, y, borrow: u32) -> (diff, borrow_out: u32) { - yb := y + borrow; - diff = x - yb; + yb := y + borrow + diff = x - yb if diff > x || yb < y { - borrow_out = 1; + borrow_out = 1 } - return; + return } sub_u64 :: proc(x, y, borrow: u64) -> (diff, borrow_out: u64) { - yb := y + borrow; - diff = x - yb; + yb := y + borrow + diff = x - yb if diff > x || yb < y { - borrow_out = 1; + borrow_out = 1 } - return; + return } sub_uint :: proc(x, y, borrow: uint) -> (diff, borrow_out: uint) { - yb := y + borrow; - diff = x - yb; + yb := y + borrow + diff = x - yb if diff > x || yb < y { - borrow_out = 1; + borrow_out = 1 } - return; + return } -sub :: proc{sub_u32, sub_u64, sub_uint}; +sub :: proc{sub_u32, sub_u64, sub_uint} mul_u32 :: proc(x, y: u32) -> (hi, lo: u32) { - z := u64(x) * u64(y); - hi, lo = u32(z>>32), u32(z); - return; + z := u64(x) * u64(y) + hi, lo = u32(z>>32), u32(z) + return } mul_u64 :: proc(x, y: u64) -> (hi, lo: u64) { - mask :: 1<<32 - 1; + mask :: 1<<32 - 1 - x0, x1 := x & mask, x >> 32; - y0, y1 := y & mask, y >> 32; + x0, x1 := x & mask, x >> 32 + y0, y1 := y & mask, y >> 32 - w0 := x0 * y0; - t := x1*y0 + w0>>32; + w0 := x0 * y0 + t := x1*y0 + w0>>32 - w1, w2 := t & mask, t >> 32; - w1 += x0 * y1; - hi = x1*y1 + w2 + w1>>32; - lo = x * y; - return; + w1, w2 := t & mask, t >> 32 + w1 += x0 * y1 + hi = x1*y1 + w2 + w1>>32 + lo = x * y + return } mul_uint :: proc(x, y: uint) -> (hi, lo: uint) { when size_of(uint) == size_of(u32) { - a, b := mul_u32(u32(x), u32(y)); + a, b := mul_u32(u32(x), u32(y)) } else { #assert(size_of(uint) == size_of(u64)); - a, b := mul_u64(u64(x), u64(y)); + a, b := mul_u64(u64(x), u64(y)) } - return uint(a), uint(b); + return uint(a), uint(b) } -mul :: proc{mul_u32, mul_u64, mul_uint}; +mul :: proc{mul_u32, mul_u64, mul_uint} div_u32 :: proc(hi, lo, y: u32) -> (quo, rem: u32) { - assert(y != 0 && y <= hi); - z := u64(hi)<<32 | u64(lo); - quo, rem = u32(z/u64(y)), u32(z%u64(y)); - return; + assert(y != 0 && y <= hi) + z := u64(hi)<<32 | u64(lo) + quo, rem = u32(z/u64(y)), u32(z%u64(y)) + return } div_u64 :: proc(hi, lo, y: u64) -> (quo, rem: u64) { - y := y; - two32 :: 1 << 32; - mask32 :: two32 - 1; + y := y + two32 :: 1 << 32 + mask32 :: two32 - 1 if y == 0 { - panic("divide error"); + panic("divide error") } if y <= hi { - panic("overflow error"); + panic("overflow error") } - s := uint(count_leading_zeros(y)); - y <<= s; + s := uint(count_leading_zeros(y)) + y <<= s - yn1 := y >> 32; - yn0 := y & mask32; - un32 := hi<<s | lo>>(64-s); - un10 := lo << s; - un1 := un10 >> 32; - un0 := un10 & mask32; - q1 := un32 / yn1; - rhat := un32 - q1*yn1; + yn1 := y >> 32 + yn0 := y & mask32 + un32 := hi<<s | lo>>(64-s) + un10 := lo << s + un1 := un10 >> 32 + un0 := un10 & mask32 + q1 := un32 / yn1 + rhat := un32 - q1*yn1 for q1 >= two32 || q1*yn0 > two32*rhat+un1 { - q1 -= 1; - rhat += yn1; + q1 -= 1 + rhat += yn1 if rhat >= two32 { - break; + break } } - un21 := un32*two32 + un1 - q1*y; - q0 := un21 / yn1; - rhat = un21 - q0*yn1; + un21 := un32*two32 + un1 - q1*y + q0 := un21 / yn1 + rhat = un21 - q0*yn1 for q0 >= two32 || q0*yn0 > two32*rhat+un0 { - q0 -= 1; - rhat += yn1; + q0 -= 1 + rhat += yn1 if rhat >= two32 { - break; + break } } - return q1*two32 + q0, (un21*two32 + un0 - q0*y) >> s; + return q1*two32 + q0, (un21*two32 + un0 - q0*y) >> s } div_uint :: proc(hi, lo, y: uint) -> (quo, rem: uint) { when size_of(uint) == size_of(u32) { - a, b := div_u32(u32(hi), u32(lo), u32(y)); + a, b := div_u32(u32(hi), u32(lo), u32(y)) } else { #assert(size_of(uint) == size_of(u64)); - a, b := div_u64(u64(hi), u64(lo), u64(y)); + a, b := div_u64(u64(hi), u64(lo), u64(y)) } - return uint(a), uint(b); + return uint(a), uint(b) } -div :: proc{div_u32, div_u64, div_uint}; +div :: proc{div_u32, div_u64, div_uint} @@ -311,7 +311,7 @@ is_power_of_two :: proc{ is_power_of_two_u32, is_power_of_two_i32, is_power_of_two_u64, is_power_of_two_i64, is_power_of_two_uint, is_power_of_two_int, -}; +} @private @@ -325,7 +325,7 @@ len_u8_table := [256]u8{ 32..<64 = 6, 64..<128 = 7, 128..<256 = 8, -}; +} bitfield_extract_u8 :: proc(value: u8, offset, bits: uint) -> u8 { return (value >> offset) & u8(1<<bits - 1); } @@ -336,40 +336,40 @@ bitfield_extract_u128 :: proc(value: u128, offset, bits: uint) -> u128 { return bitfield_extract_uint :: proc(value: uint, offset, bits: uint) -> uint { return (value >> offset) & uint(1<<bits - 1); } bitfield_extract_i8 :: proc(value: i8, offset, bits: uint) -> i8 { - v := (u8(value) >> offset) & u8(1<<bits - 1); - m := u8(1<<(bits-1)); - r := (v~m) - m; - return i8(r); + v := (u8(value) >> offset) & u8(1<<bits - 1) + m := u8(1<<(bits-1)) + r := (v~m) - m + return i8(r) } bitfield_extract_i16 :: proc(value: i16, offset, bits: uint) -> i16 { - v := (u16(value) >> offset) & u16(1<<bits - 1); - m := u16(1<<(bits-1)); - r := (v~m) - m; - return i16(r); + v := (u16(value) >> offset) & u16(1<<bits - 1) + m := u16(1<<(bits-1)) + r := (v~m) - m + return i16(r) } bitfield_extract_i32 :: proc(value: i32, offset, bits: uint) -> i32 { - v := (u32(value) >> offset) & u32(1<<bits - 1); - m := u32(1<<(bits-1)); - r := (v~m) - m; - return i32(r); + v := (u32(value) >> offset) & u32(1<<bits - 1) + m := u32(1<<(bits-1)) + r := (v~m) - m + return i32(r) } bitfield_extract_i64 :: proc(value: i64, offset, bits: uint) -> i64 { - v := (u64(value) >> offset) & u64(1<<bits - 1); - m := u64(1<<(bits-1)); - r := (v~m) - m; - return i64(r); + v := (u64(value) >> offset) & u64(1<<bits - 1) + m := u64(1<<(bits-1)) + r := (v~m) - m + return i64(r) } bitfield_extract_i128 :: proc(value: i128, offset, bits: uint) -> i128 { - v := (u128(value) >> offset) & u128(1<<bits - 1); - m := u128(1<<(bits-1)); - r := (v~m) - m; - return i128(r); + v := (u128(value) >> offset) & u128(1<<bits - 1) + m := u128(1<<(bits-1)) + r := (v~m) - m + return i128(r) } bitfield_extract_int :: proc(value: int, offset, bits: uint) -> int { - v := (uint(value) >> offset) & uint(1<<bits - 1); - m := uint(1<<(bits-1)); - r := (v~m) - m; - return int(r); + v := (uint(value) >> offset) & uint(1<<bits - 1) + m := uint(1<<(bits-1)) + r := (v~m) - m + return int(r) } @@ -386,57 +386,57 @@ bitfield_extract :: proc{ bitfield_extract_i64, bitfield_extract_i128, bitfield_extract_int, -}; +} bitfield_insert_u8 :: proc(base, insert: u8, offset, bits: uint) -> u8 { - mask := u8(1<<bits - 1); - return (base &~ (mask<<offset)) | ((insert&mask) << offset); + mask := u8(1<<bits - 1) + return (base &~ (mask<<offset)) | ((insert&mask) << offset) } bitfield_insert_u16 :: proc(base, insert: u16, offset, bits: uint) -> u16 { - mask := u16(1<<bits - 1); - return (base &~ (mask<<offset)) | ((insert&mask) << offset); + mask := u16(1<<bits - 1) + return (base &~ (mask<<offset)) | ((insert&mask) << offset) } bitfield_insert_u32 :: proc(base, insert: u32, offset, bits: uint) -> u32 { - mask := u32(1<<bits - 1); - return (base &~ (mask<<offset)) | ((insert&mask) << offset); + mask := u32(1<<bits - 1) + return (base &~ (mask<<offset)) | ((insert&mask) << offset) } bitfield_insert_u64 :: proc(base, insert: u64, offset, bits: uint) -> u64 { - mask := u64(1<<bits - 1); - return (base &~ (mask<<offset)) | ((insert&mask) << offset); + mask := u64(1<<bits - 1) + return (base &~ (mask<<offset)) | ((insert&mask) << offset) } bitfield_insert_u128 :: proc(base, insert: u128, offset, bits: uint) -> u128 { - mask := u128(1<<bits - 1); - return (base &~ (mask<<offset)) | ((insert&mask) << offset); + mask := u128(1<<bits - 1) + return (base &~ (mask<<offset)) | ((insert&mask) << offset) } bitfield_insert_uint :: proc(base, insert: uint, offset, bits: uint) -> uint { - mask := uint(1<<bits - 1); - return (base &~ (mask<<offset)) | ((insert&mask) << offset); + mask := uint(1<<bits - 1) + return (base &~ (mask<<offset)) | ((insert&mask) << offset) } bitfield_insert_i8 :: proc(base, insert: i8, offset, bits: uint) -> i8 { - mask := i8(1<<bits - 1); - return (base &~ (mask<<offset)) | ((insert&mask) << offset); + mask := i8(1<<bits - 1) + return (base &~ (mask<<offset)) | ((insert&mask) << offset) } bitfield_insert_i16 :: proc(base, insert: i16, offset, bits: uint) -> i16 { - mask := i16(1<<bits - 1); - return (base &~ (mask<<offset)) | ((insert&mask) << offset); + mask := i16(1<<bits - 1) + return (base &~ (mask<<offset)) | ((insert&mask) << offset) } bitfield_insert_i32 :: proc(base, insert: i32, offset, bits: uint) -> i32 { - mask := i32(1<<bits - 1); - return (base &~ (mask<<offset)) | ((insert&mask) << offset); + mask := i32(1<<bits - 1) + return (base &~ (mask<<offset)) | ((insert&mask) << offset) } bitfield_insert_i64 :: proc(base, insert: i64, offset, bits: uint) -> i64 { - mask := i64(1<<bits - 1); - return (base &~ (mask<<offset)) | ((insert&mask) << offset); + mask := i64(1<<bits - 1) + return (base &~ (mask<<offset)) | ((insert&mask) << offset) } bitfield_insert_i128 :: proc(base, insert: i128, offset, bits: uint) -> i128 { - mask := i128(1<<bits - 1); - return (base &~ (mask<<offset)) | ((insert&mask) << offset); + mask := i128(1<<bits - 1) + return (base &~ (mask<<offset)) | ((insert&mask) << offset) } bitfield_insert_int :: proc(base, insert: int, offset, bits: uint) -> int { - mask := int(1<<bits - 1); - return (base &~ (mask<<offset)) | ((insert&mask) << offset); + mask := int(1<<bits - 1) + return (base &~ (mask<<offset)) | ((insert&mask) << offset) } bitfield_insert :: proc{ @@ -452,4 +452,4 @@ bitfield_insert :: proc{ bitfield_insert_i64, bitfield_insert_i128, bitfield_insert_int, -}; +} diff --git a/core/math/fixed/fixed.odin b/core/math/fixed/fixed.odin index 6e4709af7..ef97b66d3 100644 --- a/core/math/fixed/fixed.odin +++ b/core/math/fixed/fixed.odin @@ -4,7 +4,7 @@ import "core:math" import "core:strconv" import "core:intrinsics" -_ :: intrinsics; +_ :: intrinsics Fixed :: struct($Backing: typeid, $Fraction_Width: uint) where @@ -14,120 +14,120 @@ Fixed :: struct($Backing: typeid, $Fraction_Width: uint) i: Backing, } -Fixed4_4 :: distinct Fixed(i8, 4); -Fixed5_3 :: distinct Fixed(i8, 3); -Fixed6_2 :: distinct Fixed(i8, 2); -Fixed7_1 :: distinct Fixed(i8, 1); +Fixed4_4 :: distinct Fixed(i8, 4) +Fixed5_3 :: distinct Fixed(i8, 3) +Fixed6_2 :: distinct Fixed(i8, 2) +Fixed7_1 :: distinct Fixed(i8, 1) -Fixed8_8 :: distinct Fixed(i16, 8); -Fixed13_3 :: distinct Fixed(i16, 3); +Fixed8_8 :: distinct Fixed(i16, 8) +Fixed13_3 :: distinct Fixed(i16, 3) -Fixed16_16 :: distinct Fixed(i32, 16); -Fixed26_6 :: distinct Fixed(i32, 6); +Fixed16_16 :: distinct Fixed(i32, 16) +Fixed26_6 :: distinct Fixed(i32, 6) -Fixed32_32 :: distinct Fixed(i64, 32); -Fixed52_12 :: distinct Fixed(i64, 12); +Fixed32_32 :: distinct Fixed(i64, 32) +Fixed52_12 :: distinct Fixed(i64, 12) init_from_f64 :: proc(x: ^$T/Fixed($Backing, $Fraction_Width), val: f64) { - i, f := math.modf(val); - x.i = Backing(f * (1<<Fraction_Width)); - x.i &= 1<<Fraction_Width - 1; - x.i |= Backing(i) << Fraction_Width; + i, f := math.modf(val) + x.i = Backing(f * (1<<Fraction_Width)) + x.i &= 1<<Fraction_Width - 1 + x.i |= Backing(i) << Fraction_Width } init_from_parts :: proc(x: ^$T/Fixed($Backing, $Fraction_Width), integer, fraction: Backing) { - i, f := math.modf(val); - x.i = fraction; - x.i &= 1<<Fraction_Width - 1; - x.i |= integer; + i, f := math.modf(val) + x.i = fraction + x.i &= 1<<Fraction_Width - 1 + x.i |= integer } to_f64 :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> f64 { - res := f64(x.i >> Fraction_Width); - res += f64(x.i & (1<<Fraction_Width-1)) / f64(1<<Fraction_Width); - return res; + res := f64(x.i >> Fraction_Width) + res += f64(x.i & (1<<Fraction_Width-1)) / f64(1<<Fraction_Width) + return res } add :: proc(x, y: $T/Fixed) -> T { - return {x.i + y.i}; + return {x.i + y.i} } sub :: proc(x, y: $T/Fixed) -> T { - return {x.i - y.i}; + return {x.i - y.i} } mul :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) { - z.i = intrinsics.fixed_point_mul(x.i, y.i, Fraction_Width); - return; + z.i = intrinsics.fixed_point_mul(x.i, y.i, Fraction_Width) + return } mul_sat :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) { - z.i = intrinsics.fixed_point_mul_sat(x.i, y.i, Fraction_Width); - return; + z.i = intrinsics.fixed_point_mul_sat(x.i, y.i, Fraction_Width) + return } div :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) { - z.i = intrinsics.fixed_point_div(x.i, y.i, Fraction_Width); - return; + z.i = intrinsics.fixed_point_div(x.i, y.i, Fraction_Width) + return } div_sat :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) { - z.i = intrinsics.fixed_point_div_sat(x.i, y.i, Fraction_Width); - return; + z.i = intrinsics.fixed_point_div_sat(x.i, y.i, Fraction_Width) + return } floor :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing { - return x.i >> Fraction_Width; + return x.i >> Fraction_Width } ceil :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing { - Integer :: 8*size_of(Backing) - Fraction_Width; - return (x.i + (1 << Integer-1)) >> Fraction_Width; + Integer :: 8*size_of(Backing) - Fraction_Width + return (x.i + (1 << Integer-1)) >> Fraction_Width } round :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing { - Integer :: 8*size_of(Backing) - Fraction_Width; - return (x.i + (1 << (Integer - 1))) >> Fraction_Width; + Integer :: 8*size_of(Backing) - Fraction_Width + return (x.i + (1 << (Integer - 1))) >> Fraction_Width } append :: proc(dst: []byte, x: $T/Fixed($Backing, $Fraction_Width)) -> string { - x := x; - buf: [48]byte; - i := 0; + x := x + buf: [48]byte + i := 0 if x.i < 0 { - buf[i] = '-'; - i += 1; - x.i = -x.i; + buf[i] = '-' + i += 1 + x.i = -x.i } - integer := x.i >> Fraction_Width; - fraction := x.i & (1<<Fraction_Width - 1); + integer := x.i >> Fraction_Width + fraction := x.i & (1<<Fraction_Width - 1) - s := strconv.append_uint(buf[i:], u64(integer), 10); - i += len(s); + s := strconv.append_uint(buf[i:], u64(integer), 10) + i += len(s) if fraction != 0 { - buf[i] = '.'; - i += 1; + buf[i] = '.' + i += 1 for fraction > 0 { - fraction *= 10; - buf[i] = byte('0' + (fraction>>Fraction_Width)); - i += 1; - fraction &= 1<<Fraction_Width - 1; + fraction *= 10 + buf[i] = byte('0' + (fraction>>Fraction_Width)) + i += 1 + fraction &= 1<<Fraction_Width - 1 } } - n := copy(dst, buf[:i]); - return string(dst[:i]); + n := copy(dst, buf[:i]) + return string(dst[:i]) } to_string :: proc(x: $T/Fixed($Backing, $Fraction_Width), allocator := context.allocator) -> string { - buf: [48]byte; - s := append(buf[:], x); - str := make([]byte, len(s), allocator); - copy(str, s); - return string(str); + buf: [48]byte + s := append(buf[:], x) + str := make([]byte, len(s), allocator) + copy(str, s) + return string(str) } diff --git a/core/math/linalg/extended.odin b/core/math/linalg/extended.odin index 373a4e4ce..8f7b2dd1e 100644 --- a/core/math/linalg/extended.odin +++ b/core/math/linalg/extended.odin @@ -6,476 +6,476 @@ import "core:math" radians :: proc(degrees: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = degrees * RAD_PER_DEG; + out[i] = degrees * RAD_PER_DEG } } else { - out = degrees * RAD_PER_DEG; + out = degrees * RAD_PER_DEG } - return; + return } degrees :: proc(radians: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = radians * DEG_PER_RAD; + out[i] = radians * DEG_PER_RAD } } else { - out = radians * DEG_PER_RAD; + out = radians * DEG_PER_RAD } - return; + return } min_double :: proc(a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = builtin.min(a[i], b[i]); + out[i] = builtin.min(a[i], b[i]) } } else { - out = builtin.min(a, b); + out = builtin.min(a, b) } - return; + return } min_single :: proc(a: $T) -> (out: ELEM_TYPE(T)) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { - N :: len(T); + N :: len(T) when N == 1 { - out = a[0]; + out = a[0] } else when N == 2 { - out = builtin.min(a[0], a[1]); + out = builtin.min(a[0], a[1]) } else { - out = builtin.min(a[0], a[1]); + out = builtin.min(a[0], a[1]) for i in 2..<N { - out = builtin.min(out, a[i]); + out = builtin.min(out, a[i]) } } } else { - out = a; + out = a } - return; + return } min_triple :: proc(a, b, c: $T) -> T where IS_NUMERIC(ELEM_TYPE(T)) { - return min_double(a, min_double(b, c)); + return min_double(a, min_double(b, c)) } -min :: proc{min_single, min_double, min_triple}; +min :: proc{min_single, min_double, min_triple} max_double :: proc(a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = builtin.max(a[i], b[i]); + out[i] = builtin.max(a[i], b[i]) } } else { - out = builtin.max(a, b); + out = builtin.max(a, b) } - return; + return } max_single :: proc(a: $T) -> (out: ELEM_TYPE(T)) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { - N :: len(T); + N :: len(T) when N == 1 { - out = a[0]; + out = a[0] } else when N == 2 { - out = builtin.max(a[0], a[1]); + out = builtin.max(a[0], a[1]) } else when N == 3 { - out = builtin.max(a[0], a[1], a[3]); + out = builtin.max(a[0], a[1], a[3]) }else { - out = builtin.max(a[0], a[1]); + out = builtin.max(a[0], a[1]) for i in 2..<N { - out = builtin.max(out, a[i]); + out = builtin.max(out, a[i]) } } } else { - out = a; + out = a } - return; + return } max_triple :: proc(a, b, c: $T) -> T where IS_NUMERIC(ELEM_TYPE(T)) { - return max_double(a, max_double(b, c)); + return max_double(a, max_double(b, c)) } -max :: proc{max_single, max_double, max_triple}; +max :: proc{max_single, max_double, max_triple} abs :: proc(a: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = builtin.abs(a[i]); + out[i] = builtin.abs(a[i]) } } else { - out = builtin.abs(a); + out = builtin.abs(a) } - return; + return } sign :: proc(a: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = #force_inline math.sign(a[i]); + out[i] = #force_inline math.sign(a[i]) } } else { - out = #force_inline math.sign(a); + out = #force_inline math.sign(a) } - return; + return } clamp :: proc(x, a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = builtin.clamp(x[i], a[i], b[i]); + out[i] = builtin.clamp(x[i], a[i], b[i]) } } else { - out = builtin.clamp(x, a, b); + out = builtin.clamp(x, a, b) } - return; + return } saturate :: proc(x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) { - return clamp(x, 0.0, 1.0); + return clamp(x, 0.0, 1.0) } lerp :: proc(a, b, t: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = a[i]*(1-t[i]) + b[i]*t[i]; + out[i] = a[i]*(1-t[i]) + b[i]*t[i] } } else { - out = a * (1.0 - t) + b * t; + out = a * (1.0 - t) + b * t } - return; + return } mix :: proc(a, b, t: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = a[i]*(1-t[i]) + b[i]*t[i]; + out[i] = a[i]*(1-t[i]) + b[i]*t[i] } } else { - out = a * (1.0 - t) + b * t; + out = a * (1.0 - t) + b * t } - return; + return } unlerp :: proc(a, b, x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) { - return (x - a) / (b - a); + return (x - a) / (b - a) } step :: proc(e, x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = x[i] < e[i] ? 0.0 : 1.0; + out[i] = x[i] < e[i] ? 0.0 : 1.0 } } else { - out = x < e ? 0.0 : 1.0; + out = x < e ? 0.0 : 1.0 } - return; + return } smoothstep :: proc(e0, e1, x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) { - t := saturate(unlerp(e0, e1, x)); - return t * t * (3.0 - 2.0 * t); + t := saturate(unlerp(e0, e1, x)) + return t * t * (3.0 - 2.0 * t) } smootherstep :: proc(e0, e1, x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) { - t := saturate(unlerp(e0, e1, x)); - return t * t * t * (t * (6*t - 15) + 10); + t := saturate(unlerp(e0, e1, x)) + return t * t * t * (t * (6*t - 15) + 10) } sqrt :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = math.sqrt(x[i]); + out[i] = math.sqrt(x[i]) } } else { - out = math.sqrt(x); + out = math.sqrt(x) } - return; + return } inverse_sqrt :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = 1.0/math.sqrt(x[i]); + out[i] = 1.0/math.sqrt(x[i]) } } else { - out = 1.0/math.sqrt(x); + out = 1.0/math.sqrt(x) } - return; + return } cos :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = math.cos(x[i]); + out[i] = math.cos(x[i]) } } else { - out = math.cos(x); + out = math.cos(x) } - return; + return } sin :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = math.sin(x[i]); + out[i] = math.sin(x[i]) } } else { - out = math.sin(x); + out = math.sin(x) } - return; + return } tan :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = math.tan(x[i]); + out[i] = math.tan(x[i]) } } else { - out = math.tan(x); + out = math.tan(x) } - return; + return } acos :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = math.acos(x[i]); + out[i] = math.acos(x[i]) } } else { - out = math.acos(x); + out = math.acos(x) } - return; + return } asin :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = math.asin(x[i]); + out[i] = math.asin(x[i]) } } else { - out = math.asin(x); + out = math.asin(x) } - return; + return } atan :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = math.atan(x[i]); + out[i] = math.atan(x[i]) } } else { - out = math.atan(x); + out = math.atan(x) } - return; + return } atan2 :: proc(y, x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = math.atan2(y[i], x[i]); + out[i] = math.atan2(y[i], x[i]) } } else { - out = math.atan2(y, x); + out = math.atan2(y, x) } - return; + return } ln :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = math.ln(x[i]); + out[i] = math.ln(x[i]) } } else { - out = math.ln(x); + out = math.ln(x) } - return; + return } log2 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = INVLN2 * math.ln(x[i]); + out[i] = INVLN2 * math.ln(x[i]) } } else { - out = INVLN2 * math.ln(x); + out = INVLN2 * math.ln(x) } - return; + return } log10 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = INVLN10 * math.ln(x[i]); + out[i] = INVLN10 * math.ln(x[i]) } } else { - out = INVLN10 * math.ln(x); + out = INVLN10 * math.ln(x) } - return; + return } log :: proc(x, b: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = math.ln(x[i]) / math.ln(cast(ELEM_TYPE(T))b[i]); + out[i] = math.ln(x[i]) / math.ln(cast(ELEM_TYPE(T))b[i]) } } else { - out = INVLN10 * math.ln(x) / math.ln(cast(ELEM_TYPE(T))b); + out = INVLN10 * math.ln(x) / math.ln(cast(ELEM_TYPE(T))b) } - return; + return } exp :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = math.exp(x[i]); + out[i] = math.exp(x[i]) } } else { - out = math.exp(x); + out = math.exp(x) } - return; + return } exp2 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = math.exp(LN2 * x[i]); + out[i] = math.exp(LN2 * x[i]) } } else { - out = math.exp(LN2 * x); + out = math.exp(LN2 * x) } - return; + return } exp10 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = math.exp(LN10 * x[i]); + out[i] = math.exp(LN10 * x[i]) } } else { - out = math.exp(LN10 * x); + out = math.exp(LN10 * x) } - return; + return } pow :: proc(x, e: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = math.pow(x[i], e[i]); + out[i] = math.pow(x[i], e[i]) } } else { - out = math.pow(x, e); + out = math.pow(x, e) } - return; + return } ceil :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = #force_inline math.ceil(x[i]); + out[i] = #force_inline math.ceil(x[i]) } } else { - out = #force_inline math.ceil(x); + out = #force_inline math.ceil(x) } - return; + return } floor :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = #force_inline math.floor(x[i]); + out[i] = #force_inline math.floor(x[i]) } } else { - out = #force_inline math.floor(x); + out = #force_inline math.floor(x) } - return; + return } round :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = #force_inline math.round(x[i]); + out[i] = #force_inline math.round(x[i]) } } else { - out = #force_inline math.round(x); + out = #force_inline math.round(x) } - return; + return } fract :: proc(x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) { - f := #force_inline floor(x); - return x - f; + f := #force_inline floor(x) + return x - f } mod :: proc(x, m: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) { - f := #force_inline floor(x / m); - return x - f * m; + f := #force_inline floor(x / m) + return x - f * m } face_forward :: proc(N, I, N_ref: $T) -> (out: T) where IS_ARRAY(T), IS_FLOAT(ELEM_TYPE(T)) { - return dot(N_ref, I) < 0 ? N : -N; + return dot(N_ref, I) < 0 ? N : -N } distance :: proc(p0, p1: $V/[$N]$E) -> E where IS_NUMERIC(E) { - return length(p1 - p0); + return length(p1 - p0) } reflect :: proc(I, N: $T) -> (out: T) where IS_ARRAY(T), IS_FLOAT(ELEM_TYPE(T)) { - b := n * (2 * dot(n, i)); - return i - b; + b := n * (2 * dot(n, i)) + return i - b } refract :: proc(I, N: $T) -> (out: T) where IS_ARRAY(T), IS_FLOAT(ELEM_TYPE(T)) { - dv := dot(n, i); - k := 1 - eta*eta - (1 - dv*dv); - a := i * eta; - b := n * eta*dv*math.sqrt(k); - return (a - b) * E(int(k >= 0)); + dv := dot(n, i) + k := 1 - eta*eta - (1 - dv*dv) + a := i * eta + b := n * eta*dv*math.sqrt(k) + return (a - b) * E(int(k >= 0)) } is_nan_single :: proc(x: $T) -> bool where IS_FLOAT(T) { - return #force_inline math.is_nan(x); + return #force_inline math.is_nan(x) } is_nan_array :: proc(x: $A/[$N]$T) -> (out: [N]bool) where IS_FLOAT(T) { for i in 0..<N { - out[i] = #force_inline is_nan(x[i]); + out[i] = #force_inline is_nan(x[i]) } - return; + return } is_inf_single :: proc(x: $T) -> bool where IS_FLOAT(T) { - return #force_inline math.is_inf(x); + return #force_inline math.is_inf(x) } is_inf_array :: proc(x: $A/[$N]$T) -> (out: [N]bool) where IS_FLOAT(T) { for i in 0..<N { - out[i] = #force_inline is_inf(x[i]); + out[i] = #force_inline is_inf(x[i]) } - return; + return } classify_single :: proc(x: $T) -> math.Float_Class where IS_FLOAT(T) { - return #force_inline math.classify(x); + return #force_inline math.classify(x) } classify_array :: proc(x: $A/[$N]$T) -> (out: [N]math.Float_Class) where IS_FLOAT(T) { for i in 0..<N { - out[i] = #force_inline classify_single(x[i]); + out[i] = #force_inline classify_single(x[i]) } - return; + return } -is_nan :: proc{is_nan_single, is_nan_array}; -is_inf :: proc{is_inf_single, is_inf_array}; -classify :: proc{classify_single, classify_array}; +is_nan :: proc{is_nan_single, is_nan_array} +is_inf :: proc{is_inf_single, is_inf_array} +classify :: proc{classify_single, classify_array} less_than_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x < y; } @@ -487,67 +487,67 @@ not_equal_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), I less_than_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) { for i in 0..<N { - out[i] = x[i] < y[i]; + out[i] = x[i] < y[i] } - return; + return } less_than_equal_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) { for i in 0..<N { - out[i] = x[i] <= y[i]; + out[i] = x[i] <= y[i] } - return; + return } greater_than_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) { for i in 0..<N { - out[i] = x[i] > y[i]; + out[i] = x[i] > y[i] } - return; + return } greater_than_equal_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) { for i in 0..<N { - out[i] = x[i] >= y[i]; + out[i] = x[i] >= y[i] } - return; + return } equal_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) { for i in 0..<N { - out[i] = x[i] == y[i]; + out[i] = x[i] == y[i] } - return; + return } not_equal_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) { for i in 0..<N { - out[i] = x[i] != y[i]; + out[i] = x[i] != y[i] } - return; + return } -less_than :: proc{less_than_single, less_than_array}; -less_than_equal :: proc{less_than_equal_single, less_than_equal_array}; -greater_than :: proc{greater_than_single, greater_than_array}; -greater_than_equal :: proc{greater_than_equal_single, greater_than_equal_array}; -equal :: proc{equal_single, equal_array}; -not_equal :: proc{not_equal_single, not_equal_array}; +less_than :: proc{less_than_single, less_than_array} +less_than_equal :: proc{less_than_equal_single, less_than_equal_array} +greater_than :: proc{greater_than_single, greater_than_array} +greater_than_equal :: proc{greater_than_equal_single, greater_than_equal_array} +equal :: proc{equal_single, equal_array} +not_equal :: proc{not_equal_single, not_equal_array} any :: proc(x: $A/[$N]bool) -> (out: bool) { for e in x { if x { - return true; + return true } } - return false; + return false } all :: proc(x: $A/[$N]bool) -> (out: bool) { for e in x { if !e { - return false; + return false } } - return true; + return true } not :: proc(x: $A/[$N]bool) -> (out: A) { for e, i in x { - out[i] = !e; + out[i] = !e } - return; + return } diff --git a/core/math/linalg/general.odin b/core/math/linalg/general.odin index a053b75fd..241a50f28 100644 --- a/core/math/linalg/general.odin +++ b/core/math/linalg/general.odin @@ -5,178 +5,178 @@ import "core:intrinsics" // Generic -TAU :: 6.28318530717958647692528676655900576; -PI :: 3.14159265358979323846264338327950288; +TAU :: 6.28318530717958647692528676655900576 +PI :: 3.14159265358979323846264338327950288 -E :: 2.71828182845904523536; +E :: 2.71828182845904523536 -τ :: TAU; -π :: PI; -e :: E; +τ :: TAU +π :: PI +e :: E -SQRT_TWO :: 1.41421356237309504880168872420969808; -SQRT_THREE :: 1.73205080756887729352744634150587236; -SQRT_FIVE :: 2.23606797749978969640917366873127623; +SQRT_TWO :: 1.41421356237309504880168872420969808 +SQRT_THREE :: 1.73205080756887729352744634150587236 +SQRT_FIVE :: 2.23606797749978969640917366873127623 -LN2 :: 0.693147180559945309417232121458176568; -LN10 :: 2.30258509299404568401799145468436421; +LN2 :: 0.693147180559945309417232121458176568 +LN10 :: 2.30258509299404568401799145468436421 -MAX_F64_PRECISION :: 16; // Maximum number of meaningful digits after the decimal point for 'f64' -MAX_F32_PRECISION :: 8; // Maximum number of meaningful digits after the decimal point for 'f32' +MAX_F64_PRECISION :: 16 // Maximum number of meaningful digits after the decimal point for 'f64' +MAX_F32_PRECISION :: 8 // Maximum number of meaningful digits after the decimal point for 'f32' -RAD_PER_DEG :: TAU/360.0; -DEG_PER_RAD :: 360.0/TAU; +RAD_PER_DEG :: TAU/360.0 +DEG_PER_RAD :: 360.0/TAU -@private IS_NUMERIC :: intrinsics.type_is_numeric; -@private IS_QUATERNION :: intrinsics.type_is_quaternion; -@private IS_ARRAY :: intrinsics.type_is_array; -@private IS_FLOAT :: intrinsics.type_is_float; -@private BASE_TYPE :: intrinsics.type_base_type; -@private ELEM_TYPE :: intrinsics.type_elem_type; +@private IS_NUMERIC :: intrinsics.type_is_numeric +@private IS_QUATERNION :: intrinsics.type_is_quaternion +@private IS_ARRAY :: intrinsics.type_is_array +@private IS_FLOAT :: intrinsics.type_is_float +@private BASE_TYPE :: intrinsics.type_base_type +@private ELEM_TYPE :: intrinsics.type_elem_type scalar_dot :: proc(a, b: $T) -> T where IS_FLOAT(T), !IS_ARRAY(T) { - return a * b; + return a * b } vector_dot :: proc(a, b: $T/[$N]$E) -> (c: E) where IS_NUMERIC(E) #no_bounds_check { for i in 0..<N { - c += a[i] * b[i]; + c += a[i] * b[i] } - return; + return } quaternion64_dot :: proc(a, b: $T/quaternion64) -> (c: f16) { - return a.w*a.w + a.x*b.x + a.y*b.y + a.z*b.z; + return a.w*a.w + a.x*b.x + a.y*b.y + a.z*b.z } quaternion128_dot :: proc(a, b: $T/quaternion128) -> (c: f32) { - return a.w*a.w + a.x*b.x + a.y*b.y + a.z*b.z; + return a.w*a.w + a.x*b.x + a.y*b.y + a.z*b.z } quaternion256_dot :: proc(a, b: $T/quaternion256) -> (c: f64) { - return a.w*a.w + a.x*b.x + a.y*b.y + a.z*b.z; + return a.w*a.w + a.x*b.x + a.y*b.y + a.z*b.z } -dot :: proc{scalar_dot, vector_dot, quaternion64_dot, quaternion128_dot, quaternion256_dot}; +dot :: proc{scalar_dot, vector_dot, quaternion64_dot, quaternion128_dot, quaternion256_dot} -inner_product :: dot; +inner_product :: dot outer_product :: proc(a: $A/[$M]$E, b: $B/[$N]E) -> (out: [M][N]E) where IS_NUMERIC(E) #no_bounds_check { for i in 0..<M { for j in 0..<N { - out[i][j] = a[i]*b[j]; + out[i][j] = a[i]*b[j] } } - return; + return } quaternion_inverse :: proc(q: $Q) -> Q where IS_QUATERNION(Q) { - return conj(q) * quaternion(1.0/dot(q, q), 0, 0, 0); + return conj(q) * quaternion(1.0/dot(q, q), 0, 0, 0) } scalar_cross :: proc(a, b: $T) -> T where IS_FLOAT(T), !IS_ARRAY(T) { - return a * b; + return a * b } vector_cross2 :: proc(a, b: $T/[2]$E) -> E where IS_NUMERIC(E) { - return a[0]*b[1] - b[0]*a[1]; + return a[0]*b[1] - b[0]*a[1] } vector_cross3 :: proc(a, b: $T/[3]$E) -> (c: T) where IS_NUMERIC(E) { - c[0] = a[1]*b[2] - b[1]*a[2]; - c[1] = a[2]*b[0] - b[2]*a[0]; - c[2] = a[0]*b[1] - b[0]*a[1]; - return; + c[0] = a[1]*b[2] - b[1]*a[2] + c[1] = a[2]*b[0] - b[2]*a[0] + c[2] = a[0]*b[1] - b[0]*a[1] + return } quaternion_cross :: proc(q1, q2: $Q) -> (q3: Q) where IS_QUATERNION(Q) { - q3.x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y; - q3.y = q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z; - q3.z = q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x; - q3.w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z; - return; + q3.x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y + q3.y = q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z + q3.z = q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x + q3.w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z + return } -vector_cross :: proc{scalar_cross, vector_cross2, vector_cross3}; -cross :: proc{scalar_cross, vector_cross2, vector_cross3, quaternion_cross}; +vector_cross :: proc{scalar_cross, vector_cross2, vector_cross3} +cross :: proc{scalar_cross, vector_cross2, vector_cross3, quaternion_cross} vector_normalize :: proc(v: $T/[$N]$E) -> T where IS_NUMERIC(E) { - return v / length(v); + return v / length(v) } quaternion_normalize :: proc(q: $Q) -> Q where IS_QUATERNION(Q) { - return q/abs(q); + return q/abs(q) } -normalize :: proc{vector_normalize, quaternion_normalize}; +normalize :: proc{vector_normalize, quaternion_normalize} vector_normalize0 :: proc(v: $T/[$N]$E) -> T where IS_NUMERIC(E) { - m := length(v); - return 0 if m == 0 else v/m; + m := length(v) + return 0 if m == 0 else v/m } quaternion_normalize0 :: proc(q: $Q) -> Q where IS_QUATERNION(Q) { - m := abs(q); - return 0 if m == 0 else q/m; + m := abs(q) + return 0 if m == 0 else q/m } -normalize0 :: proc{vector_normalize0, quaternion_normalize0}; +normalize0 :: proc{vector_normalize0, quaternion_normalize0} vector_length :: proc(v: $T/[$N]$E) -> E where IS_NUMERIC(E) { - return math.sqrt(dot(v, v)); + return math.sqrt(dot(v, v)) } vector_length2 :: proc(v: $T/[$N]$E) -> E where IS_NUMERIC(E) { - return dot(v, v); + return dot(v, v) } quaternion_length :: proc(q: $Q) -> Q where IS_QUATERNION(Q) { - return abs(q); + return abs(q) } quaternion_length2 :: proc(q: $Q) -> Q where IS_QUATERNION(Q) { - return dot(q, q); + return dot(q, q) } scalar_triple_product :: proc(a, b, c: $T/[$N]$E) -> E where IS_NUMERIC(E) { // a . (b x c) // b . (c x a) // c . (a x b) - return dot(a, cross(b, c)); + return dot(a, cross(b, c)) } vector_triple_product :: proc(a, b, c: $T/[$N]$E) -> T where IS_NUMERIC(E) { // a x (b x c) // (a . c)b - (a . b)c - return cross(a, cross(b, c)); + return cross(a, cross(b, c)) } -length :: proc{vector_length, quaternion_length}; -length2 :: proc{vector_length2, quaternion_length2}; +length :: proc{vector_length, quaternion_length} +length2 :: proc{vector_length2, quaternion_length2} projection :: proc(x, normal: $T/[$N]$E) -> T where IS_NUMERIC(E) { - return dot(x, normal) / dot(normal, normal) * normal; + return dot(x, normal) / dot(normal, normal) * normal } identity :: proc($T: typeid/[$N][N]$E) -> (m: T) #no_bounds_check { for i in 0..<N { - m[i][i] = E(1); + m[i][i] = E(1) } - return m; + return m } trace :: proc(m: $T/[$N][N]$E) -> (tr: E) { for i in 0..<N { - tr += m[i][i]; + tr += m[i][i] } - return; + return } transpose :: proc(a: $T/[$N][$M]$E) -> (m: (T when N == M else [M][N]E)) #no_bounds_check { for j in 0..<M { for i in 0..<N { - m[j][i] = a[i][j]; + m[j][i] = a[i][j] } } - return; + return } matrix_mul :: proc(a, b: $M/[$N][N]$E) -> (c: M) @@ -184,21 +184,21 @@ matrix_mul :: proc(a, b: $M/[$N][N]$E) -> (c: M) for i in 0..<N { for k in 0..<N { for j in 0..<N { - c[k][i] += a[j][i] * b[k][j]; + c[k][i] += a[j][i] * b[k][j] } } } - return; + return } matrix_comp_mul :: proc(a, b: $M/[$J][$I]$E) -> (c: M) where !IS_ARRAY(E), IS_NUMERIC(E) #no_bounds_check { for j in 0..<J { for i in 0..<I { - c[j][i] = a[j][i] * b[j][i]; + c[j][i] = a[j][i] * b[j][i] } } - return; + return } matrix_mul_differ :: proc(a: $A/[$J][$I]$E, b: $B/[$K][J]E) -> (c: [K][I]E) @@ -206,11 +206,11 @@ matrix_mul_differ :: proc(a: $A/[$J][$I]$E, b: $B/[$K][J]E) -> (c: [K][I]E) for k in 0..<K { for j in 0..<J { for i in 0..<I { - c[k][i] += a[j][i] * b[k][j]; + c[k][i] += a[j][i] * b[k][j] } } } - return; + return } @@ -218,44 +218,44 @@ matrix_mul_vector :: proc(a: $A/[$I][$J]$E, b: $B/[I]E) -> (c: B) where !IS_ARRAY(E), IS_NUMERIC(E) #no_bounds_check { for i in 0..<I { for j in 0..<J { - c[j] += a[i][j] * b[i]; + c[j] += a[i][j] * b[i] } } - return; + return } quaternion_mul_quaternion :: proc(q1, q2: $Q) -> Q where IS_QUATERNION(Q) { - return q1 * q2; + return q1 * q2 } quaternion64_mul_vector3 :: proc(q: $Q/quaternion64, v: $V/[3]$F/f16) -> V { - Raw_Quaternion :: struct {xyz: [3]f16, r: f16}; + Raw_Quaternion :: struct {xyz: [3]f16, r: f16} - q := transmute(Raw_Quaternion)q; - v := transmute([3]f16)v; + q := transmute(Raw_Quaternion)q + v := transmute([3]f16)v - t := cross(2*q.xyz, v); - return V(v + q.r*t + cross(q.xyz, t)); + t := cross(2*q.xyz, v) + return V(v + q.r*t + cross(q.xyz, t)) } quaternion128_mul_vector3 :: proc(q: $Q/quaternion128, v: $V/[3]$F/f32) -> V { - Raw_Quaternion :: struct {xyz: [3]f32, r: f32}; + Raw_Quaternion :: struct {xyz: [3]f32, r: f32} - q := transmute(Raw_Quaternion)q; - v := transmute([3]f32)v; + q := transmute(Raw_Quaternion)q + v := transmute([3]f32)v - t := cross(2*q.xyz, v); - return V(v + q.r*t + cross(q.xyz, t)); + t := cross(2*q.xyz, v) + return V(v + q.r*t + cross(q.xyz, t)) } quaternion256_mul_vector3 :: proc(q: $Q/quaternion256, v: $V/[3]$F/f64) -> V { - Raw_Quaternion :: struct {xyz: [3]f64, r: f64}; + Raw_Quaternion :: struct {xyz: [3]f64, r: f64} - q := transmute(Raw_Quaternion)q; - v := transmute([3]f64)v; + q := transmute(Raw_Quaternion)q + v := transmute([3]f64)v - t := cross(2*q.xyz, v); - return V(v + q.r*t + cross(q.xyz, t)); + t := cross(2*q.xyz, v) + return V(v + q.r*t + cross(q.xyz, t)) } -quaternion_mul_vector3 :: proc{quaternion64_mul_vector3, quaternion128_mul_vector3, quaternion256_mul_vector3}; +quaternion_mul_vector3 :: proc{quaternion64_mul_vector3, quaternion128_mul_vector3, quaternion256_mul_vector3} mul :: proc{ matrix_mul, @@ -265,16 +265,16 @@ mul :: proc{ quaternion128_mul_vector3, quaternion256_mul_vector3, quaternion_mul_quaternion, -}; +} vector_to_ptr :: proc(v: ^$V/[$N]$E) -> ^E where IS_NUMERIC(E), N > 0 #no_bounds_check { - return &v[0]; + return &v[0] } matrix_to_ptr :: proc(m: ^$A/[$I][$J]$E) -> ^E where IS_NUMERIC(E), I > 0, J > 0 #no_bounds_check { - return &m[0][0]; + return &m[0][0] } -to_ptr :: proc{vector_to_ptr, matrix_to_ptr}; +to_ptr :: proc{vector_to_ptr, matrix_to_ptr} @@ -283,60 +283,60 @@ to_ptr :: proc{vector_to_ptr, matrix_to_ptr}; // Splines vector_slerp :: proc(x, y: $T/[$N]$E, a: E) -> T { - cos_alpha := dot(x, y); - alpha := math.acos(cos_alpha); - sin_alpha := math.sin(alpha); + cos_alpha := dot(x, y) + alpha := math.acos(cos_alpha) + sin_alpha := math.sin(alpha) - t1 := math.sin((1 - a) * alpha) / sin_alpha; - t2 := math.sin(a * alpha) / sin_alpha; + t1 := math.sin((1 - a) * alpha) / sin_alpha + t2 := math.sin(a * alpha) / sin_alpha - return x * t1 + y * t2; + return x * t1 + y * t2 } catmull_rom :: proc(v1, v2, v3, v4: $T/[$N]$E, s: E) -> T { - s2 := s*s; - s3 := s2*s; + s2 := s*s + s3 := s2*s - f1 := -s3 + 2 * s2 - s; - f2 := 3 * s3 - 5 * s2 + 2; - f3 := -3 * s3 + 4 * s2 + s; - f4 := s3 - s2; + f1 := -s3 + 2 * s2 - s + f2 := 3 * s3 - 5 * s2 + 2 + f3 := -3 * s3 + 4 * s2 + s + f4 := s3 - s2 - return (f1 * v1 + f2 * v2 + f3 * v3 + f4 * v4) * 0.5; + return (f1 * v1 + f2 * v2 + f3 * v3 + f4 * v4) * 0.5 } hermite :: proc(v1, t1, v2, t2: $T/[$N]$E, s: E) -> T { - s2 := s*s; - s3 := s2*s; + s2 := s*s + s3 := s2*s - f1 := 2 * s3 - 3 * s2 + 1; - f2 := -2 * s3 + 3 * s2; - f3 := s3 - 2 * s2 + s; - f4 := s3 - s2; + f1 := 2 * s3 - 3 * s2 + 1 + f2 := -2 * s3 + 3 * s2 + f3 := s3 - 2 * s2 + s + f4 := s3 - s2 - return f1 * v1 + f2 * v2 + f3 * t1 + f4 * t2; + return f1 * v1 + f2 * v2 + f3 * t1 + f4 * t2 } cubic :: proc(v1, v2, v3, v4: $T/[$N]$E, s: E) -> T { - return ((v1 * s + v2) * s + v3) * s + v4; + return ((v1 * s + v2) * s + v3) * s + v4 } array_cast :: proc(v: $A/[$N]$T, $Elem_Type: typeid) -> (w: [N]Elem_Type) #no_bounds_check { for i in 0..<N { - w[i] = Elem_Type(v[i]); + w[i] = Elem_Type(v[i]) } - return; + return } matrix_cast :: proc(v: $A/[$M][$N]$T, $Elem_Type: typeid) -> (w: [M][N]Elem_Type) #no_bounds_check { for i in 0..<M { for j in 0..<N { - w[i][j] = Elem_Type(v[i][j]); + w[i][j] = Elem_Type(v[i][j]) } } - return; + return } to_f32 :: #force_inline proc(v: $A/[$N]$T) -> [N]f32 { return array_cast(v, f32); } diff --git a/core/math/linalg/specific.odin b/core/math/linalg/specific.odin index 7d0d9dc7e..333d17e44 100644 --- a/core/math/linalg/specific.odin +++ b/core/math/linalg/specific.odin @@ -2,2452 +2,2452 @@ package linalg import "core:math" -F16_EPSILON :: 1e-3; -F32_EPSILON :: 1e-7; -F64_EPSILON :: 1e-15; - -Vector2f16 :: distinct [2]f16; -Vector3f16 :: distinct [3]f16; -Vector4f16 :: distinct [4]f16; - -Matrix1x1f16 :: distinct [1][1]f16; -Matrix1x2f16 :: distinct [1][2]f16; -Matrix1x3f16 :: distinct [1][3]f16; -Matrix1x4f16 :: distinct [1][4]f16; - -Matrix2x1f16 :: distinct [2][1]f16; -Matrix2x2f16 :: distinct [2][2]f16; -Matrix2x3f16 :: distinct [2][3]f16; -Matrix2x4f16 :: distinct [2][4]f16; - -Matrix3x1f16 :: distinct [3][1]f16; -Matrix3x2f16 :: distinct [3][2]f16; -Matrix3x3f16 :: distinct [3][3]f16; -Matrix3x4f16 :: distinct [3][4]f16; - -Matrix4x1f16 :: distinct [4][1]f16; -Matrix4x2f16 :: distinct [4][2]f16; -Matrix4x3f16 :: distinct [4][3]f16; -Matrix4x4f16 :: distinct [4][4]f16; - -Matrix1f16 :: Matrix1x1f16; -Matrix2f16 :: Matrix2x2f16; -Matrix3f16 :: Matrix3x3f16; -Matrix4f16 :: Matrix4x4f16; - -Vector2f32 :: distinct [2]f32; -Vector3f32 :: distinct [3]f32; -Vector4f32 :: distinct [4]f32; - -Matrix1x1f32 :: distinct [1][1]f32; -Matrix1x2f32 :: distinct [1][2]f32; -Matrix1x3f32 :: distinct [1][3]f32; -Matrix1x4f32 :: distinct [1][4]f32; - -Matrix2x1f32 :: distinct [2][1]f32; -Matrix2x2f32 :: distinct [2][2]f32; -Matrix2x3f32 :: distinct [2][3]f32; -Matrix2x4f32 :: distinct [2][4]f32; - -Matrix3x1f32 :: distinct [3][1]f32; -Matrix3x2f32 :: distinct [3][2]f32; -Matrix3x3f32 :: distinct [3][3]f32; -Matrix3x4f32 :: distinct [3][4]f32; - -Matrix4x1f32 :: distinct [4][1]f32; -Matrix4x2f32 :: distinct [4][2]f32; -Matrix4x3f32 :: distinct [4][3]f32; -Matrix4x4f32 :: distinct [4][4]f32; - -Matrix1f32 :: Matrix1x1f32; -Matrix2f32 :: Matrix2x2f32; -Matrix3f32 :: Matrix3x3f32; -Matrix4f32 :: Matrix4x4f32; - -Vector2f64 :: distinct [2]f64; -Vector3f64 :: distinct [3]f64; -Vector4f64 :: distinct [4]f64; - -Matrix1x1f64 :: distinct [1][1]f64; -Matrix1x2f64 :: distinct [1][2]f64; -Matrix1x3f64 :: distinct [1][3]f64; -Matrix1x4f64 :: distinct [1][4]f64; - -Matrix2x1f64 :: distinct [2][1]f64; -Matrix2x2f64 :: distinct [2][2]f64; -Matrix2x3f64 :: distinct [2][3]f64; -Matrix2x4f64 :: distinct [2][4]f64; - -Matrix3x1f64 :: distinct [3][1]f64; -Matrix3x2f64 :: distinct [3][2]f64; -Matrix3x3f64 :: distinct [3][3]f64; -Matrix3x4f64 :: distinct [3][4]f64; - -Matrix4x1f64 :: distinct [4][1]f64; -Matrix4x2f64 :: distinct [4][2]f64; -Matrix4x3f64 :: distinct [4][3]f64; -Matrix4x4f64 :: distinct [4][4]f64; - -Matrix1f64 :: Matrix1x1f64; -Matrix2f64 :: Matrix2x2f64; -Matrix3f64 :: Matrix3x3f64; -Matrix4f64 :: Matrix4x4f64; - -Quaternionf16 :: distinct quaternion64; -Quaternionf32 :: distinct quaternion128; -Quaternionf64 :: distinct quaternion256; - -MATRIX1F16_IDENTITY :: Matrix1f16{{1}}; -MATRIX2F16_IDENTITY :: Matrix2f16{{1, 0}, {0, 1}}; -MATRIX3F16_IDENTITY :: Matrix3f16{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; -MATRIX4F16_IDENTITY :: Matrix4f16{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}; - -MATRIX1F32_IDENTITY :: Matrix1f32{{1}}; -MATRIX2F32_IDENTITY :: Matrix2f32{{1, 0}, {0, 1}}; -MATRIX3F32_IDENTITY :: Matrix3f32{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; -MATRIX4F32_IDENTITY :: Matrix4f32{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}; - -MATRIX1F64_IDENTITY :: Matrix1f64{{1}}; -MATRIX2F64_IDENTITY :: Matrix2f64{{1, 0}, {0, 1}}; -MATRIX3F64_IDENTITY :: Matrix3f64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; -MATRIX4F64_IDENTITY :: Matrix4f64{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}; - -QUATERNIONF16_IDENTITY :: Quaternionf16(1); -QUATERNIONF32_IDENTITY :: Quaternionf32(1); -QUATERNIONF64_IDENTITY :: Quaternionf64(1); - -VECTOR3F16_X_AXIS :: Vector3f16{1, 0, 0}; -VECTOR3F16_Y_AXIS :: Vector3f16{0, 1, 0}; -VECTOR3F16_Z_AXIS :: Vector3f16{0, 0, 1}; - -VECTOR3F32_X_AXIS :: Vector3f32{1, 0, 0}; -VECTOR3F32_Y_AXIS :: Vector3f32{0, 1, 0}; -VECTOR3F32_Z_AXIS :: Vector3f32{0, 0, 1}; - -VECTOR3F64_X_AXIS :: Vector3f64{1, 0, 0}; -VECTOR3F64_Y_AXIS :: Vector3f64{0, 1, 0}; -VECTOR3F64_Z_AXIS :: Vector3f64{0, 0, 1}; +F16_EPSILON :: 1e-3 +F32_EPSILON :: 1e-7 +F64_EPSILON :: 1e-15 + +Vector2f16 :: distinct [2]f16 +Vector3f16 :: distinct [3]f16 +Vector4f16 :: distinct [4]f16 + +Matrix1x1f16 :: distinct [1][1]f16 +Matrix1x2f16 :: distinct [1][2]f16 +Matrix1x3f16 :: distinct [1][3]f16 +Matrix1x4f16 :: distinct [1][4]f16 + +Matrix2x1f16 :: distinct [2][1]f16 +Matrix2x2f16 :: distinct [2][2]f16 +Matrix2x3f16 :: distinct [2][3]f16 +Matrix2x4f16 :: distinct [2][4]f16 + +Matrix3x1f16 :: distinct [3][1]f16 +Matrix3x2f16 :: distinct [3][2]f16 +Matrix3x3f16 :: distinct [3][3]f16 +Matrix3x4f16 :: distinct [3][4]f16 + +Matrix4x1f16 :: distinct [4][1]f16 +Matrix4x2f16 :: distinct [4][2]f16 +Matrix4x3f16 :: distinct [4][3]f16 +Matrix4x4f16 :: distinct [4][4]f16 + +Matrix1f16 :: Matrix1x1f16 +Matrix2f16 :: Matrix2x2f16 +Matrix3f16 :: Matrix3x3f16 +Matrix4f16 :: Matrix4x4f16 + +Vector2f32 :: distinct [2]f32 +Vector3f32 :: distinct [3]f32 +Vector4f32 :: distinct [4]f32 + +Matrix1x1f32 :: distinct [1][1]f32 +Matrix1x2f32 :: distinct [1][2]f32 +Matrix1x3f32 :: distinct [1][3]f32 +Matrix1x4f32 :: distinct [1][4]f32 + +Matrix2x1f32 :: distinct [2][1]f32 +Matrix2x2f32 :: distinct [2][2]f32 +Matrix2x3f32 :: distinct [2][3]f32 +Matrix2x4f32 :: distinct [2][4]f32 + +Matrix3x1f32 :: distinct [3][1]f32 +Matrix3x2f32 :: distinct [3][2]f32 +Matrix3x3f32 :: distinct [3][3]f32 +Matrix3x4f32 :: distinct [3][4]f32 + +Matrix4x1f32 :: distinct [4][1]f32 +Matrix4x2f32 :: distinct [4][2]f32 +Matrix4x3f32 :: distinct [4][3]f32 +Matrix4x4f32 :: distinct [4][4]f32 + +Matrix1f32 :: Matrix1x1f32 +Matrix2f32 :: Matrix2x2f32 +Matrix3f32 :: Matrix3x3f32 +Matrix4f32 :: Matrix4x4f32 + +Vector2f64 :: distinct [2]f64 +Vector3f64 :: distinct [3]f64 +Vector4f64 :: distinct [4]f64 + +Matrix1x1f64 :: distinct [1][1]f64 +Matrix1x2f64 :: distinct [1][2]f64 +Matrix1x3f64 :: distinct [1][3]f64 +Matrix1x4f64 :: distinct [1][4]f64 + +Matrix2x1f64 :: distinct [2][1]f64 +Matrix2x2f64 :: distinct [2][2]f64 +Matrix2x3f64 :: distinct [2][3]f64 +Matrix2x4f64 :: distinct [2][4]f64 + +Matrix3x1f64 :: distinct [3][1]f64 +Matrix3x2f64 :: distinct [3][2]f64 +Matrix3x3f64 :: distinct [3][3]f64 +Matrix3x4f64 :: distinct [3][4]f64 + +Matrix4x1f64 :: distinct [4][1]f64 +Matrix4x2f64 :: distinct [4][2]f64 +Matrix4x3f64 :: distinct [4][3]f64 +Matrix4x4f64 :: distinct [4][4]f64 + +Matrix1f64 :: Matrix1x1f64 +Matrix2f64 :: Matrix2x2f64 +Matrix3f64 :: Matrix3x3f64 +Matrix4f64 :: Matrix4x4f64 + +Quaternionf16 :: distinct quaternion64 +Quaternionf32 :: distinct quaternion128 +Quaternionf64 :: distinct quaternion256 + +MATRIX1F16_IDENTITY :: Matrix1f16{{1}} +MATRIX2F16_IDENTITY :: Matrix2f16{{1, 0}, {0, 1}} +MATRIX3F16_IDENTITY :: Matrix3f16{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}} +MATRIX4F16_IDENTITY :: Matrix4f16{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}} + +MATRIX1F32_IDENTITY :: Matrix1f32{{1}} +MATRIX2F32_IDENTITY :: Matrix2f32{{1, 0}, {0, 1}} +MATRIX3F32_IDENTITY :: Matrix3f32{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}} +MATRIX4F32_IDENTITY :: Matrix4f32{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}} + +MATRIX1F64_IDENTITY :: Matrix1f64{{1}} +MATRIX2F64_IDENTITY :: Matrix2f64{{1, 0}, {0, 1}} +MATRIX3F64_IDENTITY :: Matrix3f64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}} +MATRIX4F64_IDENTITY :: Matrix4f64{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}} + +QUATERNIONF16_IDENTITY :: Quaternionf16(1) +QUATERNIONF32_IDENTITY :: Quaternionf32(1) +QUATERNIONF64_IDENTITY :: Quaternionf64(1) + +VECTOR3F16_X_AXIS :: Vector3f16{1, 0, 0} +VECTOR3F16_Y_AXIS :: Vector3f16{0, 1, 0} +VECTOR3F16_Z_AXIS :: Vector3f16{0, 0, 1} + +VECTOR3F32_X_AXIS :: Vector3f32{1, 0, 0} +VECTOR3F32_Y_AXIS :: Vector3f32{0, 1, 0} +VECTOR3F32_Z_AXIS :: Vector3f32{0, 0, 1} + +VECTOR3F64_X_AXIS :: Vector3f64{1, 0, 0} +VECTOR3F64_Y_AXIS :: Vector3f64{0, 1, 0} +VECTOR3F64_Z_AXIS :: Vector3f64{0, 0, 1} vector2_orthogonal :: proc(v: $V/[2]$E) -> V where !IS_ARRAY(E), IS_FLOAT(E) { - return {-v.y, v.x}; + return {-v.y, v.x} } vector3_orthogonal :: proc(v: $V/[3]$E) -> V where !IS_ARRAY(E), IS_FLOAT(E) { - x := abs(v.x); - y := abs(v.y); - z := abs(v.z); + x := abs(v.x) + y := abs(v.y) + z := abs(v.z) - other: V; + other: V if x < y { if x < z { - other = {1, 0, 0}; + other = {1, 0, 0} } else { - other = {0, 0, 1}; + other = {0, 0, 1} } } else { if y < z { - other = {0, 1, 0}; + other = {0, 1, 0} } else { - other = {0, 0, 1}; + other = {0, 0, 1} } } - return normalize(cross(v, other)); + return normalize(cross(v, other)) } -orthogonal :: proc{vector2_orthogonal, vector3_orthogonal}; +orthogonal :: proc{vector2_orthogonal, vector3_orthogonal} vector4_srgb_to_linear_f16 :: proc(col: Vector4f16) -> Vector4f16 { - r := math.pow(col.x, 2.2); - g := math.pow(col.y, 2.2); - b := math.pow(col.z, 2.2); - a := col.w; - return {r, g, b, a}; + r := math.pow(col.x, 2.2) + g := math.pow(col.y, 2.2) + b := math.pow(col.z, 2.2) + a := col.w + return {r, g, b, a} } vector4_srgb_to_linear_f32 :: proc(col: Vector4f32) -> Vector4f32 { - r := math.pow(col.x, 2.2); - g := math.pow(col.y, 2.2); - b := math.pow(col.z, 2.2); - a := col.w; - return {r, g, b, a}; + r := math.pow(col.x, 2.2) + g := math.pow(col.y, 2.2) + b := math.pow(col.z, 2.2) + a := col.w + return {r, g, b, a} } vector4_srgb_to_linear_f64 :: proc(col: Vector4f64) -> Vector4f64 { - r := math.pow(col.x, 2.2); - g := math.pow(col.y, 2.2); - b := math.pow(col.z, 2.2); - a := col.w; - return {r, g, b, a}; + r := math.pow(col.x, 2.2) + g := math.pow(col.y, 2.2) + b := math.pow(col.z, 2.2) + a := col.w + return {r, g, b, a} } vector4_srgb_to_linear :: proc{ vector4_srgb_to_linear_f16, vector4_srgb_to_linear_f32, vector4_srgb_to_linear_f64, -}; +} vector4_linear_to_srgb_f16 :: proc(col: Vector4f16) -> Vector4f16 { - a :: 2.51; - b :: 0.03; - c :: 2.43; - d :: 0.59; - e :: 0.14; + a :: 2.51 + b :: 0.03 + c :: 2.43 + d :: 0.59 + e :: 0.14 - x := col.x; - y := col.y; - z := col.z; + x := col.x + y := col.y + z := col.z - x = (x * (a * x + b)) / (x * (c * x + d) + e); - y = (y * (a * y + b)) / (y * (c * y + d) + e); - z = (z * (a * z + b)) / (z * (c * z + d) + e); + x = (x * (a * x + b)) / (x * (c * x + d) + e) + y = (y * (a * y + b)) / (y * (c * y + d) + e) + z = (z * (a * z + b)) / (z * (c * z + d) + e) - x = math.pow(clamp(x, 0, 1), 1.0 / 2.2); - y = math.pow(clamp(y, 0, 1), 1.0 / 2.2); - z = math.pow(clamp(z, 0, 1), 1.0 / 2.2); + x = math.pow(clamp(x, 0, 1), 1.0 / 2.2) + y = math.pow(clamp(y, 0, 1), 1.0 / 2.2) + z = math.pow(clamp(z, 0, 1), 1.0 / 2.2) - return {x, y, z, col.w}; + return {x, y, z, col.w} } vector4_linear_to_srgb_f32 :: proc(col: Vector4f32) -> Vector4f32 { - a :: 2.51; - b :: 0.03; - c :: 2.43; - d :: 0.59; - e :: 0.14; + a :: 2.51 + b :: 0.03 + c :: 2.43 + d :: 0.59 + e :: 0.14 - x := col.x; - y := col.y; - z := col.z; + x := col.x + y := col.y + z := col.z - x = (x * (a * x + b)) / (x * (c * x + d) + e); - y = (y * (a * y + b)) / (y * (c * y + d) + e); - z = (z * (a * z + b)) / (z * (c * z + d) + e); + x = (x * (a * x + b)) / (x * (c * x + d) + e) + y = (y * (a * y + b)) / (y * (c * y + d) + e) + z = (z * (a * z + b)) / (z * (c * z + d) + e) - x = math.pow(clamp(x, 0, 1), 1.0 / 2.2); - y = math.pow(clamp(y, 0, 1), 1.0 / 2.2); - z = math.pow(clamp(z, 0, 1), 1.0 / 2.2); + x = math.pow(clamp(x, 0, 1), 1.0 / 2.2) + y = math.pow(clamp(y, 0, 1), 1.0 / 2.2) + z = math.pow(clamp(z, 0, 1), 1.0 / 2.2) - return {x, y, z, col.w}; + return {x, y, z, col.w} } vector4_linear_to_srgb_f64 :: proc(col: Vector4f64) -> Vector4f64 { - a :: 2.51; - b :: 0.03; - c :: 2.43; - d :: 0.59; - e :: 0.14; + a :: 2.51 + b :: 0.03 + c :: 2.43 + d :: 0.59 + e :: 0.14 - x := col.x; - y := col.y; - z := col.z; + x := col.x + y := col.y + z := col.z - x = (x * (a * x + b)) / (x * (c * x + d) + e); - y = (y * (a * y + b)) / (y * (c * y + d) + e); - z = (z * (a * z + b)) / (z * (c * z + d) + e); + x = (x * (a * x + b)) / (x * (c * x + d) + e) + y = (y * (a * y + b)) / (y * (c * y + d) + e) + z = (z * (a * z + b)) / (z * (c * z + d) + e) - x = math.pow(clamp(x, 0, 1), 1.0 / 2.2); - y = math.pow(clamp(y, 0, 1), 1.0 / 2.2); - z = math.pow(clamp(z, 0, 1), 1.0 / 2.2); + x = math.pow(clamp(x, 0, 1), 1.0 / 2.2) + y = math.pow(clamp(y, 0, 1), 1.0 / 2.2) + z = math.pow(clamp(z, 0, 1), 1.0 / 2.2) - return {x, y, z, col.w}; + return {x, y, z, col.w} } vector4_linear_to_srgb :: proc{ vector4_linear_to_srgb_f16, vector4_linear_to_srgb_f32, vector4_linear_to_srgb_f64, -}; +} vector4_hsl_to_rgb_f16 :: proc(h, s, l: f16, a: f16 = 1) -> Vector4f16 { hue_to_rgb :: proc(p, q, t: f16) -> f16 { - t := t; + t := t if t < 0 { t += 1; } if t > 1 { t -= 1; } switch { - case t < 1.0/6.0: return p + (q - p) * 6.0 * t; - case t < 1.0/2.0: return q; - case t < 2.0/3.0: return p + (q - p) * 6.0 * (2.0/3.0 - t); + case t < 1.0/6.0: return p + (q - p) * 6.0 * t + case t < 1.0/2.0: return q + case t < 2.0/3.0: return p + (q - p) * 6.0 * (2.0/3.0 - t) } - return p; + return p } - r, g, b: f16; + r, g, b: f16 if s == 0 { - r = l; - g = l; - b = l; + r = l + g = l + b = l } else { - q := l * (1+s) if l < 0.5 else l+s - l*s; - p := 2*l - q; - r = hue_to_rgb(p, q, h + 1.0/3.0); - g = hue_to_rgb(p, q, h); - b = hue_to_rgb(p, q, h - 1.0/3.0); + q := l * (1+s) if l < 0.5 else l+s - l*s + p := 2*l - q + r = hue_to_rgb(p, q, h + 1.0/3.0) + g = hue_to_rgb(p, q, h) + b = hue_to_rgb(p, q, h - 1.0/3.0) } - return {r, g, b, a}; + return {r, g, b, a} } vector4_hsl_to_rgb_f32 :: proc(h, s, l: f32, a: f32 = 1) -> Vector4f32 { hue_to_rgb :: proc(p, q, t: f32) -> f32 { - t := t; + t := t if t < 0 { t += 1; } if t > 1 { t -= 1; } switch { - case t < 1.0/6.0: return p + (q - p) * 6.0 * t; - case t < 1.0/2.0: return q; - case t < 2.0/3.0: return p + (q - p) * 6.0 * (2.0/3.0 - t); + case t < 1.0/6.0: return p + (q - p) * 6.0 * t + case t < 1.0/2.0: return q + case t < 2.0/3.0: return p + (q - p) * 6.0 * (2.0/3.0 - t) } - return p; + return p } - r, g, b: f32; + r, g, b: f32 if s == 0 { - r = l; - g = l; - b = l; + r = l + g = l + b = l } else { - q := l * (1+s) if l < 0.5 else l+s - l*s; - p := 2*l - q; - r = hue_to_rgb(p, q, h + 1.0/3.0); - g = hue_to_rgb(p, q, h); - b = hue_to_rgb(p, q, h - 1.0/3.0); + q := l * (1+s) if l < 0.5 else l+s - l*s + p := 2*l - q + r = hue_to_rgb(p, q, h + 1.0/3.0) + g = hue_to_rgb(p, q, h) + b = hue_to_rgb(p, q, h - 1.0/3.0) } - return {r, g, b, a}; + return {r, g, b, a} } vector4_hsl_to_rgb_f64 :: proc(h, s, l: f64, a: f64 = 1) -> Vector4f64 { hue_to_rgb :: proc(p, q, t: f64) -> f64 { - t := t; + t := t if t < 0 { t += 1; } if t > 1 { t -= 1; } switch { - case t < 1.0/6.0: return p + (q - p) * 6.0 * t; - case t < 1.0/2.0: return q; - case t < 2.0/3.0: return p + (q - p) * 6.0 * (2.0/3.0 - t); + case t < 1.0/6.0: return p + (q - p) * 6.0 * t + case t < 1.0/2.0: return q + case t < 2.0/3.0: return p + (q - p) * 6.0 * (2.0/3.0 - t) } - return p; + return p } - r, g, b: f64; + r, g, b: f64 if s == 0 { - r = l; - g = l; - b = l; + r = l + g = l + b = l } else { - q := l * (1+s) if l < 0.5 else l+s - l*s; - p := 2*l - q; - r = hue_to_rgb(p, q, h + 1.0/3.0); - g = hue_to_rgb(p, q, h); - b = hue_to_rgb(p, q, h - 1.0/3.0); + q := l * (1+s) if l < 0.5 else l+s - l*s + p := 2*l - q + r = hue_to_rgb(p, q, h + 1.0/3.0) + g = hue_to_rgb(p, q, h) + b = hue_to_rgb(p, q, h - 1.0/3.0) } - return {r, g, b, a}; + return {r, g, b, a} } vector4_hsl_to_rgb :: proc{ vector4_hsl_to_rgb_f16, vector4_hsl_to_rgb_f32, vector4_hsl_to_rgb_f64, -}; +} vector4_rgb_to_hsl_f16 :: proc(col: Vector4f16) -> Vector4f16 { - r := col.x; - g := col.y; - b := col.z; - a := col.w; - v_min := min(r, g, b); - v_max := max(r, g, b); - h, s, l: f16; - h = 0.0; - s = 0.0; - l = (v_min + v_max) * 0.5; + r := col.x + g := col.y + b := col.z + a := col.w + v_min := min(r, g, b) + v_max := max(r, g, b) + h, s, l: f16 + h = 0.0 + s = 0.0 + l = (v_min + v_max) * 0.5 if v_max != v_min { - d: = v_max - v_min; - s = d / (2.0 - v_max - v_min) if l > 0.5 else d / (v_max + v_min); + d: = v_max - v_min + s = d / (2.0 - v_max - v_min) if l > 0.5 else d / (v_max + v_min) switch { case v_max == r: - h = (g - b) / d + (6.0 if g < b else 0.0); + h = (g - b) / d + (6.0 if g < b else 0.0) case v_max == g: - h = (b - r) / d + 2.0; + h = (b - r) / d + 2.0 case v_max == b: - h = (r - g) / d + 4.0; + h = (r - g) / d + 4.0 } - h *= 1.0/6.0; + h *= 1.0/6.0 } - return {h, s, l, a}; + return {h, s, l, a} } vector4_rgb_to_hsl_f32 :: proc(col: Vector4f32) -> Vector4f32 { - r := col.x; - g := col.y; - b := col.z; - a := col.w; - v_min := min(r, g, b); - v_max := max(r, g, b); - h, s, l: f32; - h = 0.0; - s = 0.0; - l = (v_min + v_max) * 0.5; + r := col.x + g := col.y + b := col.z + a := col.w + v_min := min(r, g, b) + v_max := max(r, g, b) + h, s, l: f32 + h = 0.0 + s = 0.0 + l = (v_min + v_max) * 0.5 if v_max != v_min { - d: = v_max - v_min; - s = d / (2.0 - v_max - v_min) if l > 0.5 else d / (v_max + v_min); + d: = v_max - v_min + s = d / (2.0 - v_max - v_min) if l > 0.5 else d / (v_max + v_min) switch { case v_max == r: - h = (g - b) / d + (6.0 if g < b else 0.0); + h = (g - b) / d + (6.0 if g < b else 0.0) case v_max == g: - h = (b - r) / d + 2.0; + h = (b - r) / d + 2.0 case v_max == b: - h = (r - g) / d + 4.0; + h = (r - g) / d + 4.0 } - h *= 1.0/6.0; + h *= 1.0/6.0 } - return {h, s, l, a}; + return {h, s, l, a} } vector4_rgb_to_hsl_f64 :: proc(col: Vector4f64) -> Vector4f64 { - r := col.x; - g := col.y; - b := col.z; - a := col.w; - v_min := min(r, g, b); - v_max := max(r, g, b); - h, s, l: f64; - h = 0.0; - s = 0.0; - l = (v_min + v_max) * 0.5; + r := col.x + g := col.y + b := col.z + a := col.w + v_min := min(r, g, b) + v_max := max(r, g, b) + h, s, l: f64 + h = 0.0 + s = 0.0 + l = (v_min + v_max) * 0.5 if v_max != v_min { - d: = v_max - v_min; - s = d / (2.0 - v_max - v_min) if l > 0.5 else d / (v_max + v_min); + d: = v_max - v_min + s = d / (2.0 - v_max - v_min) if l > 0.5 else d / (v_max + v_min) switch { case v_max == r: - h = (g - b) / d + (6.0 if g < b else 0.0); + h = (g - b) / d + (6.0 if g < b else 0.0) case v_max == g: - h = (b - r) / d + 2.0; + h = (b - r) / d + 2.0 case v_max == b: - h = (r - g) / d + 4.0; + h = (r - g) / d + 4.0 } - h *= 1.0/6.0; + h *= 1.0/6.0 } - return {h, s, l, a}; + return {h, s, l, a} } vector4_rgb_to_hsl :: proc{ vector4_rgb_to_hsl_f16, vector4_rgb_to_hsl_f32, vector4_rgb_to_hsl_f64, -}; +} quaternion_angle_axis_f16 :: proc(angle_radians: f16, axis: Vector3f16) -> (q: Quaternionf16) { - t := angle_radians*0.5; - v := normalize(axis) * math.sin(t); - q.x = v.x; - q.y = v.y; - q.z = v.z; - q.w = math.cos(t); - return; + t := angle_radians*0.5 + v := normalize(axis) * math.sin(t) + q.x = v.x + q.y = v.y + q.z = v.z + q.w = math.cos(t) + return } quaternion_angle_axis_f32 :: proc(angle_radians: f32, axis: Vector3f32) -> (q: Quaternionf32) { - t := angle_radians*0.5; - v := normalize(axis) * math.sin(t); - q.x = v.x; - q.y = v.y; - q.z = v.z; - q.w = math.cos(t); - return; + t := angle_radians*0.5 + v := normalize(axis) * math.sin(t) + q.x = v.x + q.y = v.y + q.z = v.z + q.w = math.cos(t) + return } quaternion_angle_axis_f64 :: proc(angle_radians: f64, axis: Vector3f64) -> (q: Quaternionf64) { - t := angle_radians*0.5; - v := normalize(axis) * math.sin(t); - q.x = v.x; - q.y = v.y; - q.z = v.z; - q.w = math.cos(t); - return; + t := angle_radians*0.5 + v := normalize(axis) * math.sin(t) + q.x = v.x + q.y = v.y + q.z = v.z + q.w = math.cos(t) + return } quaternion_angle_axis :: proc{ quaternion_angle_axis_f16, quaternion_angle_axis_f32, quaternion_angle_axis_f64, -}; +} angle_from_quaternion_f16 :: proc(q: Quaternionf16) -> f16 { if abs(q.w) > math.SQRT_THREE*0.5 { - return math.asin(q.x*q.x + q.y*q.y + q.z*q.z) * 2; + return math.asin(q.x*q.x + q.y*q.y + q.z*q.z) * 2 } - return math.cos(q.x) * 2; + return math.cos(q.x) * 2 } angle_from_quaternion_f32 :: proc(q: Quaternionf32) -> f32 { if abs(q.w) > math.SQRT_THREE*0.5 { - return math.asin(q.x*q.x + q.y*q.y + q.z*q.z) * 2; + return math.asin(q.x*q.x + q.y*q.y + q.z*q.z) * 2 } - return math.cos(q.x) * 2; + return math.cos(q.x) * 2 } angle_from_quaternion_f64 :: proc(q: Quaternionf64) -> f64 { if abs(q.w) > math.SQRT_THREE*0.5 { - return math.asin(q.x*q.x + q.y*q.y + q.z*q.z) * 2; + return math.asin(q.x*q.x + q.y*q.y + q.z*q.z) * 2 } - return math.cos(q.x) * 2; + return math.cos(q.x) * 2 } angle_from_quaternion :: proc{ angle_from_quaternion_f16, angle_from_quaternion_f32, angle_from_quaternion_f64, -}; +} axis_from_quaternion_f16 :: proc(q: Quaternionf16) -> Vector3f16 { - t1 := 1 - q.w*q.w; + t1 := 1 - q.w*q.w if t1 < 0 { - return {0, 0, 1}; + return {0, 0, 1} } - t2 := 1.0 / math.sqrt(t1); - return {q.x*t2, q.y*t2, q.z*t2}; + t2 := 1.0 / math.sqrt(t1) + return {q.x*t2, q.y*t2, q.z*t2} } axis_from_quaternion_f32 :: proc(q: Quaternionf32) -> Vector3f32 { - t1 := 1 - q.w*q.w; + t1 := 1 - q.w*q.w if t1 < 0 { - return {0, 0, 1}; + return {0, 0, 1} } - t2 := 1.0 / math.sqrt(t1); - return {q.x*t2, q.y*t2, q.z*t2}; + t2 := 1.0 / math.sqrt(t1) + return {q.x*t2, q.y*t2, q.z*t2} } axis_from_quaternion_f64 :: proc(q: Quaternionf64) -> Vector3f64 { - t1 := 1 - q.w*q.w; + t1 := 1 - q.w*q.w if t1 < 0 { - return {0, 0, 1}; + return {0, 0, 1} } - t2 := 1.0 / math.sqrt(t1); - return {q.x*t2, q.y*t2, q.z*t2}; + t2 := 1.0 / math.sqrt(t1) + return {q.x*t2, q.y*t2, q.z*t2} } axis_from_quaternion :: proc{ axis_from_quaternion_f16, axis_from_quaternion_f32, axis_from_quaternion_f64, -}; +} angle_axis_from_quaternion_f16 :: proc(q: Quaternionf16) -> (angle: f16, axis: Vector3f16) { - angle = angle_from_quaternion(q); - axis = axis_from_quaternion(q); - return; + angle = angle_from_quaternion(q) + axis = axis_from_quaternion(q) + return } angle_axis_from_quaternion_f32 :: proc(q: Quaternionf32) -> (angle: f32, axis: Vector3f32) { - angle = angle_from_quaternion(q); - axis = axis_from_quaternion(q); - return; + angle = angle_from_quaternion(q) + axis = axis_from_quaternion(q) + return } angle_axis_from_quaternion_f64 :: proc(q: Quaternionf64) -> (angle: f64, axis: Vector3f64) { - angle = angle_from_quaternion(q); - axis = axis_from_quaternion(q); - return; + angle = angle_from_quaternion(q) + axis = axis_from_quaternion(q) + return } angle_axis_from_quaternion :: proc { angle_axis_from_quaternion_f16, angle_axis_from_quaternion_f32, angle_axis_from_quaternion_f64, -}; +} quaternion_from_forward_and_up_f16 :: proc(forward, up: Vector3f16) -> Quaternionf16 { - f := normalize(forward); - s := normalize(cross(f, up)); - u := cross(s, f); + f := normalize(forward) + s := normalize(cross(f, up)) + u := cross(s, f) m := Matrix3f16{ {+s.x, +u.x, -f.x}, {+s.y, +u.y, -f.y}, {+s.z, +u.z, -f.z}, - }; + } - tr := trace(m); + tr := trace(m) - q: Quaternionf16; + q: Quaternionf16 switch { case tr > 0: - S := 2 * math.sqrt(1 + tr); - q.w = 0.25 * S; - q.x = (m[2][1] - m[1][2]) / S; - q.y = (m[0][2] - m[2][0]) / S; - q.z = (m[1][0] - m[0][1]) / S; + S := 2 * math.sqrt(1 + tr) + q.w = 0.25 * S + q.x = (m[2][1] - m[1][2]) / S + q.y = (m[0][2] - m[2][0]) / S + q.z = (m[1][0] - m[0][1]) / S case (m[0][0] > m[1][1]) && (m[0][0] > m[2][2]): - S := 2 * math.sqrt(1 + m[0][0] - m[1][1] - m[2][2]); - q.w = (m[2][1] - m[1][2]) / S; - q.x = 0.25 * S; - q.y = (m[0][1] + m[1][0]) / S; - q.z = (m[0][2] + m[2][0]) / S; + S := 2 * math.sqrt(1 + m[0][0] - m[1][1] - m[2][2]) + q.w = (m[2][1] - m[1][2]) / S + q.x = 0.25 * S + q.y = (m[0][1] + m[1][0]) / S + q.z = (m[0][2] + m[2][0]) / S case m[1][1] > m[2][2]: - S := 2 * math.sqrt(1 + m[1][1] - m[0][0] - m[2][2]); - q.w = (m[0][2] - m[2][0]) / S; - q.x = (m[0][1] + m[1][0]) / S; - q.y = 0.25 * S; - q.z = (m[1][2] + m[2][1]) / S; + S := 2 * math.sqrt(1 + m[1][1] - m[0][0] - m[2][2]) + q.w = (m[0][2] - m[2][0]) / S + q.x = (m[0][1] + m[1][0]) / S + q.y = 0.25 * S + q.z = (m[1][2] + m[2][1]) / S case: - S := 2 * math.sqrt(1 + m[2][2] - m[0][0] - m[1][1]); - q.w = (m[1][0] - m[0][1]) / S; - q.x = (m[0][2] - m[2][0]) / S; - q.y = (m[1][2] + m[2][1]) / S; - q.z = 0.25 * S; + S := 2 * math.sqrt(1 + m[2][2] - m[0][0] - m[1][1]) + q.w = (m[1][0] - m[0][1]) / S + q.x = (m[0][2] - m[2][0]) / S + q.y = (m[1][2] + m[2][1]) / S + q.z = 0.25 * S } - return normalize(q); + return normalize(q) } quaternion_from_forward_and_up_f32 :: proc(forward, up: Vector3f32) -> Quaternionf32 { - f := normalize(forward); - s := normalize(cross(f, up)); - u := cross(s, f); + f := normalize(forward) + s := normalize(cross(f, up)) + u := cross(s, f) m := Matrix3f32{ {+s.x, +u.x, -f.x}, {+s.y, +u.y, -f.y}, {+s.z, +u.z, -f.z}, - }; + } - tr := trace(m); + tr := trace(m) - q: Quaternionf32; + q: Quaternionf32 switch { case tr > 0: - S := 2 * math.sqrt(1 + tr); - q.w = 0.25 * S; - q.x = (m[2][1] - m[1][2]) / S; - q.y = (m[0][2] - m[2][0]) / S; - q.z = (m[1][0] - m[0][1]) / S; + S := 2 * math.sqrt(1 + tr) + q.w = 0.25 * S + q.x = (m[2][1] - m[1][2]) / S + q.y = (m[0][2] - m[2][0]) / S + q.z = (m[1][0] - m[0][1]) / S case (m[0][0] > m[1][1]) && (m[0][0] > m[2][2]): - S := 2 * math.sqrt(1 + m[0][0] - m[1][1] - m[2][2]); - q.w = (m[2][1] - m[1][2]) / S; - q.x = 0.25 * S; - q.y = (m[0][1] + m[1][0]) / S; - q.z = (m[0][2] + m[2][0]) / S; + S := 2 * math.sqrt(1 + m[0][0] - m[1][1] - m[2][2]) + q.w = (m[2][1] - m[1][2]) / S + q.x = 0.25 * S + q.y = (m[0][1] + m[1][0]) / S + q.z = (m[0][2] + m[2][0]) / S case m[1][1] > m[2][2]: - S := 2 * math.sqrt(1 + m[1][1] - m[0][0] - m[2][2]); - q.w = (m[0][2] - m[2][0]) / S; - q.x = (m[0][1] + m[1][0]) / S; - q.y = 0.25 * S; - q.z = (m[1][2] + m[2][1]) / S; + S := 2 * math.sqrt(1 + m[1][1] - m[0][0] - m[2][2]) + q.w = (m[0][2] - m[2][0]) / S + q.x = (m[0][1] + m[1][0]) / S + q.y = 0.25 * S + q.z = (m[1][2] + m[2][1]) / S case: - S := 2 * math.sqrt(1 + m[2][2] - m[0][0] - m[1][1]); - q.w = (m[1][0] - m[0][1]) / S; - q.x = (m[0][2] - m[2][0]) / S; - q.y = (m[1][2] + m[2][1]) / S; - q.z = 0.25 * S; + S := 2 * math.sqrt(1 + m[2][2] - m[0][0] - m[1][1]) + q.w = (m[1][0] - m[0][1]) / S + q.x = (m[0][2] - m[2][0]) / S + q.y = (m[1][2] + m[2][1]) / S + q.z = 0.25 * S } - return normalize(q); + return normalize(q) } quaternion_from_forward_and_up_f64 :: proc(forward, up: Vector3f64) -> Quaternionf64 { - f := normalize(forward); - s := normalize(cross(f, up)); - u := cross(s, f); + f := normalize(forward) + s := normalize(cross(f, up)) + u := cross(s, f) m := Matrix3f64{ {+s.x, +u.x, -f.x}, {+s.y, +u.y, -f.y}, {+s.z, +u.z, -f.z}, - }; + } - tr := trace(m); + tr := trace(m) - q: Quaternionf64; + q: Quaternionf64 switch { case tr > 0: - S := 2 * math.sqrt(1 + tr); - q.w = 0.25 * S; - q.x = (m[2][1] - m[1][2]) / S; - q.y = (m[0][2] - m[2][0]) / S; - q.z = (m[1][0] - m[0][1]) / S; + S := 2 * math.sqrt(1 + tr) + q.w = 0.25 * S + q.x = (m[2][1] - m[1][2]) / S + q.y = (m[0][2] - m[2][0]) / S + q.z = (m[1][0] - m[0][1]) / S case (m[0][0] > m[1][1]) && (m[0][0] > m[2][2]): - S := 2 * math.sqrt(1 + m[0][0] - m[1][1] - m[2][2]); - q.w = (m[2][1] - m[1][2]) / S; - q.x = 0.25 * S; - q.y = (m[0][1] + m[1][0]) / S; - q.z = (m[0][2] + m[2][0]) / S; + S := 2 * math.sqrt(1 + m[0][0] - m[1][1] - m[2][2]) + q.w = (m[2][1] - m[1][2]) / S + q.x = 0.25 * S + q.y = (m[0][1] + m[1][0]) / S + q.z = (m[0][2] + m[2][0]) / S case m[1][1] > m[2][2]: - S := 2 * math.sqrt(1 + m[1][1] - m[0][0] - m[2][2]); - q.w = (m[0][2] - m[2][0]) / S; - q.x = (m[0][1] + m[1][0]) / S; - q.y = 0.25 * S; - q.z = (m[1][2] + m[2][1]) / S; + S := 2 * math.sqrt(1 + m[1][1] - m[0][0] - m[2][2]) + q.w = (m[0][2] - m[2][0]) / S + q.x = (m[0][1] + m[1][0]) / S + q.y = 0.25 * S + q.z = (m[1][2] + m[2][1]) / S case: - S := 2 * math.sqrt(1 + m[2][2] - m[0][0] - m[1][1]); - q.w = (m[1][0] - m[0][1]) / S; - q.x = (m[0][2] - m[2][0]) / S; - q.y = (m[1][2] + m[2][1]) / S; - q.z = 0.25 * S; + S := 2 * math.sqrt(1 + m[2][2] - m[0][0] - m[1][1]) + q.w = (m[1][0] - m[0][1]) / S + q.x = (m[0][2] - m[2][0]) / S + q.y = (m[1][2] + m[2][1]) / S + q.z = 0.25 * S } - return normalize(q); + return normalize(q) } quaternion_from_forward_and_up :: proc{ quaternion_from_forward_and_up_f16, quaternion_from_forward_and_up_f32, quaternion_from_forward_and_up_f64, -}; +} quaternion_look_at_f16 :: proc(eye, centre: Vector3f16, up: Vector3f16) -> Quaternionf16 { - return quaternion_from_matrix3(matrix3_look_at(eye, centre, up)); + return quaternion_from_matrix3(matrix3_look_at(eye, centre, up)) } quaternion_look_at_f32 :: proc(eye, centre: Vector3f32, up: Vector3f32) -> Quaternionf32 { - return quaternion_from_matrix3(matrix3_look_at(eye, centre, up)); + return quaternion_from_matrix3(matrix3_look_at(eye, centre, up)) } quaternion_look_at_f64 :: proc(eye, centre: Vector3f64, up: Vector3f64) -> Quaternionf64 { - return quaternion_from_matrix3(matrix3_look_at(eye, centre, up)); + return quaternion_from_matrix3(matrix3_look_at(eye, centre, up)) } quaternion_look_at :: proc{ quaternion_look_at_f16, quaternion_look_at_f32, quaternion_look_at_f64, -}; +} quaternion_nlerp_f16 :: proc(a, b: Quaternionf16, t: f16) -> (c: Quaternionf16) { - c.x = a.x + (b.x-a.x)*t; - c.y = a.y + (b.y-a.y)*t; - c.z = a.z + (b.z-a.z)*t; - c.w = a.w + (b.w-a.w)*t; - return normalize(c); + c.x = a.x + (b.x-a.x)*t + c.y = a.y + (b.y-a.y)*t + c.z = a.z + (b.z-a.z)*t + c.w = a.w + (b.w-a.w)*t + return normalize(c) } quaternion_nlerp_f32 :: proc(a, b: Quaternionf32, t: f32) -> (c: Quaternionf32) { - c.x = a.x + (b.x-a.x)*t; - c.y = a.y + (b.y-a.y)*t; - c.z = a.z + (b.z-a.z)*t; - c.w = a.w + (b.w-a.w)*t; - return normalize(c); + c.x = a.x + (b.x-a.x)*t + c.y = a.y + (b.y-a.y)*t + c.z = a.z + (b.z-a.z)*t + c.w = a.w + (b.w-a.w)*t + return normalize(c) } quaternion_nlerp_f64 :: proc(a, b: Quaternionf64, t: f64) -> (c: Quaternionf64) { - c.x = a.x + (b.x-a.x)*t; - c.y = a.y + (b.y-a.y)*t; - c.z = a.z + (b.z-a.z)*t; - c.w = a.w + (b.w-a.w)*t; - return normalize(c); + c.x = a.x + (b.x-a.x)*t + c.y = a.y + (b.y-a.y)*t + c.z = a.z + (b.z-a.z)*t + c.w = a.w + (b.w-a.w)*t + return normalize(c) } quaternion_nlerp :: proc{ quaternion_nlerp_f16, quaternion_nlerp_f32, quaternion_nlerp_f64, -}; +} quaternion_slerp_f16 :: proc(x, y: Quaternionf16, t: f16) -> (q: Quaternionf16) { - a, b := x, y; - cos_angle := dot(a, b); + a, b := x, y + cos_angle := dot(a, b) if cos_angle < 0 { - b = -b; - cos_angle = -cos_angle; + b = -b + cos_angle = -cos_angle } if cos_angle > 1 - F32_EPSILON { - q.x = a.x + (b.x-a.x)*t; - q.y = a.y + (b.y-a.y)*t; - q.z = a.z + (b.z-a.z)*t; - q.w = a.w + (b.w-a.w)*t; - return; + q.x = a.x + (b.x-a.x)*t + q.y = a.y + (b.y-a.y)*t + q.z = a.z + (b.z-a.z)*t + q.w = a.w + (b.w-a.w)*t + return } - angle := math.acos(cos_angle); - sin_angle := math.sin(angle); - factor_a := math.sin((1-t) * angle) / sin_angle; - factor_b := math.sin(t * angle) / sin_angle; + angle := math.acos(cos_angle) + sin_angle := math.sin(angle) + factor_a := math.sin((1-t) * angle) / sin_angle + factor_b := math.sin(t * angle) / sin_angle - q.x = factor_a * a.x + factor_b * b.x; - q.y = factor_a * a.y + factor_b * b.y; - q.z = factor_a * a.z + factor_b * b.z; - q.w = factor_a * a.w + factor_b * b.w; - return; + q.x = factor_a * a.x + factor_b * b.x + q.y = factor_a * a.y + factor_b * b.y + q.z = factor_a * a.z + factor_b * b.z + q.w = factor_a * a.w + factor_b * b.w + return } quaternion_slerp_f32 :: proc(x, y: Quaternionf32, t: f32) -> (q: Quaternionf32) { - a, b := x, y; - cos_angle := dot(a, b); + a, b := x, y + cos_angle := dot(a, b) if cos_angle < 0 { - b = -b; - cos_angle = -cos_angle; + b = -b + cos_angle = -cos_angle } if cos_angle > 1 - F32_EPSILON { - q.x = a.x + (b.x-a.x)*t; - q.y = a.y + (b.y-a.y)*t; - q.z = a.z + (b.z-a.z)*t; - q.w = a.w + (b.w-a.w)*t; - return; + q.x = a.x + (b.x-a.x)*t + q.y = a.y + (b.y-a.y)*t + q.z = a.z + (b.z-a.z)*t + q.w = a.w + (b.w-a.w)*t + return } - angle := math.acos(cos_angle); - sin_angle := math.sin(angle); - factor_a := math.sin((1-t) * angle) / sin_angle; - factor_b := math.sin(t * angle) / sin_angle; + angle := math.acos(cos_angle) + sin_angle := math.sin(angle) + factor_a := math.sin((1-t) * angle) / sin_angle + factor_b := math.sin(t * angle) / sin_angle - q.x = factor_a * a.x + factor_b * b.x; - q.y = factor_a * a.y + factor_b * b.y; - q.z = factor_a * a.z + factor_b * b.z; - q.w = factor_a * a.w + factor_b * b.w; - return; + q.x = factor_a * a.x + factor_b * b.x + q.y = factor_a * a.y + factor_b * b.y + q.z = factor_a * a.z + factor_b * b.z + q.w = factor_a * a.w + factor_b * b.w + return } quaternion_slerp_f64 :: proc(x, y: Quaternionf64, t: f64) -> (q: Quaternionf64) { - a, b := x, y; - cos_angle := dot(a, b); + a, b := x, y + cos_angle := dot(a, b) if cos_angle < 0 { - b = -b; - cos_angle = -cos_angle; + b = -b + cos_angle = -cos_angle } if cos_angle > 1 - F64_EPSILON { - q.x = a.x + (b.x-a.x)*t; - q.y = a.y + (b.y-a.y)*t; - q.z = a.z + (b.z-a.z)*t; - q.w = a.w + (b.w-a.w)*t; - return; + q.x = a.x + (b.x-a.x)*t + q.y = a.y + (b.y-a.y)*t + q.z = a.z + (b.z-a.z)*t + q.w = a.w + (b.w-a.w)*t + return } - angle := math.acos(cos_angle); - sin_angle := math.sin(angle); - factor_a := math.sin((1-t) * angle) / sin_angle; - factor_b := math.sin(t * angle) / sin_angle; + angle := math.acos(cos_angle) + sin_angle := math.sin(angle) + factor_a := math.sin((1-t) * angle) / sin_angle + factor_b := math.sin(t * angle) / sin_angle - q.x = factor_a * a.x + factor_b * b.x; - q.y = factor_a * a.y + factor_b * b.y; - q.z = factor_a * a.z + factor_b * b.z; - q.w = factor_a * a.w + factor_b * b.w; - return; + q.x = factor_a * a.x + factor_b * b.x + q.y = factor_a * a.y + factor_b * b.y + q.z = factor_a * a.z + factor_b * b.z + q.w = factor_a * a.w + factor_b * b.w + return } quaternion_slerp :: proc{ quaternion_slerp_f16, quaternion_slerp_f32, quaternion_slerp_f64, -}; +} quaternion_squad_f16 :: proc(q1, q2, s1, s2: Quaternionf16, h: f16) -> Quaternionf16 { - slerp :: quaternion_slerp; - return slerp(slerp(q1, q2, h), slerp(s1, s2, h), 2 * (1 - h) * h); + slerp :: quaternion_slerp + return slerp(slerp(q1, q2, h), slerp(s1, s2, h), 2 * (1 - h) * h) } quaternion_squad_f32 :: proc(q1, q2, s1, s2: Quaternionf32, h: f32) -> Quaternionf32 { - slerp :: quaternion_slerp; - return slerp(slerp(q1, q2, h), slerp(s1, s2, h), 2 * (1 - h) * h); + slerp :: quaternion_slerp + return slerp(slerp(q1, q2, h), slerp(s1, s2, h), 2 * (1 - h) * h) } quaternion_squad_f64 :: proc(q1, q2, s1, s2: Quaternionf64, h: f64) -> Quaternionf64 { - slerp :: quaternion_slerp; - return slerp(slerp(q1, q2, h), slerp(s1, s2, h), 2 * (1 - h) * h); + slerp :: quaternion_slerp + return slerp(slerp(q1, q2, h), slerp(s1, s2, h), 2 * (1 - h) * h) } quaternion_squad :: proc{ quaternion_squad_f16, quaternion_squad_f32, quaternion_squad_f64, -}; +} quaternion_from_matrix4_f16 :: proc(m: Matrix4f16) -> (q: Quaternionf16) { - m3: Matrix3f16 = ---; - m3[0][0], m3[0][1], m3[0][2] = m[0][0], m[0][1], m[0][2]; - m3[1][0], m3[1][1], m3[1][2] = m[1][0], m[1][1], m[1][2]; - m3[2][0], m3[2][1], m3[2][2] = m[2][0], m[2][1], m[2][2]; - return quaternion_from_matrix3(m3); + m3: Matrix3f16 = --- + m3[0][0], m3[0][1], m3[0][2] = m[0][0], m[0][1], m[0][2] + m3[1][0], m3[1][1], m3[1][2] = m[1][0], m[1][1], m[1][2] + m3[2][0], m3[2][1], m3[2][2] = m[2][0], m[2][1], m[2][2] + return quaternion_from_matrix3(m3) } quaternion_from_matrix4_f32 :: proc(m: Matrix4f32) -> (q: Quaternionf32) { - m3: Matrix3f32 = ---; - m3[0][0], m3[0][1], m3[0][2] = m[0][0], m[0][1], m[0][2]; - m3[1][0], m3[1][1], m3[1][2] = m[1][0], m[1][1], m[1][2]; - m3[2][0], m3[2][1], m3[2][2] = m[2][0], m[2][1], m[2][2]; - return quaternion_from_matrix3(m3); + m3: Matrix3f32 = --- + m3[0][0], m3[0][1], m3[0][2] = m[0][0], m[0][1], m[0][2] + m3[1][0], m3[1][1], m3[1][2] = m[1][0], m[1][1], m[1][2] + m3[2][0], m3[2][1], m3[2][2] = m[2][0], m[2][1], m[2][2] + return quaternion_from_matrix3(m3) } quaternion_from_matrix4_f64 :: proc(m: Matrix4f64) -> (q: Quaternionf64) { - m3: Matrix3f64 = ---; - m3[0][0], m3[0][1], m3[0][2] = m[0][0], m[0][1], m[0][2]; - m3[1][0], m3[1][1], m3[1][2] = m[1][0], m[1][1], m[1][2]; - m3[2][0], m3[2][1], m3[2][2] = m[2][0], m[2][1], m[2][2]; - return quaternion_from_matrix3(m3); + m3: Matrix3f64 = --- + m3[0][0], m3[0][1], m3[0][2] = m[0][0], m[0][1], m[0][2] + m3[1][0], m3[1][1], m3[1][2] = m[1][0], m[1][1], m[1][2] + m3[2][0], m3[2][1], m3[2][2] = m[2][0], m[2][1], m[2][2] + return quaternion_from_matrix3(m3) } quaternion_from_matrix4 :: proc{ quaternion_from_matrix4_f16, quaternion_from_matrix4_f32, quaternion_from_matrix4_f64, -}; +} quaternion_from_matrix3_f16 :: proc(m: Matrix3f16) -> (q: Quaternionf16) { - four_x_squared_minus_1 := m[0][0] - m[1][1] - m[2][2]; - four_y_squared_minus_1 := m[1][1] - m[0][0] - m[2][2]; - four_z_squared_minus_1 := m[2][2] - m[0][0] - m[1][1]; - four_w_squared_minus_1 := m[0][0] + m[1][1] + m[2][2]; + four_x_squared_minus_1 := m[0][0] - m[1][1] - m[2][2] + four_y_squared_minus_1 := m[1][1] - m[0][0] - m[2][2] + four_z_squared_minus_1 := m[2][2] - m[0][0] - m[1][1] + four_w_squared_minus_1 := m[0][0] + m[1][1] + m[2][2] - biggest_index := 0; - four_biggest_squared_minus_1 := four_w_squared_minus_1; + biggest_index := 0 + four_biggest_squared_minus_1 := four_w_squared_minus_1 if four_x_squared_minus_1 > four_biggest_squared_minus_1 { - four_biggest_squared_minus_1 = four_x_squared_minus_1; - biggest_index = 1; + four_biggest_squared_minus_1 = four_x_squared_minus_1 + biggest_index = 1 } if four_y_squared_minus_1 > four_biggest_squared_minus_1 { - four_biggest_squared_minus_1 = four_y_squared_minus_1; - biggest_index = 2; + four_biggest_squared_minus_1 = four_y_squared_minus_1 + biggest_index = 2 } if four_z_squared_minus_1 > four_biggest_squared_minus_1 { - four_biggest_squared_minus_1 = four_z_squared_minus_1; - biggest_index = 3; + four_biggest_squared_minus_1 = four_z_squared_minus_1 + biggest_index = 3 } - biggest_val := math.sqrt(four_biggest_squared_minus_1 + 1) * 0.5; - mult := 0.25 / biggest_val; + biggest_val := math.sqrt(four_biggest_squared_minus_1 + 1) * 0.5 + mult := 0.25 / biggest_val - q = 1; + q = 1 switch biggest_index { case 0: - q.w = biggest_val; - q.x = (m[1][2] - m[2][1]) * mult; - q.y = (m[2][0] - m[0][2]) * mult; - q.z = (m[0][1] - m[1][0]) * mult; + q.w = biggest_val + q.x = (m[1][2] - m[2][1]) * mult + q.y = (m[2][0] - m[0][2]) * mult + q.z = (m[0][1] - m[1][0]) * mult case 1: - q.w = (m[1][2] - m[2][1]) * mult; - q.x = biggest_val; - q.y = (m[0][1] + m[1][0]) * mult; - q.z = (m[2][0] + m[0][2]) * mult; + q.w = (m[1][2] - m[2][1]) * mult + q.x = biggest_val + q.y = (m[0][1] + m[1][0]) * mult + q.z = (m[2][0] + m[0][2]) * mult case 2: - q.w = (m[2][0] - m[0][2]) * mult; - q.x = (m[0][1] + m[1][0]) * mult; - q.y = biggest_val; - q.z = (m[1][2] + m[2][1]) * mult; + q.w = (m[2][0] - m[0][2]) * mult + q.x = (m[0][1] + m[1][0]) * mult + q.y = biggest_val + q.z = (m[1][2] + m[2][1]) * mult case 3: - q.w = (m[0][1] - m[1][0]) * mult; - q.x = (m[2][0] + m[0][2]) * mult; - q.y = (m[1][2] + m[2][1]) * mult; - q.z = biggest_val; + q.w = (m[0][1] - m[1][0]) * mult + q.x = (m[2][0] + m[0][2]) * mult + q.y = (m[1][2] + m[2][1]) * mult + q.z = biggest_val } - return; + return } quaternion_from_matrix3_f32 :: proc(m: Matrix3f32) -> (q: Quaternionf32) { - four_x_squared_minus_1 := m[0][0] - m[1][1] - m[2][2]; - four_y_squared_minus_1 := m[1][1] - m[0][0] - m[2][2]; - four_z_squared_minus_1 := m[2][2] - m[0][0] - m[1][1]; - four_w_squared_minus_1 := m[0][0] + m[1][1] + m[2][2]; + four_x_squared_minus_1 := m[0][0] - m[1][1] - m[2][2] + four_y_squared_minus_1 := m[1][1] - m[0][0] - m[2][2] + four_z_squared_minus_1 := m[2][2] - m[0][0] - m[1][1] + four_w_squared_minus_1 := m[0][0] + m[1][1] + m[2][2] - biggest_index := 0; - four_biggest_squared_minus_1 := four_w_squared_minus_1; + biggest_index := 0 + four_biggest_squared_minus_1 := four_w_squared_minus_1 if four_x_squared_minus_1 > four_biggest_squared_minus_1 { - four_biggest_squared_minus_1 = four_x_squared_minus_1; - biggest_index = 1; + four_biggest_squared_minus_1 = four_x_squared_minus_1 + biggest_index = 1 } if four_y_squared_minus_1 > four_biggest_squared_minus_1 { - four_biggest_squared_minus_1 = four_y_squared_minus_1; - biggest_index = 2; + four_biggest_squared_minus_1 = four_y_squared_minus_1 + biggest_index = 2 } if four_z_squared_minus_1 > four_biggest_squared_minus_1 { - four_biggest_squared_minus_1 = four_z_squared_minus_1; - biggest_index = 3; + four_biggest_squared_minus_1 = four_z_squared_minus_1 + biggest_index = 3 } - biggest_val := math.sqrt(four_biggest_squared_minus_1 + 1) * 0.5; - mult := 0.25 / biggest_val; + biggest_val := math.sqrt(four_biggest_squared_minus_1 + 1) * 0.5 + mult := 0.25 / biggest_val - q = 1; + q = 1 switch biggest_index { case 0: - q.w = biggest_val; - q.x = (m[1][2] - m[2][1]) * mult; - q.y = (m[2][0] - m[0][2]) * mult; - q.z = (m[0][1] - m[1][0]) * mult; + q.w = biggest_val + q.x = (m[1][2] - m[2][1]) * mult + q.y = (m[2][0] - m[0][2]) * mult + q.z = (m[0][1] - m[1][0]) * mult case 1: - q.w = (m[1][2] - m[2][1]) * mult; - q.x = biggest_val; - q.y = (m[0][1] + m[1][0]) * mult; - q.z = (m[2][0] + m[0][2]) * mult; + q.w = (m[1][2] - m[2][1]) * mult + q.x = biggest_val + q.y = (m[0][1] + m[1][0]) * mult + q.z = (m[2][0] + m[0][2]) * mult case 2: - q.w = (m[2][0] - m[0][2]) * mult; - q.x = (m[0][1] + m[1][0]) * mult; - q.y = biggest_val; - q.z = (m[1][2] + m[2][1]) * mult; + q.w = (m[2][0] - m[0][2]) * mult + q.x = (m[0][1] + m[1][0]) * mult + q.y = biggest_val + q.z = (m[1][2] + m[2][1]) * mult case 3: - q.w = (m[0][1] - m[1][0]) * mult; - q.x = (m[2][0] + m[0][2]) * mult; - q.y = (m[1][2] + m[2][1]) * mult; - q.z = biggest_val; + q.w = (m[0][1] - m[1][0]) * mult + q.x = (m[2][0] + m[0][2]) * mult + q.y = (m[1][2] + m[2][1]) * mult + q.z = biggest_val } - return; + return } quaternion_from_matrix3_f64 :: proc(m: Matrix3f64) -> (q: Quaternionf64) { - four_x_squared_minus_1 := m[0][0] - m[1][1] - m[2][2]; - four_y_squared_minus_1 := m[1][1] - m[0][0] - m[2][2]; - four_z_squared_minus_1 := m[2][2] - m[0][0] - m[1][1]; - four_w_squared_minus_1 := m[0][0] + m[1][1] + m[2][2]; + four_x_squared_minus_1 := m[0][0] - m[1][1] - m[2][2] + four_y_squared_minus_1 := m[1][1] - m[0][0] - m[2][2] + four_z_squared_minus_1 := m[2][2] - m[0][0] - m[1][1] + four_w_squared_minus_1 := m[0][0] + m[1][1] + m[2][2] - biggest_index := 0; - four_biggest_squared_minus_1 := four_w_squared_minus_1; + biggest_index := 0 + four_biggest_squared_minus_1 := four_w_squared_minus_1 if four_x_squared_minus_1 > four_biggest_squared_minus_1 { - four_biggest_squared_minus_1 = four_x_squared_minus_1; - biggest_index = 1; + four_biggest_squared_minus_1 = four_x_squared_minus_1 + biggest_index = 1 } if four_y_squared_minus_1 > four_biggest_squared_minus_1 { - four_biggest_squared_minus_1 = four_y_squared_minus_1; - biggest_index = 2; + four_biggest_squared_minus_1 = four_y_squared_minus_1 + biggest_index = 2 } if four_z_squared_minus_1 > four_biggest_squared_minus_1 { - four_biggest_squared_minus_1 = four_z_squared_minus_1; - biggest_index = 3; + four_biggest_squared_minus_1 = four_z_squared_minus_1 + biggest_index = 3 } - biggest_val := math.sqrt(four_biggest_squared_minus_1 + 1) * 0.5; - mult := 0.25 / biggest_val; + biggest_val := math.sqrt(four_biggest_squared_minus_1 + 1) * 0.5 + mult := 0.25 / biggest_val - q = 1; + q = 1 switch biggest_index { case 0: - q.w = biggest_val; - q.x = (m[1][2] - m[2][1]) * mult; - q.y = (m[2][0] - m[0][2]) * mult; - q.z = (m[0][1] - m[1][0]) * mult; + q.w = biggest_val + q.x = (m[1][2] - m[2][1]) * mult + q.y = (m[2][0] - m[0][2]) * mult + q.z = (m[0][1] - m[1][0]) * mult case 1: - q.w = (m[1][2] - m[2][1]) * mult; - q.x = biggest_val; - q.y = (m[0][1] + m[1][0]) * mult; - q.z = (m[2][0] + m[0][2]) * mult; + q.w = (m[1][2] - m[2][1]) * mult + q.x = biggest_val + q.y = (m[0][1] + m[1][0]) * mult + q.z = (m[2][0] + m[0][2]) * mult case 2: - q.w = (m[2][0] - m[0][2]) * mult; - q.x = (m[0][1] + m[1][0]) * mult; - q.y = biggest_val; - q.z = (m[1][2] + m[2][1]) * mult; + q.w = (m[2][0] - m[0][2]) * mult + q.x = (m[0][1] + m[1][0]) * mult + q.y = biggest_val + q.z = (m[1][2] + m[2][1]) * mult case 3: - q.w = (m[0][1] - m[1][0]) * mult; - q.x = (m[2][0] + m[0][2]) * mult; - q.y = (m[1][2] + m[2][1]) * mult; - q.z = biggest_val; + q.w = (m[0][1] - m[1][0]) * mult + q.x = (m[2][0] + m[0][2]) * mult + q.y = (m[1][2] + m[2][1]) * mult + q.z = biggest_val } - return; + return } quaternion_from_matrix3 :: proc{ quaternion_from_matrix3_f16, quaternion_from_matrix3_f32, quaternion_from_matrix3_f64, -}; +} quaternion_between_two_vector3_f16 :: proc(from, to: Vector3f16) -> (q: Quaternionf16) { - x := normalize(from); - y := normalize(to); + x := normalize(from) + y := normalize(to) - cos_theta := dot(x, y); + cos_theta := dot(x, y) if abs(cos_theta + 1) < 2*F32_EPSILON { - v := vector3_orthogonal(x); - q.x = v.x; - q.y = v.y; - q.z = v.z; - q.w = 0; - return; - } - v := cross(x, y); - w := cos_theta + 1; - q.w = w; - q.x = v.x; - q.y = v.y; - q.z = v.z; - return normalize(q); + v := vector3_orthogonal(x) + q.x = v.x + q.y = v.y + q.z = v.z + q.w = 0 + return + } + v := cross(x, y) + w := cos_theta + 1 + q.w = w + q.x = v.x + q.y = v.y + q.z = v.z + return normalize(q) } quaternion_between_two_vector3_f32 :: proc(from, to: Vector3f32) -> (q: Quaternionf32) { - x := normalize(from); - y := normalize(to); + x := normalize(from) + y := normalize(to) - cos_theta := dot(x, y); + cos_theta := dot(x, y) if abs(cos_theta + 1) < 2*F32_EPSILON { - v := vector3_orthogonal(x); - q.x = v.x; - q.y = v.y; - q.z = v.z; - q.w = 0; - return; - } - v := cross(x, y); - w := cos_theta + 1; - q.w = w; - q.x = v.x; - q.y = v.y; - q.z = v.z; - return normalize(q); + v := vector3_orthogonal(x) + q.x = v.x + q.y = v.y + q.z = v.z + q.w = 0 + return + } + v := cross(x, y) + w := cos_theta + 1 + q.w = w + q.x = v.x + q.y = v.y + q.z = v.z + return normalize(q) } quaternion_between_two_vector3_f64 :: proc(from, to: Vector3f64) -> (q: Quaternionf64) { - x := normalize(from); - y := normalize(to); + x := normalize(from) + y := normalize(to) - cos_theta := dot(x, y); + cos_theta := dot(x, y) if abs(cos_theta + 1) < 2*F64_EPSILON { - v := vector3_orthogonal(x); - q.x = v.x; - q.y = v.y; - q.z = v.z; - q.w = 0; - return; - } - v := cross(x, y); - w := cos_theta + 1; - q.w = w; - q.x = v.x; - q.y = v.y; - q.z = v.z; - return normalize(q); + v := vector3_orthogonal(x) + q.x = v.x + q.y = v.y + q.z = v.z + q.w = 0 + return + } + v := cross(x, y) + w := cos_theta + 1 + q.w = w + q.x = v.x + q.y = v.y + q.z = v.z + return normalize(q) } quaternion_between_two_vector3 :: proc{ quaternion_between_two_vector3_f16, quaternion_between_two_vector3_f32, quaternion_between_two_vector3_f64, -}; +} matrix2_inverse_transpose_f16 :: proc(m: Matrix2f16) -> (c: Matrix2f16) { - d := m[0][0]*m[1][1] - m[1][0]*m[0][1]; - id := 1.0/d; - c[0][0] = +m[1][1] * id; - c[0][1] = -m[0][1] * id; - c[1][0] = -m[1][0] * id; - c[1][1] = +m[0][0] * id; - return c; + d := m[0][0]*m[1][1] - m[1][0]*m[0][1] + id := 1.0/d + c[0][0] = +m[1][1] * id + c[0][1] = -m[0][1] * id + c[1][0] = -m[1][0] * id + c[1][1] = +m[0][0] * id + return c } matrix2_inverse_transpose_f32 :: proc(m: Matrix2f32) -> (c: Matrix2f32) { - d := m[0][0]*m[1][1] - m[1][0]*m[0][1]; - id := 1.0/d; - c[0][0] = +m[1][1] * id; - c[0][1] = -m[0][1] * id; - c[1][0] = -m[1][0] * id; - c[1][1] = +m[0][0] * id; - return c; + d := m[0][0]*m[1][1] - m[1][0]*m[0][1] + id := 1.0/d + c[0][0] = +m[1][1] * id + c[0][1] = -m[0][1] * id + c[1][0] = -m[1][0] * id + c[1][1] = +m[0][0] * id + return c } matrix2_inverse_transpose_f64 :: proc(m: Matrix2f64) -> (c: Matrix2f64) { - d := m[0][0]*m[1][1] - m[1][0]*m[0][1]; - id := 1.0/d; - c[0][0] = +m[1][1] * id; - c[0][1] = -m[0][1] * id; - c[1][0] = -m[1][0] * id; - c[1][1] = +m[0][0] * id; - return c; + d := m[0][0]*m[1][1] - m[1][0]*m[0][1] + id := 1.0/d + c[0][0] = +m[1][1] * id + c[0][1] = -m[0][1] * id + c[1][0] = -m[1][0] * id + c[1][1] = +m[0][0] * id + return c } matrix2_inverse_transpose :: proc{ matrix2_inverse_transpose_f16, matrix2_inverse_transpose_f32, matrix2_inverse_transpose_f64, -}; +} matrix2_determinant_f16 :: proc(m: Matrix2f16) -> f16 { - return m[0][0]*m[1][1] - m[1][0]*m[0][1]; + return m[0][0]*m[1][1] - m[1][0]*m[0][1] } matrix2_determinant_f32 :: proc(m: Matrix2f32) -> f32 { - return m[0][0]*m[1][1] - m[1][0]*m[0][1]; + return m[0][0]*m[1][1] - m[1][0]*m[0][1] } matrix2_determinant_f64 :: proc(m: Matrix2f64) -> f64 { - return m[0][0]*m[1][1] - m[1][0]*m[0][1]; + return m[0][0]*m[1][1] - m[1][0]*m[0][1] } matrix2_determinant :: proc{ matrix2_determinant_f16, matrix2_determinant_f32, matrix2_determinant_f64, -}; +} matrix2_inverse_f16 :: proc(m: Matrix2f16) -> (c: Matrix2f16) { - d := m[0][0]*m[1][1] - m[1][0]*m[0][1]; - id := 1.0/d; - c[0][0] = +m[1][1] * id; - c[1][0] = -m[0][1] * id; - c[0][1] = -m[1][0] * id; - c[1][1] = +m[0][0] * id; - return c; + d := m[0][0]*m[1][1] - m[1][0]*m[0][1] + id := 1.0/d + c[0][0] = +m[1][1] * id + c[1][0] = -m[0][1] * id + c[0][1] = -m[1][0] * id + c[1][1] = +m[0][0] * id + return c } matrix2_inverse_f32 :: proc(m: Matrix2f32) -> (c: Matrix2f32) { - d := m[0][0]*m[1][1] - m[1][0]*m[0][1]; - id := 1.0/d; - c[0][0] = +m[1][1] * id; - c[1][0] = -m[0][1] * id; - c[0][1] = -m[1][0] * id; - c[1][1] = +m[0][0] * id; - return c; + d := m[0][0]*m[1][1] - m[1][0]*m[0][1] + id := 1.0/d + c[0][0] = +m[1][1] * id + c[1][0] = -m[0][1] * id + c[0][1] = -m[1][0] * id + c[1][1] = +m[0][0] * id + return c } matrix2_inverse_f64 :: proc(m: Matrix2f64) -> (c: Matrix2f64) { - d := m[0][0]*m[1][1] - m[1][0]*m[0][1]; - id := 1.0/d; - c[0][0] = +m[1][1] * id; - c[1][0] = -m[0][1] * id; - c[0][1] = -m[1][0] * id; - c[1][1] = +m[0][0] * id; - return c; + d := m[0][0]*m[1][1] - m[1][0]*m[0][1] + id := 1.0/d + c[0][0] = +m[1][1] * id + c[1][0] = -m[0][1] * id + c[0][1] = -m[1][0] * id + c[1][1] = +m[0][0] * id + return c } matrix2_inverse :: proc{ matrix2_inverse_f16, matrix2_inverse_f32, matrix2_inverse_f64, -}; +} matrix2_adjoint_f16 :: proc(m: Matrix2f16) -> (c: Matrix2f16) { - c[0][0] = +m[1][1]; - c[0][1] = -m[1][0]; - c[1][0] = -m[0][1]; - c[1][1] = +m[0][0]; - return c; + c[0][0] = +m[1][1] + c[0][1] = -m[1][0] + c[1][0] = -m[0][1] + c[1][1] = +m[0][0] + return c } matrix2_adjoint_f32 :: proc(m: Matrix2f32) -> (c: Matrix2f32) { - c[0][0] = +m[1][1]; - c[0][1] = -m[1][0]; - c[1][0] = -m[0][1]; - c[1][1] = +m[0][0]; - return c; + c[0][0] = +m[1][1] + c[0][1] = -m[1][0] + c[1][0] = -m[0][1] + c[1][1] = +m[0][0] + return c } matrix2_adjoint_f64 :: proc(m: Matrix2f64) -> (c: Matrix2f64) { - c[0][0] = +m[1][1]; - c[0][1] = -m[1][0]; - c[1][0] = -m[0][1]; - c[1][1] = +m[0][0]; - return c; + c[0][0] = +m[1][1] + c[0][1] = -m[1][0] + c[1][0] = -m[0][1] + c[1][1] = +m[0][0] + return c } matrix2_adjoint :: proc{ matrix2_adjoint_f16, matrix2_adjoint_f32, matrix2_adjoint_f64, -}; +} matrix3_from_quaternion_f16 :: proc(q: Quaternionf16) -> (m: Matrix3f16) { - qxx := q.x * q.x; - qyy := q.y * q.y; - qzz := q.z * q.z; - qxz := q.x * q.z; - qxy := q.x * q.y; - qyz := q.y * q.z; - qwx := q.w * q.x; - qwy := q.w * q.y; - qwz := q.w * q.z; - - m[0][0] = 1 - 2 * (qyy + qzz); - m[0][1] = 2 * (qxy + qwz); - m[0][2] = 2 * (qxz - qwy); - - m[1][0] = 2 * (qxy - qwz); - m[1][1] = 1 - 2 * (qxx + qzz); - m[1][2] = 2 * (qyz + qwx); - - m[2][0] = 2 * (qxz + qwy); - m[2][1] = 2 * (qyz - qwx); - m[2][2] = 1 - 2 * (qxx + qyy); - return m; + qxx := q.x * q.x + qyy := q.y * q.y + qzz := q.z * q.z + qxz := q.x * q.z + qxy := q.x * q.y + qyz := q.y * q.z + qwx := q.w * q.x + qwy := q.w * q.y + qwz := q.w * q.z + + m[0][0] = 1 - 2 * (qyy + qzz) + m[0][1] = 2 * (qxy + qwz) + m[0][2] = 2 * (qxz - qwy) + + m[1][0] = 2 * (qxy - qwz) + m[1][1] = 1 - 2 * (qxx + qzz) + m[1][2] = 2 * (qyz + qwx) + + m[2][0] = 2 * (qxz + qwy) + m[2][1] = 2 * (qyz - qwx) + m[2][2] = 1 - 2 * (qxx + qyy) + return m } matrix3_from_quaternion_f32 :: proc(q: Quaternionf32) -> (m: Matrix3f32) { - qxx := q.x * q.x; - qyy := q.y * q.y; - qzz := q.z * q.z; - qxz := q.x * q.z; - qxy := q.x * q.y; - qyz := q.y * q.z; - qwx := q.w * q.x; - qwy := q.w * q.y; - qwz := q.w * q.z; - - m[0][0] = 1 - 2 * (qyy + qzz); - m[0][1] = 2 * (qxy + qwz); - m[0][2] = 2 * (qxz - qwy); - - m[1][0] = 2 * (qxy - qwz); - m[1][1] = 1 - 2 * (qxx + qzz); - m[1][2] = 2 * (qyz + qwx); - - m[2][0] = 2 * (qxz + qwy); - m[2][1] = 2 * (qyz - qwx); - m[2][2] = 1 - 2 * (qxx + qyy); - return m; + qxx := q.x * q.x + qyy := q.y * q.y + qzz := q.z * q.z + qxz := q.x * q.z + qxy := q.x * q.y + qyz := q.y * q.z + qwx := q.w * q.x + qwy := q.w * q.y + qwz := q.w * q.z + + m[0][0] = 1 - 2 * (qyy + qzz) + m[0][1] = 2 * (qxy + qwz) + m[0][2] = 2 * (qxz - qwy) + + m[1][0] = 2 * (qxy - qwz) + m[1][1] = 1 - 2 * (qxx + qzz) + m[1][2] = 2 * (qyz + qwx) + + m[2][0] = 2 * (qxz + qwy) + m[2][1] = 2 * (qyz - qwx) + m[2][2] = 1 - 2 * (qxx + qyy) + return m } matrix3_from_quaternion_f64 :: proc(q: Quaternionf64) -> (m: Matrix3f64) { - qxx := q.x * q.x; - qyy := q.y * q.y; - qzz := q.z * q.z; - qxz := q.x * q.z; - qxy := q.x * q.y; - qyz := q.y * q.z; - qwx := q.w * q.x; - qwy := q.w * q.y; - qwz := q.w * q.z; - - m[0][0] = 1 - 2 * (qyy + qzz); - m[0][1] = 2 * (qxy + qwz); - m[0][2] = 2 * (qxz - qwy); - - m[1][0] = 2 * (qxy - qwz); - m[1][1] = 1 - 2 * (qxx + qzz); - m[1][2] = 2 * (qyz + qwx); - - m[2][0] = 2 * (qxz + qwy); - m[2][1] = 2 * (qyz - qwx); - m[2][2] = 1 - 2 * (qxx + qyy); - return m; + qxx := q.x * q.x + qyy := q.y * q.y + qzz := q.z * q.z + qxz := q.x * q.z + qxy := q.x * q.y + qyz := q.y * q.z + qwx := q.w * q.x + qwy := q.w * q.y + qwz := q.w * q.z + + m[0][0] = 1 - 2 * (qyy + qzz) + m[0][1] = 2 * (qxy + qwz) + m[0][2] = 2 * (qxz - qwy) + + m[1][0] = 2 * (qxy - qwz) + m[1][1] = 1 - 2 * (qxx + qzz) + m[1][2] = 2 * (qyz + qwx) + + m[2][0] = 2 * (qxz + qwy) + m[2][1] = 2 * (qyz - qwx) + m[2][2] = 1 - 2 * (qxx + qyy) + return m } matrix3_from_quaternion :: proc{ matrix3_from_quaternion_f16, matrix3_from_quaternion_f32, matrix3_from_quaternion_f64, -}; +} matrix3_inverse_f16 :: proc(m: Matrix3f16) -> Matrix3f16 { - return auto_cast transpose(matrix3_inverse_transpose(m)); + return auto_cast transpose(matrix3_inverse_transpose(m)) } matrix3_inverse_f32 :: proc(m: Matrix3f32) -> Matrix3f32 { - return auto_cast transpose(matrix3_inverse_transpose(m)); + return auto_cast transpose(matrix3_inverse_transpose(m)) } matrix3_inverse_f64 :: proc(m: Matrix3f64) -> Matrix3f64 { - return auto_cast transpose(matrix3_inverse_transpose(m)); + return auto_cast transpose(matrix3_inverse_transpose(m)) } matrix3_inverse :: proc{ matrix3_inverse_f16, matrix3_inverse_f32, matrix3_inverse_f64, -}; +} matrix3_determinant_f16 :: proc(m: Matrix3f16) -> f16 { - a := +m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]); - b := -m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]); - c := +m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]); - return a + b + c; + a := +m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) + b := -m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]) + c := +m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]) + return a + b + c } matrix3_determinant_f32 :: proc(m: Matrix3f32) -> f32 { - a := +m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]); - b := -m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]); - c := +m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]); - return a + b + c; + a := +m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) + b := -m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]) + c := +m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]) + return a + b + c } matrix3_determinant_f64 :: proc(m: Matrix3f64) -> f64 { - a := +m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]); - b := -m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]); - c := +m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]); - return a + b + c; + a := +m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) + b := -m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]) + c := +m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]) + return a + b + c } matrix3_determinant :: proc{ matrix3_determinant_f16, matrix3_determinant_f32, matrix3_determinant_f64, -}; +} matrix3_adjoint_f16 :: proc(m: Matrix3f16) -> (adjoint: Matrix3f16) { - adjoint[0][0] = +(m[1][1] * m[2][2] - m[1][2] * m[2][1]); - adjoint[1][0] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]); - adjoint[2][0] = +(m[0][1] * m[1][2] - m[0][2] * m[1][1]); - adjoint[0][1] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]); - adjoint[1][1] = +(m[0][0] * m[2][2] - m[0][2] * m[2][0]); - adjoint[2][1] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]); - adjoint[0][2] = +(m[1][0] * m[2][1] - m[1][1] * m[2][0]); - adjoint[1][2] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]); - adjoint[2][2] = +(m[0][0] * m[1][1] - m[0][1] * m[1][0]); - return adjoint; + adjoint[0][0] = +(m[1][1] * m[2][2] - m[1][2] * m[2][1]) + adjoint[1][0] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]) + adjoint[2][0] = +(m[0][1] * m[1][2] - m[0][2] * m[1][1]) + adjoint[0][1] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]) + adjoint[1][1] = +(m[0][0] * m[2][2] - m[0][2] * m[2][0]) + adjoint[2][1] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]) + adjoint[0][2] = +(m[1][0] * m[2][1] - m[1][1] * m[2][0]) + adjoint[1][2] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]) + adjoint[2][2] = +(m[0][0] * m[1][1] - m[0][1] * m[1][0]) + return adjoint } matrix3_adjoint_f32 :: proc(m: Matrix3f32) -> (adjoint: Matrix3f32) { - adjoint[0][0] = +(m[1][1] * m[2][2] - m[1][2] * m[2][1]); - adjoint[1][0] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]); - adjoint[2][0] = +(m[0][1] * m[1][2] - m[0][2] * m[1][1]); - adjoint[0][1] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]); - adjoint[1][1] = +(m[0][0] * m[2][2] - m[0][2] * m[2][0]); - adjoint[2][1] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]); - adjoint[0][2] = +(m[1][0] * m[2][1] - m[1][1] * m[2][0]); - adjoint[1][2] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]); - adjoint[2][2] = +(m[0][0] * m[1][1] - m[0][1] * m[1][0]); - return adjoint; + adjoint[0][0] = +(m[1][1] * m[2][2] - m[1][2] * m[2][1]) + adjoint[1][0] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]) + adjoint[2][0] = +(m[0][1] * m[1][2] - m[0][2] * m[1][1]) + adjoint[0][1] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]) + adjoint[1][1] = +(m[0][0] * m[2][2] - m[0][2] * m[2][0]) + adjoint[2][1] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]) + adjoint[0][2] = +(m[1][0] * m[2][1] - m[1][1] * m[2][0]) + adjoint[1][2] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]) + adjoint[2][2] = +(m[0][0] * m[1][1] - m[0][1] * m[1][0]) + return adjoint } matrix3_adjoint_f64 :: proc(m: Matrix3f64) -> (adjoint: Matrix3f64) { - adjoint[0][0] = +(m[1][1] * m[2][2] - m[1][2] * m[2][1]); - adjoint[1][0] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]); - adjoint[2][0] = +(m[0][1] * m[1][2] - m[0][2] * m[1][1]); - adjoint[0][1] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]); - adjoint[1][1] = +(m[0][0] * m[2][2] - m[0][2] * m[2][0]); - adjoint[2][1] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]); - adjoint[0][2] = +(m[1][0] * m[2][1] - m[1][1] * m[2][0]); - adjoint[1][2] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]); - adjoint[2][2] = +(m[0][0] * m[1][1] - m[0][1] * m[1][0]); - return adjoint; + adjoint[0][0] = +(m[1][1] * m[2][2] - m[1][2] * m[2][1]) + adjoint[1][0] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]) + adjoint[2][0] = +(m[0][1] * m[1][2] - m[0][2] * m[1][1]) + adjoint[0][1] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]) + adjoint[1][1] = +(m[0][0] * m[2][2] - m[0][2] * m[2][0]) + adjoint[2][1] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]) + adjoint[0][2] = +(m[1][0] * m[2][1] - m[1][1] * m[2][0]) + adjoint[1][2] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]) + adjoint[2][2] = +(m[0][0] * m[1][1] - m[0][1] * m[1][0]) + return adjoint } matrix3_adjoint :: proc{ matrix3_adjoint_f16, matrix3_adjoint_f32, matrix3_adjoint_f64, -}; +} matrix3_inverse_transpose_f16 :: proc(m: Matrix3f16) -> (inverse_transpose: Matrix3f16) { - adjoint := matrix3_adjoint(m); - determinant := matrix3_determinant(m); - inv_determinant := 1.0 / determinant; + adjoint := matrix3_adjoint(m) + determinant := matrix3_determinant(m) + inv_determinant := 1.0 / determinant for i in 0..<3 { for j in 0..<3 { - inverse_transpose[i][j] = adjoint[i][j] * inv_determinant; + inverse_transpose[i][j] = adjoint[i][j] * inv_determinant } } - return; + return } matrix3_inverse_transpose_f32 :: proc(m: Matrix3f32) -> (inverse_transpose: Matrix3f32) { - adjoint := matrix3_adjoint(m); - determinant := matrix3_determinant(m); - inv_determinant := 1.0 / determinant; + adjoint := matrix3_adjoint(m) + determinant := matrix3_determinant(m) + inv_determinant := 1.0 / determinant for i in 0..<3 { for j in 0..<3 { - inverse_transpose[i][j] = adjoint[i][j] * inv_determinant; + inverse_transpose[i][j] = adjoint[i][j] * inv_determinant } } - return; + return } matrix3_inverse_transpose_f64 :: proc(m: Matrix3f64) -> (inverse_transpose: Matrix3f64) { - adjoint := matrix3_adjoint(m); - determinant := matrix3_determinant(m); - inv_determinant := 1.0 / determinant; + adjoint := matrix3_adjoint(m) + determinant := matrix3_determinant(m) + inv_determinant := 1.0 / determinant for i in 0..<3 { for j in 0..<3 { - inverse_transpose[i][j] = adjoint[i][j] * inv_determinant; + inverse_transpose[i][j] = adjoint[i][j] * inv_determinant } } - return; + return } matrix3_inverse_transpose :: proc{ matrix3_inverse_transpose_f16, matrix3_inverse_transpose_f32, matrix3_inverse_transpose_f64, -}; +} matrix3_scale_f16 :: proc(s: Vector3f16) -> (m: Matrix3f16) { - m[0][0] = s[0]; - m[1][1] = s[1]; - m[2][2] = s[2]; - return m; + m[0][0] = s[0] + m[1][1] = s[1] + m[2][2] = s[2] + return m } matrix3_scale_f32 :: proc(s: Vector3f32) -> (m: Matrix3f32) { - m[0][0] = s[0]; - m[1][1] = s[1]; - m[2][2] = s[2]; - return m; + m[0][0] = s[0] + m[1][1] = s[1] + m[2][2] = s[2] + return m } matrix3_scale_f64 :: proc(s: Vector3f64) -> (m: Matrix3f64) { - m[0][0] = s[0]; - m[1][1] = s[1]; - m[2][2] = s[2]; - return m; + m[0][0] = s[0] + m[1][1] = s[1] + m[2][2] = s[2] + return m } matrix3_scale :: proc{ matrix3_scale_f16, matrix3_scale_f32, matrix3_scale_f64, -}; +} matrix3_rotate_f16 :: proc(angle_radians: f16, v: Vector3f16) -> (rot: Matrix3f16) { - c := math.cos(angle_radians); - s := math.sin(angle_radians); + c := math.cos(angle_radians) + s := math.sin(angle_radians) - a := normalize(v); - t := a * (1-c); + a := normalize(v) + t := a * (1-c) - rot[0][0] = c + t[0]*a[0]; - rot[0][1] = 0 + t[0]*a[1] + s*a[2]; - rot[0][2] = 0 + t[0]*a[2] - s*a[1]; + rot[0][0] = c + t[0]*a[0] + rot[0][1] = 0 + t[0]*a[1] + s*a[2] + rot[0][2] = 0 + t[0]*a[2] - s*a[1] - rot[1][0] = 0 + t[1]*a[0] - s*a[2]; - rot[1][1] = c + t[1]*a[1]; - rot[1][2] = 0 + t[1]*a[2] + s*a[0]; + rot[1][0] = 0 + t[1]*a[0] - s*a[2] + rot[1][1] = c + t[1]*a[1] + rot[1][2] = 0 + t[1]*a[2] + s*a[0] - rot[2][0] = 0 + t[2]*a[0] + s*a[1]; - rot[2][1] = 0 + t[2]*a[1] - s*a[0]; - rot[2][2] = c + t[2]*a[2]; + rot[2][0] = 0 + t[2]*a[0] + s*a[1] + rot[2][1] = 0 + t[2]*a[1] - s*a[0] + rot[2][2] = c + t[2]*a[2] - return rot; + return rot } matrix3_rotate_f32 :: proc(angle_radians: f32, v: Vector3f32) -> (rot: Matrix3f32) { - c := math.cos(angle_radians); - s := math.sin(angle_radians); + c := math.cos(angle_radians) + s := math.sin(angle_radians) - a := normalize(v); - t := a * (1-c); + a := normalize(v) + t := a * (1-c) - rot[0][0] = c + t[0]*a[0]; - rot[0][1] = 0 + t[0]*a[1] + s*a[2]; - rot[0][2] = 0 + t[0]*a[2] - s*a[1]; + rot[0][0] = c + t[0]*a[0] + rot[0][1] = 0 + t[0]*a[1] + s*a[2] + rot[0][2] = 0 + t[0]*a[2] - s*a[1] - rot[1][0] = 0 + t[1]*a[0] - s*a[2]; - rot[1][1] = c + t[1]*a[1]; - rot[1][2] = 0 + t[1]*a[2] + s*a[0]; + rot[1][0] = 0 + t[1]*a[0] - s*a[2] + rot[1][1] = c + t[1]*a[1] + rot[1][2] = 0 + t[1]*a[2] + s*a[0] - rot[2][0] = 0 + t[2]*a[0] + s*a[1]; - rot[2][1] = 0 + t[2]*a[1] - s*a[0]; - rot[2][2] = c + t[2]*a[2]; + rot[2][0] = 0 + t[2]*a[0] + s*a[1] + rot[2][1] = 0 + t[2]*a[1] - s*a[0] + rot[2][2] = c + t[2]*a[2] - return rot; + return rot } matrix3_rotate_f64 :: proc(angle_radians: f64, v: Vector3f64) -> (rot: Matrix3f64) { - c := math.cos(angle_radians); - s := math.sin(angle_radians); + c := math.cos(angle_radians) + s := math.sin(angle_radians) - a := normalize(v); - t := a * (1-c); + a := normalize(v) + t := a * (1-c) - rot[0][0] = c + t[0]*a[0]; - rot[0][1] = 0 + t[0]*a[1] + s*a[2]; - rot[0][2] = 0 + t[0]*a[2] - s*a[1]; + rot[0][0] = c + t[0]*a[0] + rot[0][1] = 0 + t[0]*a[1] + s*a[2] + rot[0][2] = 0 + t[0]*a[2] - s*a[1] - rot[1][0] = 0 + t[1]*a[0] - s*a[2]; - rot[1][1] = c + t[1]*a[1]; - rot[1][2] = 0 + t[1]*a[2] + s*a[0]; + rot[1][0] = 0 + t[1]*a[0] - s*a[2] + rot[1][1] = c + t[1]*a[1] + rot[1][2] = 0 + t[1]*a[2] + s*a[0] - rot[2][0] = 0 + t[2]*a[0] + s*a[1]; - rot[2][1] = 0 + t[2]*a[1] - s*a[0]; - rot[2][2] = c + t[2]*a[2]; + rot[2][0] = 0 + t[2]*a[0] + s*a[1] + rot[2][1] = 0 + t[2]*a[1] - s*a[0] + rot[2][2] = c + t[2]*a[2] - return rot; + return rot } matrix3_rotate :: proc{ matrix3_rotate_f16, matrix3_rotate_f32, matrix3_rotate_f64, -}; +} matrix3_look_at_f16 :: proc(eye, centre, up: Vector3f16) -> Matrix3f16 { - f := normalize(centre - eye); - s := normalize(cross(f, up)); - u := cross(s, f); + f := normalize(centre - eye) + s := normalize(cross(f, up)) + u := cross(s, f) return Matrix3f16{ {+s.x, +u.x, -f.x}, {+s.y, +u.y, -f.y}, {+s.z, +u.z, -f.z}, - }; + } } matrix3_look_at_f32 :: proc(eye, centre, up: Vector3f32) -> Matrix3f32 { - f := normalize(centre - eye); - s := normalize(cross(f, up)); - u := cross(s, f); + f := normalize(centre - eye) + s := normalize(cross(f, up)) + u := cross(s, f) return Matrix3f32{ {+s.x, +u.x, -f.x}, {+s.y, +u.y, -f.y}, {+s.z, +u.z, -f.z}, - }; + } } matrix3_look_at_f64 :: proc(eye, centre, up: Vector3f64) -> Matrix3f64 { - f := normalize(centre - eye); - s := normalize(cross(f, up)); - u := cross(s, f); + f := normalize(centre - eye) + s := normalize(cross(f, up)) + u := cross(s, f) return Matrix3f64{ {+s.x, +u.x, -f.x}, {+s.y, +u.y, -f.y}, {+s.z, +u.z, -f.z}, - }; + } } matrix3_look_at :: proc{ matrix3_look_at_f16, matrix3_look_at_f32, matrix3_look_at_f64, -}; +} matrix4_from_quaternion_f16 :: proc(q: Quaternionf16) -> (m: Matrix4f16) { - qxx := q.x * q.x; - qyy := q.y * q.y; - qzz := q.z * q.z; - qxz := q.x * q.z; - qxy := q.x * q.y; - qyz := q.y * q.z; - qwx := q.w * q.x; - qwy := q.w * q.y; - qwz := q.w * q.z; + qxx := q.x * q.x + qyy := q.y * q.y + qzz := q.z * q.z + qxz := q.x * q.z + qxy := q.x * q.y + qyz := q.y * q.z + qwx := q.w * q.x + qwy := q.w * q.y + qwz := q.w * q.z - m[0][0] = 1 - 2 * (qyy + qzz); - m[0][1] = 2 * (qxy + qwz); - m[0][2] = 2 * (qxz - qwy); + m[0][0] = 1 - 2 * (qyy + qzz) + m[0][1] = 2 * (qxy + qwz) + m[0][2] = 2 * (qxz - qwy) - m[1][0] = 2 * (qxy - qwz); - m[1][1] = 1 - 2 * (qxx + qzz); - m[1][2] = 2 * (qyz + qwx); + m[1][0] = 2 * (qxy - qwz) + m[1][1] = 1 - 2 * (qxx + qzz) + m[1][2] = 2 * (qyz + qwx) - m[2][0] = 2 * (qxz + qwy); - m[2][1] = 2 * (qyz - qwx); - m[2][2] = 1 - 2 * (qxx + qyy); + m[2][0] = 2 * (qxz + qwy) + m[2][1] = 2 * (qyz - qwx) + m[2][2] = 1 - 2 * (qxx + qyy) - m[3][3] = 1; + m[3][3] = 1 - return m; + return m } matrix4_from_quaternion_f32 :: proc(q: Quaternionf32) -> (m: Matrix4f32) { - qxx := q.x * q.x; - qyy := q.y * q.y; - qzz := q.z * q.z; - qxz := q.x * q.z; - qxy := q.x * q.y; - qyz := q.y * q.z; - qwx := q.w * q.x; - qwy := q.w * q.y; - qwz := q.w * q.z; + qxx := q.x * q.x + qyy := q.y * q.y + qzz := q.z * q.z + qxz := q.x * q.z + qxy := q.x * q.y + qyz := q.y * q.z + qwx := q.w * q.x + qwy := q.w * q.y + qwz := q.w * q.z - m[0][0] = 1 - 2 * (qyy + qzz); - m[0][1] = 2 * (qxy + qwz); - m[0][2] = 2 * (qxz - qwy); + m[0][0] = 1 - 2 * (qyy + qzz) + m[0][1] = 2 * (qxy + qwz) + m[0][2] = 2 * (qxz - qwy) - m[1][0] = 2 * (qxy - qwz); - m[1][1] = 1 - 2 * (qxx + qzz); - m[1][2] = 2 * (qyz + qwx); + m[1][0] = 2 * (qxy - qwz) + m[1][1] = 1 - 2 * (qxx + qzz) + m[1][2] = 2 * (qyz + qwx) - m[2][0] = 2 * (qxz + qwy); - m[2][1] = 2 * (qyz - qwx); - m[2][2] = 1 - 2 * (qxx + qyy); + m[2][0] = 2 * (qxz + qwy) + m[2][1] = 2 * (qyz - qwx) + m[2][2] = 1 - 2 * (qxx + qyy) - m[3][3] = 1; + m[3][3] = 1 - return m; + return m } matrix4_from_quaternion_f64 :: proc(q: Quaternionf64) -> (m: Matrix4f64) { - qxx := q.x * q.x; - qyy := q.y * q.y; - qzz := q.z * q.z; - qxz := q.x * q.z; - qxy := q.x * q.y; - qyz := q.y * q.z; - qwx := q.w * q.x; - qwy := q.w * q.y; - qwz := q.w * q.z; + qxx := q.x * q.x + qyy := q.y * q.y + qzz := q.z * q.z + qxz := q.x * q.z + qxy := q.x * q.y + qyz := q.y * q.z + qwx := q.w * q.x + qwy := q.w * q.y + qwz := q.w * q.z - m[0][0] = 1 - 2 * (qyy + qzz); - m[0][1] = 2 * (qxy + qwz); - m[0][2] = 2 * (qxz - qwy); + m[0][0] = 1 - 2 * (qyy + qzz) + m[0][1] = 2 * (qxy + qwz) + m[0][2] = 2 * (qxz - qwy) - m[1][0] = 2 * (qxy - qwz); - m[1][1] = 1 - 2 * (qxx + qzz); - m[1][2] = 2 * (qyz + qwx); + m[1][0] = 2 * (qxy - qwz) + m[1][1] = 1 - 2 * (qxx + qzz) + m[1][2] = 2 * (qyz + qwx) - m[2][0] = 2 * (qxz + qwy); - m[2][1] = 2 * (qyz - qwx); - m[2][2] = 1 - 2 * (qxx + qyy); + m[2][0] = 2 * (qxz + qwy) + m[2][1] = 2 * (qyz - qwx) + m[2][2] = 1 - 2 * (qxx + qyy) - m[3][3] = 1; + m[3][3] = 1 - return m; + return m } matrix4_from_quaternion :: proc{ matrix4_from_quaternion_f16, matrix4_from_quaternion_f32, matrix4_from_quaternion_f64, -}; +} matrix4_from_trs_f16 :: proc(t: Vector3f16, r: Quaternionf16, s: Vector3f16) -> Matrix4f16 { - translation := matrix4_translate(t); - rotation := matrix4_from_quaternion(r); - scale := matrix4_scale(s); - return mul(translation, mul(rotation, scale)); + translation := matrix4_translate(t) + rotation := matrix4_from_quaternion(r) + scale := matrix4_scale(s) + return mul(translation, mul(rotation, scale)) } matrix4_from_trs_f32 :: proc(t: Vector3f32, r: Quaternionf32, s: Vector3f32) -> Matrix4f32 { - translation := matrix4_translate(t); - rotation := matrix4_from_quaternion(r); - scale := matrix4_scale(s); - return mul(translation, mul(rotation, scale)); + translation := matrix4_translate(t) + rotation := matrix4_from_quaternion(r) + scale := matrix4_scale(s) + return mul(translation, mul(rotation, scale)) } matrix4_from_trs_f64 :: proc(t: Vector3f64, r: Quaternionf64, s: Vector3f64) -> Matrix4f64 { - translation := matrix4_translate(t); - rotation := matrix4_from_quaternion(r); - scale := matrix4_scale(s); - return mul(translation, mul(rotation, scale)); + translation := matrix4_translate(t) + rotation := matrix4_from_quaternion(r) + scale := matrix4_scale(s) + return mul(translation, mul(rotation, scale)) } matrix4_from_trs :: proc{ matrix4_from_trs_f16, matrix4_from_trs_f32, matrix4_from_trs_f64, -}; +} matrix4_inverse_f16 :: proc(m: Matrix4f16) -> Matrix4f16 { - return auto_cast transpose(matrix4_inverse_transpose(m)); + return auto_cast transpose(matrix4_inverse_transpose(m)) } matrix4_inverse_f32 :: proc(m: Matrix4f32) -> Matrix4f32 { - return auto_cast transpose(matrix4_inverse_transpose(m)); + return auto_cast transpose(matrix4_inverse_transpose(m)) } matrix4_inverse_f64 :: proc(m: Matrix4f64) -> Matrix4f64 { - return auto_cast transpose(matrix4_inverse_transpose(m)); + return auto_cast transpose(matrix4_inverse_transpose(m)) } matrix4_inverse :: proc{ matrix4_inverse_f16, matrix4_inverse_f32, matrix4_inverse_f64, -}; +} matrix4_minor_f16 :: proc(m: Matrix4f16, c, r: int) -> f16 { - cut_down: Matrix3f16; + cut_down: Matrix3f16 for i in 0..<3 { - col := i if i < c else i+1; + col := i if i < c else i+1 for j in 0..<3 { - row := j if j < r else j+1; - cut_down[i][j] = m[col][row]; + row := j if j < r else j+1 + cut_down[i][j] = m[col][row] } } - return matrix3_determinant(cut_down); + return matrix3_determinant(cut_down) } matrix4_minor_f32 :: proc(m: Matrix4f32, c, r: int) -> f32 { - cut_down: Matrix3f32; + cut_down: Matrix3f32 for i in 0..<3 { - col := i if i < c else i+1; + col := i if i < c else i+1 for j in 0..<3 { - row := j if j < r else j+1; - cut_down[i][j] = m[col][row]; + row := j if j < r else j+1 + cut_down[i][j] = m[col][row] } } - return matrix3_determinant(cut_down); + return matrix3_determinant(cut_down) } matrix4_minor_f64 :: proc(m: Matrix4f64, c, r: int) -> f64 { - cut_down: Matrix3f64; + cut_down: Matrix3f64 for i in 0..<3 { - col := i if i < c else i+1; + col := i if i < c else i+1 for j in 0..<3 { - row := j if j < r else j+1; - cut_down[i][j] = m[col][row]; + row := j if j < r else j+1 + cut_down[i][j] = m[col][row] } } - return matrix3_determinant(cut_down); + return matrix3_determinant(cut_down) } matrix4_minor :: proc{ matrix4_minor_f16, matrix4_minor_f32, matrix4_minor_f64, -}; +} matrix4_cofactor_f16 :: proc(m: Matrix4f16, c, r: int) -> f16 { - sign, minor: f16; - sign = 1 if (c + r) % 2 == 0 else -1; - minor = matrix4_minor(m, c, r); - return sign * minor; + sign, minor: f16 + sign = 1 if (c + r) % 2 == 0 else -1 + minor = matrix4_minor(m, c, r) + return sign * minor } matrix4_cofactor_f32 :: proc(m: Matrix4f32, c, r: int) -> f32 { - sign, minor: f32; - sign = 1 if (c + r) % 2 == 0 else -1; - minor = matrix4_minor(m, c, r); - return sign * minor; + sign, minor: f32 + sign = 1 if (c + r) % 2 == 0 else -1 + minor = matrix4_minor(m, c, r) + return sign * minor } matrix4_cofactor_f64 :: proc(m: Matrix4f64, c, r: int) -> f64 { - sign, minor: f64; - sign = 1 if (c + r) % 2 == 0 else -1; - minor = matrix4_minor(m, c, r); - return sign * minor; + sign, minor: f64 + sign = 1 if (c + r) % 2 == 0 else -1 + minor = matrix4_minor(m, c, r) + return sign * minor } matrix4_cofactor :: proc{ matrix4_cofactor_f16, matrix4_cofactor_f32, matrix4_cofactor_f64, -}; +} matrix4_adjoint_f16 :: proc(m: Matrix4f16) -> (adjoint: Matrix4f16) { for i in 0..<4 { for j in 0..<4 { - adjoint[i][j] = matrix4_cofactor(m, i, j); + adjoint[i][j] = matrix4_cofactor(m, i, j) } } - return; + return } matrix4_adjoint_f32 :: proc(m: Matrix4f32) -> (adjoint: Matrix4f32) { for i in 0..<4 { for j in 0..<4 { - adjoint[i][j] = matrix4_cofactor(m, i, j); + adjoint[i][j] = matrix4_cofactor(m, i, j) } } - return; + return } matrix4_adjoint_f64 :: proc(m: Matrix4f64) -> (adjoint: Matrix4f64) { for i in 0..<4 { for j in 0..<4 { - adjoint[i][j] = matrix4_cofactor(m, i, j); + adjoint[i][j] = matrix4_cofactor(m, i, j) } } - return; + return } matrix4_adjoint :: proc{ matrix4_adjoint_f16, matrix4_adjoint_f32, matrix4_adjoint_f64, -}; +} matrix4_determinant_f16 :: proc(m: Matrix4f16) -> (determinant: f16) { - adjoint := matrix4_adjoint(m); + adjoint := matrix4_adjoint(m) for i in 0..<4 { - determinant += m[i][0] * adjoint[i][0]; + determinant += m[i][0] * adjoint[i][0] } - return; + return } matrix4_determinant_f32 :: proc(m: Matrix4f32) -> (determinant: f32) { - adjoint := matrix4_adjoint(m); + adjoint := matrix4_adjoint(m) for i in 0..<4 { - determinant += m[i][0] * adjoint[i][0]; + determinant += m[i][0] * adjoint[i][0] } - return; + return } matrix4_determinant_f64 :: proc(m: Matrix4f64) -> (determinant: f64) { - adjoint := matrix4_adjoint(m); + adjoint := matrix4_adjoint(m) for i in 0..<4 { - determinant += m[i][0] * adjoint[i][0]; + determinant += m[i][0] * adjoint[i][0] } - return; + return } matrix4_determinant :: proc{ matrix4_determinant_f16, matrix4_determinant_f32, matrix4_determinant_f64, -}; +} matrix4_inverse_transpose_f16 :: proc(m: Matrix4f16) -> (inverse_transpose: Matrix4f16) { - adjoint := matrix4_adjoint(m); - determinant: f16 = 0; + adjoint := matrix4_adjoint(m) + determinant: f16 = 0 for i in 0..<4 { - determinant += m[i][0] * adjoint[i][0]; + determinant += m[i][0] * adjoint[i][0] } - inv_determinant := 1.0 / determinant; + inv_determinant := 1.0 / determinant for i in 0..<4 { for j in 0..<4 { - inverse_transpose[i][j] = adjoint[i][j] * inv_determinant; + inverse_transpose[i][j] = adjoint[i][j] * inv_determinant } } - return; + return } matrix4_inverse_transpose_f32 :: proc(m: Matrix4f32) -> (inverse_transpose: Matrix4f32) { - adjoint := matrix4_adjoint(m); - determinant: f32 = 0; + adjoint := matrix4_adjoint(m) + determinant: f32 = 0 for i in 0..<4 { - determinant += m[i][0] * adjoint[i][0]; + determinant += m[i][0] * adjoint[i][0] } - inv_determinant := 1.0 / determinant; + inv_determinant := 1.0 / determinant for i in 0..<4 { for j in 0..<4 { - inverse_transpose[i][j] = adjoint[i][j] * inv_determinant; + inverse_transpose[i][j] = adjoint[i][j] * inv_determinant } } - return; + return } matrix4_inverse_transpose_f64 :: proc(m: Matrix4f64) -> (inverse_transpose: Matrix4f64) { - adjoint := matrix4_adjoint(m); - determinant: f64 = 0; + adjoint := matrix4_adjoint(m) + determinant: f64 = 0 for i in 0..<4 { - determinant += m[i][0] * adjoint[i][0]; + determinant += m[i][0] * adjoint[i][0] } - inv_determinant := 1.0 / determinant; + inv_determinant := 1.0 / determinant for i in 0..<4 { for j in 0..<4 { - inverse_transpose[i][j] = adjoint[i][j] * inv_determinant; + inverse_transpose[i][j] = adjoint[i][j] * inv_determinant } } - return; + return } matrix4_inverse_transpose :: proc{ matrix4_inverse_transpose_f16, matrix4_inverse_transpose_f32, matrix4_inverse_transpose_f64, -}; +} matrix4_translate_f16 :: proc(v: Vector3f16) -> Matrix4f16 { - m := MATRIX4F16_IDENTITY; - m[3][0] = v[0]; - m[3][1] = v[1]; - m[3][2] = v[2]; - return m; + m := MATRIX4F16_IDENTITY + m[3][0] = v[0] + m[3][1] = v[1] + m[3][2] = v[2] + return m } matrix4_translate_f32 :: proc(v: Vector3f32) -> Matrix4f32 { - m := MATRIX4F32_IDENTITY; - m[3][0] = v[0]; - m[3][1] = v[1]; - m[3][2] = v[2]; - return m; + m := MATRIX4F32_IDENTITY + m[3][0] = v[0] + m[3][1] = v[1] + m[3][2] = v[2] + return m } matrix4_translate_f64 :: proc(v: Vector3f64) -> Matrix4f64 { - m := MATRIX4F64_IDENTITY; - m[3][0] = v[0]; - m[3][1] = v[1]; - m[3][2] = v[2]; - return m; + m := MATRIX4F64_IDENTITY + m[3][0] = v[0] + m[3][1] = v[1] + m[3][2] = v[2] + return m } matrix4_translate :: proc{ matrix4_translate_f16, matrix4_translate_f32, matrix4_translate_f64, -}; +} matrix4_rotate_f16 :: proc(angle_radians: f16, v: Vector3f16) -> Matrix4f16 { - c := math.cos(angle_radians); - s := math.sin(angle_radians); + c := math.cos(angle_radians) + s := math.sin(angle_radians) - a := normalize(v); - t := a * (1-c); + a := normalize(v) + t := a * (1-c) - rot := MATRIX4F16_IDENTITY; + rot := MATRIX4F16_IDENTITY - rot[0][0] = c + t[0]*a[0]; - rot[0][1] = 0 + t[0]*a[1] + s*a[2]; - rot[0][2] = 0 + t[0]*a[2] - s*a[1]; - rot[0][3] = 0; + rot[0][0] = c + t[0]*a[0] + rot[0][1] = 0 + t[0]*a[1] + s*a[2] + rot[0][2] = 0 + t[0]*a[2] - s*a[1] + rot[0][3] = 0 - rot[1][0] = 0 + t[1]*a[0] - s*a[2]; - rot[1][1] = c + t[1]*a[1]; - rot[1][2] = 0 + t[1]*a[2] + s*a[0]; - rot[1][3] = 0; + rot[1][0] = 0 + t[1]*a[0] - s*a[2] + rot[1][1] = c + t[1]*a[1] + rot[1][2] = 0 + t[1]*a[2] + s*a[0] + rot[1][3] = 0 - rot[2][0] = 0 + t[2]*a[0] + s*a[1]; - rot[2][1] = 0 + t[2]*a[1] - s*a[0]; - rot[2][2] = c + t[2]*a[2]; - rot[2][3] = 0; + rot[2][0] = 0 + t[2]*a[0] + s*a[1] + rot[2][1] = 0 + t[2]*a[1] - s*a[0] + rot[2][2] = c + t[2]*a[2] + rot[2][3] = 0 - return rot; + return rot } matrix4_rotate_f32 :: proc(angle_radians: f32, v: Vector3f32) -> Matrix4f32 { - c := math.cos(angle_radians); - s := math.sin(angle_radians); + c := math.cos(angle_radians) + s := math.sin(angle_radians) - a := normalize(v); - t := a * (1-c); + a := normalize(v) + t := a * (1-c) - rot := MATRIX4F32_IDENTITY; + rot := MATRIX4F32_IDENTITY - rot[0][0] = c + t[0]*a[0]; - rot[0][1] = 0 + t[0]*a[1] + s*a[2]; - rot[0][2] = 0 + t[0]*a[2] - s*a[1]; - rot[0][3] = 0; + rot[0][0] = c + t[0]*a[0] + rot[0][1] = 0 + t[0]*a[1] + s*a[2] + rot[0][2] = 0 + t[0]*a[2] - s*a[1] + rot[0][3] = 0 - rot[1][0] = 0 + t[1]*a[0] - s*a[2]; - rot[1][1] = c + t[1]*a[1]; - rot[1][2] = 0 + t[1]*a[2] + s*a[0]; - rot[1][3] = 0; + rot[1][0] = 0 + t[1]*a[0] - s*a[2] + rot[1][1] = c + t[1]*a[1] + rot[1][2] = 0 + t[1]*a[2] + s*a[0] + rot[1][3] = 0 - rot[2][0] = 0 + t[2]*a[0] + s*a[1]; - rot[2][1] = 0 + t[2]*a[1] - s*a[0]; - rot[2][2] = c + t[2]*a[2]; - rot[2][3] = 0; + rot[2][0] = 0 + t[2]*a[0] + s*a[1] + rot[2][1] = 0 + t[2]*a[1] - s*a[0] + rot[2][2] = c + t[2]*a[2] + rot[2][3] = 0 - return rot; + return rot } matrix4_rotate_f64 :: proc(angle_radians: f64, v: Vector3f64) -> Matrix4f64 { - c := math.cos(angle_radians); - s := math.sin(angle_radians); + c := math.cos(angle_radians) + s := math.sin(angle_radians) - a := normalize(v); - t := a * (1-c); + a := normalize(v) + t := a * (1-c) - rot := MATRIX4F64_IDENTITY; + rot := MATRIX4F64_IDENTITY - rot[0][0] = c + t[0]*a[0]; - rot[0][1] = 0 + t[0]*a[1] + s*a[2]; - rot[0][2] = 0 + t[0]*a[2] - s*a[1]; - rot[0][3] = 0; + rot[0][0] = c + t[0]*a[0] + rot[0][1] = 0 + t[0]*a[1] + s*a[2] + rot[0][2] = 0 + t[0]*a[2] - s*a[1] + rot[0][3] = 0 - rot[1][0] = 0 + t[1]*a[0] - s*a[2]; - rot[1][1] = c + t[1]*a[1]; - rot[1][2] = 0 + t[1]*a[2] + s*a[0]; - rot[1][3] = 0; + rot[1][0] = 0 + t[1]*a[0] - s*a[2] + rot[1][1] = c + t[1]*a[1] + rot[1][2] = 0 + t[1]*a[2] + s*a[0] + rot[1][3] = 0 - rot[2][0] = 0 + t[2]*a[0] + s*a[1]; - rot[2][1] = 0 + t[2]*a[1] - s*a[0]; - rot[2][2] = c + t[2]*a[2]; - rot[2][3] = 0; + rot[2][0] = 0 + t[2]*a[0] + s*a[1] + rot[2][1] = 0 + t[2]*a[1] - s*a[0] + rot[2][2] = c + t[2]*a[2] + rot[2][3] = 0 - return rot; + return rot } matrix4_rotate :: proc{ matrix4_rotate_f16, matrix4_rotate_f32, matrix4_rotate_f64, -}; +} matrix4_scale_f16 :: proc(v: Vector3f16) -> (m: Matrix4f16) { - m[0][0] = v[0]; - m[1][1] = v[1]; - m[2][2] = v[2]; - m[3][3] = 1; - return; + m[0][0] = v[0] + m[1][1] = v[1] + m[2][2] = v[2] + m[3][3] = 1 + return } matrix4_scale_f32 :: proc(v: Vector3f32) -> (m: Matrix4f32) { - m[0][0] = v[0]; - m[1][1] = v[1]; - m[2][2] = v[2]; - m[3][3] = 1; - return; + m[0][0] = v[0] + m[1][1] = v[1] + m[2][2] = v[2] + m[3][3] = 1 + return } matrix4_scale_f64 :: proc(v: Vector3f64) -> (m: Matrix4f64) { - m[0][0] = v[0]; - m[1][1] = v[1]; - m[2][2] = v[2]; - m[3][3] = 1; - return; + m[0][0] = v[0] + m[1][1] = v[1] + m[2][2] = v[2] + m[3][3] = 1 + return } matrix4_scale :: proc{ matrix4_scale_f16, matrix4_scale_f32, matrix4_scale_f64, -}; +} matrix4_look_at_f16 :: proc(eye, centre, up: Vector3f16, flip_z_axis := true) -> (m: Matrix4f16) { - f := normalize(centre - eye); - s := normalize(cross(f, up)); - u := cross(s, f); + f := normalize(centre - eye) + s := normalize(cross(f, up)) + u := cross(s, f) - fe := dot(f, eye); + fe := dot(f, eye) return { {+s.x, +u.x, -f.x, 0}, {+s.y, +u.y, -f.y, 0}, {+s.z, +u.z, -f.z, 0}, {-dot(s, eye), -dot(u, eye), +fe if flip_z_axis else -fe, 1}, - }; + } } matrix4_look_at_f32 :: proc(eye, centre, up: Vector3f32, flip_z_axis := true) -> (m: Matrix4f32) { - f := normalize(centre - eye); - s := normalize(cross(f, up)); - u := cross(s, f); + f := normalize(centre - eye) + s := normalize(cross(f, up)) + u := cross(s, f) - fe := dot(f, eye); + fe := dot(f, eye) return { {+s.x, +u.x, -f.x, 0}, {+s.y, +u.y, -f.y, 0}, {+s.z, +u.z, -f.z, 0}, {-dot(s, eye), -dot(u, eye), +fe if flip_z_axis else -fe, 1}, - }; + } } matrix4_look_at_f64 :: proc(eye, centre, up: Vector3f64, flip_z_axis := true) -> (m: Matrix4f64) { - f := normalize(centre - eye); - s := normalize(cross(f, up)); - u := cross(s, f); + f := normalize(centre - eye) + s := normalize(cross(f, up)) + u := cross(s, f) - fe := dot(f, eye); + fe := dot(f, eye) return { {+s.x, +u.x, -f.x, 0}, {+s.y, +u.y, -f.y, 0}, {+s.z, +u.z, -f.z, 0}, {-dot(s, eye), -dot(u, eye), +fe if flip_z_axis else -fe, 1}, - }; + } } matrix4_look_at :: proc{ matrix4_look_at_f16, matrix4_look_at_f32, matrix4_look_at_f64, -}; +} matrix4_perspective_f16 :: proc(fovy, aspect, near, far: f16, flip_z_axis := true) -> (m: Matrix4f16) { - tan_half_fovy := math.tan(0.5 * fovy); - m[0][0] = 1 / (aspect*tan_half_fovy); - m[1][1] = 1 / (tan_half_fovy); - m[2][2] = +(far + near) / (far - near); - m[2][3] = +1; - m[3][2] = -2*far*near / (far - near); + tan_half_fovy := math.tan(0.5 * fovy) + m[0][0] = 1 / (aspect*tan_half_fovy) + m[1][1] = 1 / (tan_half_fovy) + m[2][2] = +(far + near) / (far - near) + m[2][3] = +1 + m[3][2] = -2*far*near / (far - near) if flip_z_axis { - m[2] = -m[2]; + m[2] = -m[2] } - return; + return } matrix4_perspective_f32 :: proc(fovy, aspect, near, far: f32, flip_z_axis := true) -> (m: Matrix4f32) { - tan_half_fovy := math.tan(0.5 * fovy); - m[0][0] = 1 / (aspect*tan_half_fovy); - m[1][1] = 1 / (tan_half_fovy); - m[2][2] = +(far + near) / (far - near); - m[2][3] = +1; - m[3][2] = -2*far*near / (far - near); + tan_half_fovy := math.tan(0.5 * fovy) + m[0][0] = 1 / (aspect*tan_half_fovy) + m[1][1] = 1 / (tan_half_fovy) + m[2][2] = +(far + near) / (far - near) + m[2][3] = +1 + m[3][2] = -2*far*near / (far - near) if flip_z_axis { - m[2] = -m[2]; + m[2] = -m[2] } - return; + return } matrix4_perspective_f64 :: proc(fovy, aspect, near, far: f64, flip_z_axis := true) -> (m: Matrix4f64) { - tan_half_fovy := math.tan(0.5 * fovy); - m[0][0] = 1 / (aspect*tan_half_fovy); - m[1][1] = 1 / (tan_half_fovy); - m[2][2] = +(far + near) / (far - near); - m[2][3] = +1; - m[3][2] = -2*far*near / (far - near); + tan_half_fovy := math.tan(0.5 * fovy) + m[0][0] = 1 / (aspect*tan_half_fovy) + m[1][1] = 1 / (tan_half_fovy) + m[2][2] = +(far + near) / (far - near) + m[2][3] = +1 + m[3][2] = -2*far*near / (far - near) if flip_z_axis { - m[2] = -m[2]; + m[2] = -m[2] } - return; + return } matrix4_perspective :: proc{ matrix4_perspective_f16, matrix4_perspective_f32, matrix4_perspective_f64, -}; +} matrix_ortho3d_f16 :: proc(left, right, bottom, top, near, far: f16, flip_z_axis := true) -> (m: Matrix4f16) { - m[0][0] = +2 / (right - left); - m[1][1] = +2 / (top - bottom); - m[2][2] = +2 / (far - near); - m[3][0] = -(right + left) / (right - left); - m[3][1] = -(top + bottom) / (top - bottom); - m[3][2] = -(far + near) / (far- near); - m[3][3] = 1; + m[0][0] = +2 / (right - left) + m[1][1] = +2 / (top - bottom) + m[2][2] = +2 / (far - near) + m[3][0] = -(right + left) / (right - left) + m[3][1] = -(top + bottom) / (top - bottom) + m[3][2] = -(far + near) / (far- near) + m[3][3] = 1 if flip_z_axis { - m[2] = -m[2]; + m[2] = -m[2] } - return; + return } matrix_ortho3d_f32 :: proc(left, right, bottom, top, near, far: f32, flip_z_axis := true) -> (m: Matrix4f32) { - m[0][0] = +2 / (right - left); - m[1][1] = +2 / (top - bottom); - m[2][2] = +2 / (far - near); - m[3][0] = -(right + left) / (right - left); - m[3][1] = -(top + bottom) / (top - bottom); - m[3][2] = -(far + near) / (far- near); - m[3][3] = 1; + m[0][0] = +2 / (right - left) + m[1][1] = +2 / (top - bottom) + m[2][2] = +2 / (far - near) + m[3][0] = -(right + left) / (right - left) + m[3][1] = -(top + bottom) / (top - bottom) + m[3][2] = -(far + near) / (far- near) + m[3][3] = 1 if flip_z_axis { - m[2] = -m[2]; + m[2] = -m[2] } - return; + return } matrix_ortho3d_f64 :: proc(left, right, bottom, top, near, far: f64, flip_z_axis := true) -> (m: Matrix4f64) { - m[0][0] = +2 / (right - left); - m[1][1] = +2 / (top - bottom); - m[2][2] = +2 / (far - near); - m[3][0] = -(right + left) / (right - left); - m[3][1] = -(top + bottom) / (top - bottom); - m[3][2] = -(far + near) / (far- near); - m[3][3] = 1; + m[0][0] = +2 / (right - left) + m[1][1] = +2 / (top - bottom) + m[2][2] = +2 / (far - near) + m[3][0] = -(right + left) / (right - left) + m[3][1] = -(top + bottom) / (top - bottom) + m[3][2] = -(far + near) / (far- near) + m[3][3] = 1 if flip_z_axis { - m[2] = -m[2]; + m[2] = -m[2] } - return; + return } matrix_ortho3d :: proc{ matrix_ortho3d_f16, matrix_ortho3d_f32, matrix_ortho3d_f64, -}; +} matrix4_infinite_perspective_f16 :: proc(fovy, aspect, near: f16, flip_z_axis := true) -> (m: Matrix4f16) { - tan_half_fovy := math.tan(0.5 * fovy); - m[0][0] = 1 / (aspect*tan_half_fovy); - m[1][1] = 1 / (tan_half_fovy); - m[2][2] = +1; - m[2][3] = +1; - m[3][2] = -2*near; + tan_half_fovy := math.tan(0.5 * fovy) + m[0][0] = 1 / (aspect*tan_half_fovy) + m[1][1] = 1 / (tan_half_fovy) + m[2][2] = +1 + m[2][3] = +1 + m[3][2] = -2*near if flip_z_axis { - m[2] = -m[2]; + m[2] = -m[2] } - return; + return } matrix4_infinite_perspective_f32 :: proc(fovy, aspect, near: f32, flip_z_axis := true) -> (m: Matrix4f32) { - tan_half_fovy := math.tan(0.5 * fovy); - m[0][0] = 1 / (aspect*tan_half_fovy); - m[1][1] = 1 / (tan_half_fovy); - m[2][2] = +1; - m[2][3] = +1; - m[3][2] = -2*near; + tan_half_fovy := math.tan(0.5 * fovy) + m[0][0] = 1 / (aspect*tan_half_fovy) + m[1][1] = 1 / (tan_half_fovy) + m[2][2] = +1 + m[2][3] = +1 + m[3][2] = -2*near if flip_z_axis { - m[2] = -m[2]; + m[2] = -m[2] } - return; + return } matrix4_infinite_perspective_f64 :: proc(fovy, aspect, near: f64, flip_z_axis := true) -> (m: Matrix4f64) { - tan_half_fovy := math.tan(0.5 * fovy); - m[0][0] = 1 / (aspect*tan_half_fovy); - m[1][1] = 1 / (tan_half_fovy); - m[2][2] = +1; - m[2][3] = +1; - m[3][2] = -2*near; + tan_half_fovy := math.tan(0.5 * fovy) + m[0][0] = 1 / (aspect*tan_half_fovy) + m[1][1] = 1 / (tan_half_fovy) + m[2][2] = +1 + m[2][3] = +1 + m[3][2] = -2*near if flip_z_axis { - m[2] = -m[2]; + m[2] = -m[2] } - return; + return } matrix4_infinite_perspective :: proc{ matrix4_infinite_perspective_f16, matrix4_infinite_perspective_f32, matrix4_infinite_perspective_f64, -}; +} matrix2_from_scalar_f16 :: proc(f: f16) -> (m: Matrix2f16) { - m[0][0], m[0][1] = f, 0; - m[1][0], m[1][1] = 0, f; - return; + m[0][0], m[0][1] = f, 0 + m[1][0], m[1][1] = 0, f + return } matrix2_from_scalar_f32 :: proc(f: f32) -> (m: Matrix2f32) { - m[0][0], m[0][1] = f, 0; - m[1][0], m[1][1] = 0, f; - return; + m[0][0], m[0][1] = f, 0 + m[1][0], m[1][1] = 0, f + return } matrix2_from_scalar_f64 :: proc(f: f64) -> (m: Matrix2f64) { - m[0][0], m[0][1] = f, 0; - m[1][0], m[1][1] = 0, f; - return; + m[0][0], m[0][1] = f, 0 + m[1][0], m[1][1] = 0, f + return } matrix2_from_scalar :: proc{ matrix2_from_scalar_f16, matrix2_from_scalar_f32, matrix2_from_scalar_f64, -}; +} matrix3_from_scalar_f16 :: proc(f: f16) -> (m: Matrix3f16) { - m[0][0], m[0][1], m[0][2] = f, 0, 0; - m[1][0], m[1][1], m[1][2] = 0, f, 0; - m[2][0], m[2][1], m[2][2] = 0, 0, f; - return; + m[0][0], m[0][1], m[0][2] = f, 0, 0 + m[1][0], m[1][1], m[1][2] = 0, f, 0 + m[2][0], m[2][1], m[2][2] = 0, 0, f + return } matrix3_from_scalar_f32 :: proc(f: f32) -> (m: Matrix3f32) { - m[0][0], m[0][1], m[0][2] = f, 0, 0; - m[1][0], m[1][1], m[1][2] = 0, f, 0; - m[2][0], m[2][1], m[2][2] = 0, 0, f; - return; + m[0][0], m[0][1], m[0][2] = f, 0, 0 + m[1][0], m[1][1], m[1][2] = 0, f, 0 + m[2][0], m[2][1], m[2][2] = 0, 0, f + return } matrix3_from_scalar_f64 :: proc(f: f64) -> (m: Matrix3f64) { - m[0][0], m[0][1], m[0][2] = f, 0, 0; - m[1][0], m[1][1], m[1][2] = 0, f, 0; - m[2][0], m[2][1], m[2][2] = 0, 0, f; - return; + m[0][0], m[0][1], m[0][2] = f, 0, 0 + m[1][0], m[1][1], m[1][2] = 0, f, 0 + m[2][0], m[2][1], m[2][2] = 0, 0, f + return } matrix3_from_scalar :: proc{ matrix3_from_scalar_f16, matrix3_from_scalar_f32, matrix3_from_scalar_f64, -}; +} matrix4_from_scalar_f16 :: proc(f: f16) -> (m: Matrix4f16) { - m[0][0], m[0][1], m[0][2], m[0][3] = f, 0, 0, 0; - m[1][0], m[1][1], m[1][2], m[1][3] = 0, f, 0, 0; - m[2][0], m[2][1], m[2][2], m[2][3] = 0, 0, f, 0; - m[3][0], m[3][1], m[3][2], m[3][3] = 0, 0, 0, f; - return; + m[0][0], m[0][1], m[0][2], m[0][3] = f, 0, 0, 0 + m[1][0], m[1][1], m[1][2], m[1][3] = 0, f, 0, 0 + m[2][0], m[2][1], m[2][2], m[2][3] = 0, 0, f, 0 + m[3][0], m[3][1], m[3][2], m[3][3] = 0, 0, 0, f + return } matrix4_from_scalar_f32 :: proc(f: f32) -> (m: Matrix4f32) { - m[0][0], m[0][1], m[0][2], m[0][3] = f, 0, 0, 0; - m[1][0], m[1][1], m[1][2], m[1][3] = 0, f, 0, 0; - m[2][0], m[2][1], m[2][2], m[2][3] = 0, 0, f, 0; - m[3][0], m[3][1], m[3][2], m[3][3] = 0, 0, 0, f; - return; + m[0][0], m[0][1], m[0][2], m[0][3] = f, 0, 0, 0 + m[1][0], m[1][1], m[1][2], m[1][3] = 0, f, 0, 0 + m[2][0], m[2][1], m[2][2], m[2][3] = 0, 0, f, 0 + m[3][0], m[3][1], m[3][2], m[3][3] = 0, 0, 0, f + return } matrix4_from_scalar_f64 :: proc(f: f64) -> (m: Matrix4f64) { - m[0][0], m[0][1], m[0][2], m[0][3] = f, 0, 0, 0; - m[1][0], m[1][1], m[1][2], m[1][3] = 0, f, 0, 0; - m[2][0], m[2][1], m[2][2], m[2][3] = 0, 0, f, 0; - m[3][0], m[3][1], m[3][2], m[3][3] = 0, 0, 0, f; - return; + m[0][0], m[0][1], m[0][2], m[0][3] = f, 0, 0, 0 + m[1][0], m[1][1], m[1][2], m[1][3] = 0, f, 0, 0 + m[2][0], m[2][1], m[2][2], m[2][3] = 0, 0, f, 0 + m[3][0], m[3][1], m[3][2], m[3][3] = 0, 0, 0, f + return } matrix4_from_scalar :: proc{ matrix4_from_scalar_f16, matrix4_from_scalar_f32, matrix4_from_scalar_f64, -}; +} matrix2_from_matrix3_f16 :: proc(m: Matrix3f16) -> (r: Matrix2f16) { - r[0][0], r[0][1] = m[0][0], m[0][1]; - r[1][0], r[1][1] = m[1][0], m[1][1]; - return; + r[0][0], r[0][1] = m[0][0], m[0][1] + r[1][0], r[1][1] = m[1][0], m[1][1] + return } matrix2_from_matrix3_f32 :: proc(m: Matrix3f32) -> (r: Matrix2f32) { - r[0][0], r[0][1] = m[0][0], m[0][1]; - r[1][0], r[1][1] = m[1][0], m[1][1]; - return; + r[0][0], r[0][1] = m[0][0], m[0][1] + r[1][0], r[1][1] = m[1][0], m[1][1] + return } matrix2_from_matrix3_f64 :: proc(m: Matrix3f64) -> (r: Matrix2f64) { - r[0][0], r[0][1] = m[0][0], m[0][1]; - r[1][0], r[1][1] = m[1][0], m[1][1]; - return; + r[0][0], r[0][1] = m[0][0], m[0][1] + r[1][0], r[1][1] = m[1][0], m[1][1] + return } matrix2_from_matrix3 :: proc{ matrix2_from_matrix3_f16, matrix2_from_matrix3_f32, matrix2_from_matrix3_f64, -}; +} matrix2_from_matrix4_f16 :: proc(m: Matrix4f16) -> (r: Matrix2f16) { - r[0][0], r[0][1] = m[0][0], m[0][1]; - r[1][0], r[1][1] = m[1][0], m[1][1]; - return; + r[0][0], r[0][1] = m[0][0], m[0][1] + r[1][0], r[1][1] = m[1][0], m[1][1] + return } matrix2_from_matrix4_f32 :: proc(m: Matrix4f32) -> (r: Matrix2f32) { - r[0][0], r[0][1] = m[0][0], m[0][1]; - r[1][0], r[1][1] = m[1][0], m[1][1]; - return; + r[0][0], r[0][1] = m[0][0], m[0][1] + r[1][0], r[1][1] = m[1][0], m[1][1] + return } matrix2_from_matrix4_f64 :: proc(m: Matrix4f64) -> (r: Matrix2f64) { - r[0][0], r[0][1] = m[0][0], m[0][1]; - r[1][0], r[1][1] = m[1][0], m[1][1]; - return; + r[0][0], r[0][1] = m[0][0], m[0][1] + r[1][0], r[1][1] = m[1][0], m[1][1] + return } matrix2_from_matrix4 :: proc{ matrix2_from_matrix4_f16, matrix2_from_matrix4_f32, matrix2_from_matrix4_f64, -}; +} matrix3_from_matrix2_f16 :: proc(m: Matrix2f16) -> (r: Matrix3f16) { - r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], 0; - r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], 0; - r[2][0], r[2][1], r[2][2] = 0, 0, 1; - return; + r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], 0 + r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], 0 + r[2][0], r[2][1], r[2][2] = 0, 0, 1 + return } matrix3_from_matrix2_f32 :: proc(m: Matrix2f32) -> (r: Matrix3f32) { - r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], 0; - r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], 0; - r[2][0], r[2][1], r[2][2] = 0, 0, 1; - return; + r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], 0 + r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], 0 + r[2][0], r[2][1], r[2][2] = 0, 0, 1 + return } matrix3_from_matrix2_f64 :: proc(m: Matrix2f64) -> (r: Matrix3f64) { - r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], 0; - r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], 0; - r[2][0], r[2][1], r[2][2] = 0, 0, 1; - return; + r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], 0 + r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], 0 + r[2][0], r[2][1], r[2][2] = 0, 0, 1 + return } matrix3_from_matrix2 :: proc{ matrix3_from_matrix2_f16, matrix3_from_matrix2_f32, matrix3_from_matrix2_f64, -}; +} matrix3_from_matrix4_f16 :: proc(m: Matrix4f16) -> (r: Matrix3f16) { - r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], m[0][2]; - r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], m[1][2]; - r[2][0], r[2][1], r[2][2] = m[2][0], m[2][1], m[2][2]; - return; + r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], m[0][2] + r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], m[1][2] + r[2][0], r[2][1], r[2][2] = m[2][0], m[2][1], m[2][2] + return } matrix3_from_matrix4_f32 :: proc(m: Matrix4f32) -> (r: Matrix3f32) { - r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], m[0][2]; - r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], m[1][2]; - r[2][0], r[2][1], r[2][2] = m[2][0], m[2][1], m[2][2]; - return; + r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], m[0][2] + r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], m[1][2] + r[2][0], r[2][1], r[2][2] = m[2][0], m[2][1], m[2][2] + return } matrix3_from_matrix4_f64 :: proc(m: Matrix4f64) -> (r: Matrix3f64) { - r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], m[0][2]; - r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], m[1][2]; - r[2][0], r[2][1], r[2][2] = m[2][0], m[2][1], m[2][2]; - return; + r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], m[0][2] + r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], m[1][2] + r[2][0], r[2][1], r[2][2] = m[2][0], m[2][1], m[2][2] + return } matrix3_from_matrix4 :: proc{ matrix3_from_matrix4_f16, matrix3_from_matrix4_f32, matrix3_from_matrix4_f64, -}; +} matrix4_from_matrix2_f16 :: proc(m: Matrix2f16) -> (r: Matrix4f16) { - r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], 0, 0; - r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], 0, 0; - r[2][0], r[2][1], r[2][2], r[2][3] = 0, 0, 1, 0; - r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1; - return; + r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], 0, 0 + r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], 0, 0 + r[2][0], r[2][1], r[2][2], r[2][3] = 0, 0, 1, 0 + r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1 + return } matrix4_from_matrix2_f32 :: proc(m: Matrix2f32) -> (r: Matrix4f32) { - r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], 0, 0; - r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], 0, 0; - r[2][0], r[2][1], r[2][2], r[2][3] = 0, 0, 1, 0; - r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1; - return; + r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], 0, 0 + r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], 0, 0 + r[2][0], r[2][1], r[2][2], r[2][3] = 0, 0, 1, 0 + r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1 + return } matrix4_from_matrix2_f64 :: proc(m: Matrix2f64) -> (r: Matrix4f64) { - r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], 0, 0; - r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], 0, 0; - r[2][0], r[2][1], r[2][2], r[2][3] = 0, 0, 1, 0; - r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1; - return; + r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], 0, 0 + r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], 0, 0 + r[2][0], r[2][1], r[2][2], r[2][3] = 0, 0, 1, 0 + r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1 + return } matrix4_from_matrix2 :: proc{ matrix4_from_matrix2_f16, matrix4_from_matrix2_f32, matrix4_from_matrix2_f64, -}; +} matrix4_from_matrix3_f16 :: proc(m: Matrix3f16) -> (r: Matrix4f16) { - r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], m[0][2], 0; - r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], m[1][2], 0; - r[2][0], r[2][1], r[2][2], r[2][3] = m[2][0], m[2][1], m[2][2], 0; - r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1; - return; + r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], m[0][2], 0 + r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], m[1][2], 0 + r[2][0], r[2][1], r[2][2], r[2][3] = m[2][0], m[2][1], m[2][2], 0 + r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1 + return } matrix4_from_matrix3_f32 :: proc(m: Matrix3f32) -> (r: Matrix4f32) { - r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], m[0][2], 0; - r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], m[1][2], 0; - r[2][0], r[2][1], r[2][2], r[2][3] = m[2][0], m[2][1], m[2][2], 0; - r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1; - return; + r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], m[0][2], 0 + r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], m[1][2], 0 + r[2][0], r[2][1], r[2][2], r[2][3] = m[2][0], m[2][1], m[2][2], 0 + r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1 + return } matrix4_from_matrix3_f64 :: proc(m: Matrix3f64) -> (r: Matrix4f64) { - r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], m[0][2], 0; - r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], m[1][2], 0; - r[2][0], r[2][1], r[2][2], r[2][3] = m[2][0], m[2][1], m[2][2], 0; - r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1; - return; + r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], m[0][2], 0 + r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], m[1][2], 0 + r[2][0], r[2][1], r[2][2], r[2][3] = m[2][0], m[2][1], m[2][2], 0 + r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1 + return } matrix4_from_matrix3 :: proc{ matrix4_from_matrix3_f16, matrix4_from_matrix3_f32, matrix4_from_matrix3_f64, -}; +} quaternion_from_scalar_f16 :: proc(f: f16) -> (q: Quaternionf16) { - q.w = f; - return; + q.w = f + return } quaternion_from_scalar_f32 :: proc(f: f32) -> (q: Quaternionf32) { - q.w = f; - return; + q.w = f + return } quaternion_from_scalar_f64 :: proc(f: f64) -> (q: Quaternionf64) { - q.w = f; - return; + q.w = f + return } quaternion_from_scalar :: proc{ quaternion_from_scalar_f16, quaternion_from_scalar_f32, quaternion_from_scalar_f64, -}; +} -to_matrix2f16 :: proc{matrix2_from_scalar_f16, matrix2_from_matrix3_f16, matrix2_from_matrix4_f16}; -to_matrix3f16 :: proc{matrix3_from_scalar_f16, matrix3_from_matrix2_f16, matrix3_from_matrix4_f16, matrix3_from_quaternion_f16}; -to_matrix4f16 :: proc{matrix4_from_scalar_f16, matrix4_from_matrix2_f16, matrix4_from_matrix3_f16, matrix4_from_quaternion_f16}; -to_quaternionf16 :: proc{quaternion_from_scalar_f16, quaternion_from_matrix3_f16, quaternion_from_matrix4_f16}; +to_matrix2f16 :: proc{matrix2_from_scalar_f16, matrix2_from_matrix3_f16, matrix2_from_matrix4_f16} +to_matrix3f16 :: proc{matrix3_from_scalar_f16, matrix3_from_matrix2_f16, matrix3_from_matrix4_f16, matrix3_from_quaternion_f16} +to_matrix4f16 :: proc{matrix4_from_scalar_f16, matrix4_from_matrix2_f16, matrix4_from_matrix3_f16, matrix4_from_quaternion_f16} +to_quaternionf16 :: proc{quaternion_from_scalar_f16, quaternion_from_matrix3_f16, quaternion_from_matrix4_f16} -to_matrix2f32 :: proc{matrix2_from_scalar_f32, matrix2_from_matrix3_f32, matrix2_from_matrix4_f32}; -to_matrix3f32 :: proc{matrix3_from_scalar_f32, matrix3_from_matrix2_f32, matrix3_from_matrix4_f32, matrix3_from_quaternion_f32}; -to_matrix4f32 :: proc{matrix4_from_scalar_f32, matrix4_from_matrix2_f32, matrix4_from_matrix3_f32, matrix4_from_quaternion_f32}; -to_quaternionf32 :: proc{quaternion_from_scalar_f32, quaternion_from_matrix3_f32, quaternion_from_matrix4_f32}; +to_matrix2f32 :: proc{matrix2_from_scalar_f32, matrix2_from_matrix3_f32, matrix2_from_matrix4_f32} +to_matrix3f32 :: proc{matrix3_from_scalar_f32, matrix3_from_matrix2_f32, matrix3_from_matrix4_f32, matrix3_from_quaternion_f32} +to_matrix4f32 :: proc{matrix4_from_scalar_f32, matrix4_from_matrix2_f32, matrix4_from_matrix3_f32, matrix4_from_quaternion_f32} +to_quaternionf32 :: proc{quaternion_from_scalar_f32, quaternion_from_matrix3_f32, quaternion_from_matrix4_f32} -to_matrix2f64 :: proc{matrix2_from_scalar_f64, matrix2_from_matrix3_f64, matrix2_from_matrix4_f64}; -to_matrix3f64 :: proc{matrix3_from_scalar_f64, matrix3_from_matrix2_f64, matrix3_from_matrix4_f64, matrix3_from_quaternion_f64}; -to_matrix4f64 :: proc{matrix4_from_scalar_f64, matrix4_from_matrix2_f64, matrix4_from_matrix3_f64, matrix4_from_quaternion_f64}; -to_quaternionf64 :: proc{quaternion_from_scalar_f64, quaternion_from_matrix3_f64, quaternion_from_matrix4_f64}; +to_matrix2f64 :: proc{matrix2_from_scalar_f64, matrix2_from_matrix3_f64, matrix2_from_matrix4_f64} +to_matrix3f64 :: proc{matrix3_from_scalar_f64, matrix3_from_matrix2_f64, matrix3_from_matrix4_f64, matrix3_from_quaternion_f64} +to_matrix4f64 :: proc{matrix4_from_scalar_f64, matrix4_from_matrix2_f64, matrix4_from_matrix3_f64, matrix4_from_quaternion_f64} +to_quaternionf64 :: proc{quaternion_from_scalar_f64, quaternion_from_matrix3_f64, quaternion_from_matrix4_f64} @@ -2457,250 +2457,250 @@ to_matrix2f :: proc{ matrix2_from_scalar_f16, matrix2_from_matrix3_f16, matrix2_from_matrix4_f16, matrix2_from_scalar_f32, matrix2_from_matrix3_f32, matrix2_from_matrix4_f32, matrix2_from_scalar_f64, matrix2_from_matrix3_f64, matrix2_from_matrix4_f64, -}; +} to_matrix3 :: proc{ matrix3_from_scalar_f16, matrix3_from_matrix2_f16, matrix3_from_matrix4_f16, matrix3_from_quaternion_f16, matrix3_from_scalar_f32, matrix3_from_matrix2_f32, matrix3_from_matrix4_f32, matrix3_from_quaternion_f32, matrix3_from_scalar_f64, matrix3_from_matrix2_f64, matrix3_from_matrix4_f64, matrix3_from_quaternion_f64, -}; +} to_matrix4 :: proc{ matrix4_from_scalar_f16, matrix4_from_matrix2_f16, matrix4_from_matrix3_f16, matrix4_from_quaternion_f16, matrix4_from_scalar_f32, matrix4_from_matrix2_f32, matrix4_from_matrix3_f32, matrix4_from_quaternion_f32, matrix4_from_scalar_f64, matrix4_from_matrix2_f64, matrix4_from_matrix3_f64, matrix4_from_quaternion_f64, -}; +} to_quaternion :: proc{ quaternion_from_scalar_f16, quaternion_from_matrix3_f16, quaternion_from_matrix4_f16, quaternion_from_scalar_f32, quaternion_from_matrix3_f32, quaternion_from_matrix4_f32, quaternion_from_scalar_f64, quaternion_from_matrix3_f64, quaternion_from_matrix4_f64, -}; +} matrix2_orthonormalize_f16 :: proc(m: Matrix2f16) -> (r: Matrix2f16) { - r[0] = normalize(m[0]); + r[0] = normalize(m[0]) - d0 := dot(r[0], r[1]); - r[1] -= r[0] * d0; - r[1] = normalize(r[1]); + d0 := dot(r[0], r[1]) + r[1] -= r[0] * d0 + r[1] = normalize(r[1]) - return; + return } matrix2_orthonormalize_f32 :: proc(m: Matrix2f32) -> (r: Matrix2f32) { - r[0] = normalize(m[0]); + r[0] = normalize(m[0]) - d0 := dot(r[0], r[1]); - r[1] -= r[0] * d0; - r[1] = normalize(r[1]); + d0 := dot(r[0], r[1]) + r[1] -= r[0] * d0 + r[1] = normalize(r[1]) - return; + return } matrix2_orthonormalize_f64 :: proc(m: Matrix2f64) -> (r: Matrix2f64) { - r[0] = normalize(m[0]); + r[0] = normalize(m[0]) - d0 := dot(r[0], r[1]); - r[1] -= r[0] * d0; - r[1] = normalize(r[1]); + d0 := dot(r[0], r[1]) + r[1] -= r[0] * d0 + r[1] = normalize(r[1]) - return; + return } matrix2_orthonormalize :: proc{ matrix2_orthonormalize_f16, matrix2_orthonormalize_f32, matrix2_orthonormalize_f64, -}; +} matrix3_orthonormalize_f16 :: proc(m: Matrix3f16) -> (r: Matrix3f16) { - r[0] = normalize(m[0]); + r[0] = normalize(m[0]) - d0 := dot(r[0], r[1]); - r[1] -= r[0] * d0; - r[1] = normalize(r[1]); + d0 := dot(r[0], r[1]) + r[1] -= r[0] * d0 + r[1] = normalize(r[1]) - d1 := dot(r[1], r[2]); - d0 = dot(r[0], r[2]); - r[2] -= r[0]*d0 + r[1]*d1; - r[2] = normalize(r[2]); + d1 := dot(r[1], r[2]) + d0 = dot(r[0], r[2]) + r[2] -= r[0]*d0 + r[1]*d1 + r[2] = normalize(r[2]) - return; + return } matrix3_orthonormalize_f32 :: proc(m: Matrix3f32) -> (r: Matrix3f32) { - r[0] = normalize(m[0]); + r[0] = normalize(m[0]) - d0 := dot(r[0], r[1]); - r[1] -= r[0] * d0; - r[1] = normalize(r[1]); + d0 := dot(r[0], r[1]) + r[1] -= r[0] * d0 + r[1] = normalize(r[1]) - d1 := dot(r[1], r[2]); - d0 = dot(r[0], r[2]); - r[2] -= r[0]*d0 + r[1]*d1; - r[2] = normalize(r[2]); + d1 := dot(r[1], r[2]) + d0 = dot(r[0], r[2]) + r[2] -= r[0]*d0 + r[1]*d1 + r[2] = normalize(r[2]) - return; + return } matrix3_orthonormalize_f64 :: proc(m: Matrix3f64) -> (r: Matrix3f64) { - r[0] = normalize(m[0]); + r[0] = normalize(m[0]) - d0 := dot(r[0], r[1]); - r[1] -= r[0] * d0; - r[1] = normalize(r[1]); + d0 := dot(r[0], r[1]) + r[1] -= r[0] * d0 + r[1] = normalize(r[1]) - d1 := dot(r[1], r[2]); - d0 = dot(r[0], r[2]); - r[2] -= r[0]*d0 + r[1]*d1; - r[2] = normalize(r[2]); + d1 := dot(r[1], r[2]) + d0 = dot(r[0], r[2]) + r[2] -= r[0]*d0 + r[1]*d1 + r[2] = normalize(r[2]) - return; + return } matrix3_orthonormalize :: proc{ matrix3_orthonormalize_f16, matrix3_orthonormalize_f32, matrix3_orthonormalize_f64, -}; +} vector3_orthonormalize_f16 :: proc(x, y: Vector3f16) -> (z: Vector3f16) { - return normalize(x - y * dot(y, x)); + return normalize(x - y * dot(y, x)) } vector3_orthonormalize_f32 :: proc(x, y: Vector3f32) -> (z: Vector3f32) { - return normalize(x - y * dot(y, x)); + return normalize(x - y * dot(y, x)) } vector3_orthonormalize_f64 :: proc(x, y: Vector3f64) -> (z: Vector3f64) { - return normalize(x - y * dot(y, x)); + return normalize(x - y * dot(y, x)) } vector3_orthonormalize :: proc{ vector3_orthonormalize_f16, vector3_orthonormalize_f32, vector3_orthonormalize_f64, -}; +} orthonormalize :: proc{ matrix2_orthonormalize_f16, matrix3_orthonormalize_f16, vector3_orthonormalize_f16, matrix2_orthonormalize_f32, matrix3_orthonormalize_f32, vector3_orthonormalize_f32, matrix2_orthonormalize_f64, matrix3_orthonormalize_f64, vector3_orthonormalize_f64, -}; +} matrix4_orientation_f16 :: proc(normal, up: Vector3f16) -> Matrix4f16 { if all(equal(normal, up)) { - return MATRIX4F16_IDENTITY; + return MATRIX4F16_IDENTITY } - rotation_axis := cross(up, normal); - angle := math.acos(dot(normal, up)); + rotation_axis := cross(up, normal) + angle := math.acos(dot(normal, up)) - return matrix4_rotate(angle, rotation_axis); + return matrix4_rotate(angle, rotation_axis) } matrix4_orientation_f32 :: proc(normal, up: Vector3f32) -> Matrix4f32 { if all(equal(normal, up)) { - return MATRIX4F32_IDENTITY; + return MATRIX4F32_IDENTITY } - rotation_axis := cross(up, normal); - angle := math.acos(dot(normal, up)); + rotation_axis := cross(up, normal) + angle := math.acos(dot(normal, up)) - return matrix4_rotate(angle, rotation_axis); + return matrix4_rotate(angle, rotation_axis) } matrix4_orientation_f64 :: proc(normal, up: Vector3f64) -> Matrix4f64 { if all(equal(normal, up)) { - return MATRIX4F64_IDENTITY; + return MATRIX4F64_IDENTITY } - rotation_axis := cross(up, normal); - angle := math.acos(dot(normal, up)); + rotation_axis := cross(up, normal) + angle := math.acos(dot(normal, up)) - return matrix4_rotate(angle, rotation_axis); + return matrix4_rotate(angle, rotation_axis) } matrix4_orientation :: proc{ matrix4_orientation_f16, matrix4_orientation_f32, matrix4_orientation_f64, -}; +} euclidean_from_polar_f16 :: proc(polar: Vector2f16) -> Vector3f16 { - latitude, longitude := polar.x, polar.y; - cx, sx := math.cos(latitude), math.sin(latitude); - cy, sy := math.cos(longitude), math.sin(longitude); + latitude, longitude := polar.x, polar.y + cx, sx := math.cos(latitude), math.sin(latitude) + cy, sy := math.cos(longitude), math.sin(longitude) return { cx*sy, sx, cx*cy, - }; + } } euclidean_from_polar_f32 :: proc(polar: Vector2f32) -> Vector3f32 { - latitude, longitude := polar.x, polar.y; - cx, sx := math.cos(latitude), math.sin(latitude); - cy, sy := math.cos(longitude), math.sin(longitude); + latitude, longitude := polar.x, polar.y + cx, sx := math.cos(latitude), math.sin(latitude) + cy, sy := math.cos(longitude), math.sin(longitude) return { cx*sy, sx, cx*cy, - }; + } } euclidean_from_polar_f64 :: proc(polar: Vector2f64) -> Vector3f64 { - latitude, longitude := polar.x, polar.y; - cx, sx := math.cos(latitude), math.sin(latitude); - cy, sy := math.cos(longitude), math.sin(longitude); + latitude, longitude := polar.x, polar.y + cx, sx := math.cos(latitude), math.sin(latitude) + cy, sy := math.cos(longitude), math.sin(longitude) return { cx*sy, sx, cx*cy, - }; + } } euclidean_from_polar :: proc{ euclidean_from_polar_f16, euclidean_from_polar_f32, euclidean_from_polar_f64, -}; +} polar_from_euclidean_f16 :: proc(euclidean: Vector3f16) -> Vector3f16 { - n := length(euclidean); - tmp := euclidean / n; + n := length(euclidean) + tmp := euclidean / n - xz_dist := math.sqrt(tmp.x*tmp.x + tmp.z*tmp.z); + xz_dist := math.sqrt(tmp.x*tmp.x + tmp.z*tmp.z) return { math.asin(tmp.y), math.atan2(tmp.x, tmp.z), xz_dist, - }; + } } polar_from_euclidean_f32 :: proc(euclidean: Vector3f32) -> Vector3f32 { - n := length(euclidean); - tmp := euclidean / n; + n := length(euclidean) + tmp := euclidean / n - xz_dist := math.sqrt(tmp.x*tmp.x + tmp.z*tmp.z); + xz_dist := math.sqrt(tmp.x*tmp.x + tmp.z*tmp.z) return { math.asin(tmp.y), math.atan2(tmp.x, tmp.z), xz_dist, - }; + } } polar_from_euclidean_f64 :: proc(euclidean: Vector3f64) -> Vector3f64 { - n := length(euclidean); - tmp := euclidean / n; + n := length(euclidean) + tmp := euclidean / n - xz_dist := math.sqrt(tmp.x*tmp.x + tmp.z*tmp.z); + xz_dist := math.sqrt(tmp.x*tmp.x + tmp.z*tmp.z) return { math.asin(tmp.y), math.atan2(tmp.x, tmp.z), xz_dist, - }; + } } polar_from_euclidean :: proc{ polar_from_euclidean_f16, polar_from_euclidean_f32, polar_from_euclidean_f64, -}; +} diff --git a/core/math/linalg/specific_euler_angles.odin b/core/math/linalg/specific_euler_angles.odin index 000edda12..4d714be54 100644 --- a/core/math/linalg/specific_euler_angles.odin +++ b/core/math/linalg/specific_euler_angles.odin @@ -19,109 +19,109 @@ Euler_Angle_Order :: enum { } -quaternion_from_euler_angles :: proc{quaternion_from_euler_angles_f16, quaternion_from_euler_angles_f32, quaternion_from_euler_angles_f64}; -quaternion_from_euler_angle_x :: proc{quaternion_from_euler_angle_x_f16, quaternion_from_euler_angle_x_f32, quaternion_from_euler_angle_x_f64}; -quaternion_from_euler_angle_y :: proc{quaternion_from_euler_angle_y_f16, quaternion_from_euler_angle_y_f32, quaternion_from_euler_angle_y_f64}; -quaternion_from_euler_angle_z :: proc{quaternion_from_euler_angle_z_f16, quaternion_from_euler_angle_z_f32, quaternion_from_euler_angle_z_f64}; -quaternion_from_pitch_yaw_roll :: proc{quaternion_from_pitch_yaw_roll_f16, quaternion_from_pitch_yaw_roll_f32, quaternion_from_pitch_yaw_roll_f64}; +quaternion_from_euler_angles :: proc{quaternion_from_euler_angles_f16, quaternion_from_euler_angles_f32, quaternion_from_euler_angles_f64} +quaternion_from_euler_angle_x :: proc{quaternion_from_euler_angle_x_f16, quaternion_from_euler_angle_x_f32, quaternion_from_euler_angle_x_f64} +quaternion_from_euler_angle_y :: proc{quaternion_from_euler_angle_y_f16, quaternion_from_euler_angle_y_f32, quaternion_from_euler_angle_y_f64} +quaternion_from_euler_angle_z :: proc{quaternion_from_euler_angle_z_f16, quaternion_from_euler_angle_z_f32, quaternion_from_euler_angle_z_f64} +quaternion_from_pitch_yaw_roll :: proc{quaternion_from_pitch_yaw_roll_f16, quaternion_from_pitch_yaw_roll_f32, quaternion_from_pitch_yaw_roll_f64} -euler_angles_from_quaternion :: proc{euler_angles_from_quaternion_f16, euler_angles_from_quaternion_f32, euler_angles_from_quaternion_f64}; -euler_angles_xyz_from_quaternion :: proc{euler_angles_xyz_from_quaternion_f16, euler_angles_xyz_from_quaternion_f32, euler_angles_xyz_from_quaternion_f64}; -euler_angles_yxz_from_quaternion :: proc{euler_angles_yxz_from_quaternion_f16, euler_angles_yxz_from_quaternion_f32, euler_angles_yxz_from_quaternion_f64}; -euler_angles_xzx_from_quaternion :: proc{euler_angles_xzx_from_quaternion_f16, euler_angles_xzx_from_quaternion_f32, euler_angles_xzx_from_quaternion_f64}; -euler_angles_xyx_from_quaternion :: proc{euler_angles_xyx_from_quaternion_f16, euler_angles_xyx_from_quaternion_f32, euler_angles_xyx_from_quaternion_f64}; -euler_angles_yxy_from_quaternion :: proc{euler_angles_yxy_from_quaternion_f16, euler_angles_yxy_from_quaternion_f32, euler_angles_yxy_from_quaternion_f64}; -euler_angles_yzy_from_quaternion :: proc{euler_angles_yzy_from_quaternion_f16, euler_angles_yzy_from_quaternion_f32, euler_angles_yzy_from_quaternion_f64}; -euler_angles_zyz_from_quaternion :: proc{euler_angles_zyz_from_quaternion_f16, euler_angles_zyz_from_quaternion_f32, euler_angles_zyz_from_quaternion_f64}; -euler_angles_zxz_from_quaternion :: proc{euler_angles_zxz_from_quaternion_f16, euler_angles_zxz_from_quaternion_f32, euler_angles_zxz_from_quaternion_f64}; -euler_angles_xzy_from_quaternion :: proc{euler_angles_xzy_from_quaternion_f16, euler_angles_xzy_from_quaternion_f32, euler_angles_xzy_from_quaternion_f64}; -euler_angles_yzx_from_quaternion :: proc{euler_angles_yzx_from_quaternion_f16, euler_angles_yzx_from_quaternion_f32, euler_angles_yzx_from_quaternion_f64}; -euler_angles_zyx_from_quaternion :: proc{euler_angles_zyx_from_quaternion_f16, euler_angles_zyx_from_quaternion_f32, euler_angles_zyx_from_quaternion_f64}; -euler_angles_zxy_from_quaternion :: proc{euler_angles_zxy_from_quaternion_f16, euler_angles_zxy_from_quaternion_f32, euler_angles_zxy_from_quaternion_f64}; +euler_angles_from_quaternion :: proc{euler_angles_from_quaternion_f16, euler_angles_from_quaternion_f32, euler_angles_from_quaternion_f64} +euler_angles_xyz_from_quaternion :: proc{euler_angles_xyz_from_quaternion_f16, euler_angles_xyz_from_quaternion_f32, euler_angles_xyz_from_quaternion_f64} +euler_angles_yxz_from_quaternion :: proc{euler_angles_yxz_from_quaternion_f16, euler_angles_yxz_from_quaternion_f32, euler_angles_yxz_from_quaternion_f64} +euler_angles_xzx_from_quaternion :: proc{euler_angles_xzx_from_quaternion_f16, euler_angles_xzx_from_quaternion_f32, euler_angles_xzx_from_quaternion_f64} +euler_angles_xyx_from_quaternion :: proc{euler_angles_xyx_from_quaternion_f16, euler_angles_xyx_from_quaternion_f32, euler_angles_xyx_from_quaternion_f64} +euler_angles_yxy_from_quaternion :: proc{euler_angles_yxy_from_quaternion_f16, euler_angles_yxy_from_quaternion_f32, euler_angles_yxy_from_quaternion_f64} +euler_angles_yzy_from_quaternion :: proc{euler_angles_yzy_from_quaternion_f16, euler_angles_yzy_from_quaternion_f32, euler_angles_yzy_from_quaternion_f64} +euler_angles_zyz_from_quaternion :: proc{euler_angles_zyz_from_quaternion_f16, euler_angles_zyz_from_quaternion_f32, euler_angles_zyz_from_quaternion_f64} +euler_angles_zxz_from_quaternion :: proc{euler_angles_zxz_from_quaternion_f16, euler_angles_zxz_from_quaternion_f32, euler_angles_zxz_from_quaternion_f64} +euler_angles_xzy_from_quaternion :: proc{euler_angles_xzy_from_quaternion_f16, euler_angles_xzy_from_quaternion_f32, euler_angles_xzy_from_quaternion_f64} +euler_angles_yzx_from_quaternion :: proc{euler_angles_yzx_from_quaternion_f16, euler_angles_yzx_from_quaternion_f32, euler_angles_yzx_from_quaternion_f64} +euler_angles_zyx_from_quaternion :: proc{euler_angles_zyx_from_quaternion_f16, euler_angles_zyx_from_quaternion_f32, euler_angles_zyx_from_quaternion_f64} +euler_angles_zxy_from_quaternion :: proc{euler_angles_zxy_from_quaternion_f16, euler_angles_zxy_from_quaternion_f32, euler_angles_zxy_from_quaternion_f64} -roll_from_quaternion :: proc{roll_from_quaternion_f16, roll_from_quaternion_f32, roll_from_quaternion_f64}; -pitch_from_quaternion :: proc{pitch_from_quaternion_f16, pitch_from_quaternion_f32, pitch_from_quaternion_f64}; -yaw_from_quaternion :: proc{yaw_from_quaternion_f16, yaw_from_quaternion_f32, yaw_from_quaternion_f64}; -pitch_yaw_roll_from_quaternion :: proc{pitch_yaw_roll_from_quaternion_f16, pitch_yaw_roll_from_quaternion_f32, pitch_yaw_roll_from_quaternion_f64}; +roll_from_quaternion :: proc{roll_from_quaternion_f16, roll_from_quaternion_f32, roll_from_quaternion_f64} +pitch_from_quaternion :: proc{pitch_from_quaternion_f16, pitch_from_quaternion_f32, pitch_from_quaternion_f64} +yaw_from_quaternion :: proc{yaw_from_quaternion_f16, yaw_from_quaternion_f32, yaw_from_quaternion_f64} +pitch_yaw_roll_from_quaternion :: proc{pitch_yaw_roll_from_quaternion_f16, pitch_yaw_roll_from_quaternion_f32, pitch_yaw_roll_from_quaternion_f64} -matrix3_from_euler_angles :: proc{matrix3_from_euler_angles_f16, matrix3_from_euler_angles_f32, matrix3_from_euler_angles_f64}; -matrix3_from_euler_angle_x :: proc{matrix3_from_euler_angle_x_f16, matrix3_from_euler_angle_x_f32, matrix3_from_euler_angle_x_f64}; -matrix3_from_euler_angle_y :: proc{matrix3_from_euler_angle_y_f16, matrix3_from_euler_angle_y_f32, matrix3_from_euler_angle_y_f64}; -matrix3_from_euler_angle_z :: proc{matrix3_from_euler_angle_z_f16, matrix3_from_euler_angle_z_f32, matrix3_from_euler_angle_z_f64}; -matrix3_from_derived_euler_angle_x :: proc{matrix3_from_derived_euler_angle_x_f16, matrix3_from_derived_euler_angle_x_f32, matrix3_from_derived_euler_angle_x_f64}; -matrix3_from_derived_euler_angle_y :: proc{matrix3_from_derived_euler_angle_y_f16, matrix3_from_derived_euler_angle_y_f32, matrix3_from_derived_euler_angle_y_f64}; -matrix3_from_derived_euler_angle_z :: proc{matrix3_from_derived_euler_angle_z_f16, matrix3_from_derived_euler_angle_z_f32, matrix3_from_derived_euler_angle_z_f64}; -matrix3_from_euler_angles_xy :: proc{matrix3_from_euler_angles_xy_f16, matrix3_from_euler_angles_xy_f32, matrix3_from_euler_angles_xy_f64}; -matrix3_from_euler_angles_yx :: proc{matrix3_from_euler_angles_yx_f16, matrix3_from_euler_angles_yx_f32, matrix3_from_euler_angles_yx_f64}; -matrix3_from_euler_angles_xz :: proc{matrix3_from_euler_angles_xz_f16, matrix3_from_euler_angles_xz_f32, matrix3_from_euler_angles_xz_f64}; -matrix3_from_euler_angles_zx :: proc{matrix3_from_euler_angles_zx_f16, matrix3_from_euler_angles_zx_f32, matrix3_from_euler_angles_zx_f64}; -matrix3_from_euler_angles_yz :: proc{matrix3_from_euler_angles_yz_f16, matrix3_from_euler_angles_yz_f32, matrix3_from_euler_angles_yz_f64}; -matrix3_from_euler_angles_zy :: proc{matrix3_from_euler_angles_zy_f16, matrix3_from_euler_angles_zy_f32, matrix3_from_euler_angles_zy_f64}; -matrix3_from_euler_angles_xyz :: proc{matrix3_from_euler_angles_xyz_f16, matrix3_from_euler_angles_xyz_f32, matrix3_from_euler_angles_xyz_f64}; -matrix3_from_euler_angles_yxz :: proc{matrix3_from_euler_angles_yxz_f16, matrix3_from_euler_angles_yxz_f32, matrix3_from_euler_angles_yxz_f64}; -matrix3_from_euler_angles_xzx :: proc{matrix3_from_euler_angles_xzx_f16, matrix3_from_euler_angles_xzx_f32, matrix3_from_euler_angles_xzx_f64}; -matrix3_from_euler_angles_xyx :: proc{matrix3_from_euler_angles_xyx_f16, matrix3_from_euler_angles_xyx_f32, matrix3_from_euler_angles_xyx_f64}; -matrix3_from_euler_angles_yxy :: proc{matrix3_from_euler_angles_yxy_f16, matrix3_from_euler_angles_yxy_f32, matrix3_from_euler_angles_yxy_f64}; -matrix3_from_euler_angles_yzy :: proc{matrix3_from_euler_angles_yzy_f16, matrix3_from_euler_angles_yzy_f32, matrix3_from_euler_angles_yzy_f64}; -matrix3_from_euler_angles_zyz :: proc{matrix3_from_euler_angles_zyz_f16, matrix3_from_euler_angles_zyz_f32, matrix3_from_euler_angles_zyz_f64}; -matrix3_from_euler_angles_zxz :: proc{matrix3_from_euler_angles_zxz_f16, matrix3_from_euler_angles_zxz_f32, matrix3_from_euler_angles_zxz_f64}; -matrix3_from_euler_angles_xzy :: proc{matrix3_from_euler_angles_xzy_f16, matrix3_from_euler_angles_xzy_f32, matrix3_from_euler_angles_xzy_f64}; -matrix3_from_euler_angles_yzx :: proc{matrix3_from_euler_angles_yzx_f16, matrix3_from_euler_angles_yzx_f32, matrix3_from_euler_angles_yzx_f64}; -matrix3_from_euler_angles_zyx :: proc{matrix3_from_euler_angles_zyx_f16, matrix3_from_euler_angles_zyx_f32, matrix3_from_euler_angles_zyx_f64}; -matrix3_from_euler_angles_zxy :: proc{matrix3_from_euler_angles_zxy_f16, matrix3_from_euler_angles_zxy_f32, matrix3_from_euler_angles_zxy_f64}; -matrix3_from_yaw_pitch_roll :: proc{matrix3_from_yaw_pitch_roll_f16, matrix3_from_yaw_pitch_roll_f32, matrix3_from_yaw_pitch_roll_f64}; +matrix3_from_euler_angles :: proc{matrix3_from_euler_angles_f16, matrix3_from_euler_angles_f32, matrix3_from_euler_angles_f64} +matrix3_from_euler_angle_x :: proc{matrix3_from_euler_angle_x_f16, matrix3_from_euler_angle_x_f32, matrix3_from_euler_angle_x_f64} +matrix3_from_euler_angle_y :: proc{matrix3_from_euler_angle_y_f16, matrix3_from_euler_angle_y_f32, matrix3_from_euler_angle_y_f64} +matrix3_from_euler_angle_z :: proc{matrix3_from_euler_angle_z_f16, matrix3_from_euler_angle_z_f32, matrix3_from_euler_angle_z_f64} +matrix3_from_derived_euler_angle_x :: proc{matrix3_from_derived_euler_angle_x_f16, matrix3_from_derived_euler_angle_x_f32, matrix3_from_derived_euler_angle_x_f64} +matrix3_from_derived_euler_angle_y :: proc{matrix3_from_derived_euler_angle_y_f16, matrix3_from_derived_euler_angle_y_f32, matrix3_from_derived_euler_angle_y_f64} +matrix3_from_derived_euler_angle_z :: proc{matrix3_from_derived_euler_angle_z_f16, matrix3_from_derived_euler_angle_z_f32, matrix3_from_derived_euler_angle_z_f64} +matrix3_from_euler_angles_xy :: proc{matrix3_from_euler_angles_xy_f16, matrix3_from_euler_angles_xy_f32, matrix3_from_euler_angles_xy_f64} +matrix3_from_euler_angles_yx :: proc{matrix3_from_euler_angles_yx_f16, matrix3_from_euler_angles_yx_f32, matrix3_from_euler_angles_yx_f64} +matrix3_from_euler_angles_xz :: proc{matrix3_from_euler_angles_xz_f16, matrix3_from_euler_angles_xz_f32, matrix3_from_euler_angles_xz_f64} +matrix3_from_euler_angles_zx :: proc{matrix3_from_euler_angles_zx_f16, matrix3_from_euler_angles_zx_f32, matrix3_from_euler_angles_zx_f64} +matrix3_from_euler_angles_yz :: proc{matrix3_from_euler_angles_yz_f16, matrix3_from_euler_angles_yz_f32, matrix3_from_euler_angles_yz_f64} +matrix3_from_euler_angles_zy :: proc{matrix3_from_euler_angles_zy_f16, matrix3_from_euler_angles_zy_f32, matrix3_from_euler_angles_zy_f64} +matrix3_from_euler_angles_xyz :: proc{matrix3_from_euler_angles_xyz_f16, matrix3_from_euler_angles_xyz_f32, matrix3_from_euler_angles_xyz_f64} +matrix3_from_euler_angles_yxz :: proc{matrix3_from_euler_angles_yxz_f16, matrix3_from_euler_angles_yxz_f32, matrix3_from_euler_angles_yxz_f64} +matrix3_from_euler_angles_xzx :: proc{matrix3_from_euler_angles_xzx_f16, matrix3_from_euler_angles_xzx_f32, matrix3_from_euler_angles_xzx_f64} +matrix3_from_euler_angles_xyx :: proc{matrix3_from_euler_angles_xyx_f16, matrix3_from_euler_angles_xyx_f32, matrix3_from_euler_angles_xyx_f64} +matrix3_from_euler_angles_yxy :: proc{matrix3_from_euler_angles_yxy_f16, matrix3_from_euler_angles_yxy_f32, matrix3_from_euler_angles_yxy_f64} +matrix3_from_euler_angles_yzy :: proc{matrix3_from_euler_angles_yzy_f16, matrix3_from_euler_angles_yzy_f32, matrix3_from_euler_angles_yzy_f64} +matrix3_from_euler_angles_zyz :: proc{matrix3_from_euler_angles_zyz_f16, matrix3_from_euler_angles_zyz_f32, matrix3_from_euler_angles_zyz_f64} +matrix3_from_euler_angles_zxz :: proc{matrix3_from_euler_angles_zxz_f16, matrix3_from_euler_angles_zxz_f32, matrix3_from_euler_angles_zxz_f64} +matrix3_from_euler_angles_xzy :: proc{matrix3_from_euler_angles_xzy_f16, matrix3_from_euler_angles_xzy_f32, matrix3_from_euler_angles_xzy_f64} +matrix3_from_euler_angles_yzx :: proc{matrix3_from_euler_angles_yzx_f16, matrix3_from_euler_angles_yzx_f32, matrix3_from_euler_angles_yzx_f64} +matrix3_from_euler_angles_zyx :: proc{matrix3_from_euler_angles_zyx_f16, matrix3_from_euler_angles_zyx_f32, matrix3_from_euler_angles_zyx_f64} +matrix3_from_euler_angles_zxy :: proc{matrix3_from_euler_angles_zxy_f16, matrix3_from_euler_angles_zxy_f32, matrix3_from_euler_angles_zxy_f64} +matrix3_from_yaw_pitch_roll :: proc{matrix3_from_yaw_pitch_roll_f16, matrix3_from_yaw_pitch_roll_f32, matrix3_from_yaw_pitch_roll_f64} -euler_angles_from_matrix3 :: proc{euler_angles_from_matrix3_f16, euler_angles_from_matrix3_f32, euler_angles_from_matrix3_f64}; -euler_angles_xyz_from_matrix3 :: proc{euler_angles_xyz_from_matrix3_f16, euler_angles_xyz_from_matrix3_f32, euler_angles_xyz_from_matrix3_f64}; -euler_angles_yxz_from_matrix3 :: proc{euler_angles_yxz_from_matrix3_f16, euler_angles_yxz_from_matrix3_f32, euler_angles_yxz_from_matrix3_f64}; -euler_angles_xzx_from_matrix3 :: proc{euler_angles_xzx_from_matrix3_f16, euler_angles_xzx_from_matrix3_f32, euler_angles_xzx_from_matrix3_f64}; -euler_angles_xyx_from_matrix3 :: proc{euler_angles_xyx_from_matrix3_f16, euler_angles_xyx_from_matrix3_f32, euler_angles_xyx_from_matrix3_f64}; -euler_angles_yxy_from_matrix3 :: proc{euler_angles_yxy_from_matrix3_f16, euler_angles_yxy_from_matrix3_f32, euler_angles_yxy_from_matrix3_f64}; -euler_angles_yzy_from_matrix3 :: proc{euler_angles_yzy_from_matrix3_f16, euler_angles_yzy_from_matrix3_f32, euler_angles_yzy_from_matrix3_f64}; -euler_angles_zyz_from_matrix3 :: proc{euler_angles_zyz_from_matrix3_f16, euler_angles_zyz_from_matrix3_f32, euler_angles_zyz_from_matrix3_f64}; -euler_angles_zxz_from_matrix3 :: proc{euler_angles_zxz_from_matrix3_f16, euler_angles_zxz_from_matrix3_f32, euler_angles_zxz_from_matrix3_f64}; -euler_angles_xzy_from_matrix3 :: proc{euler_angles_xzy_from_matrix3_f16, euler_angles_xzy_from_matrix3_f32, euler_angles_xzy_from_matrix3_f64}; -euler_angles_yzx_from_matrix3 :: proc{euler_angles_yzx_from_matrix3_f16, euler_angles_yzx_from_matrix3_f32, euler_angles_yzx_from_matrix3_f64}; -euler_angles_zyx_from_matrix3 :: proc{euler_angles_zyx_from_matrix3_f16, euler_angles_zyx_from_matrix3_f32, euler_angles_zyx_from_matrix3_f64}; -euler_angles_zxy_from_matrix3 :: proc{euler_angles_zxy_from_matrix3_f16, euler_angles_zxy_from_matrix3_f32, euler_angles_zxy_from_matrix3_f64}; +euler_angles_from_matrix3 :: proc{euler_angles_from_matrix3_f16, euler_angles_from_matrix3_f32, euler_angles_from_matrix3_f64} +euler_angles_xyz_from_matrix3 :: proc{euler_angles_xyz_from_matrix3_f16, euler_angles_xyz_from_matrix3_f32, euler_angles_xyz_from_matrix3_f64} +euler_angles_yxz_from_matrix3 :: proc{euler_angles_yxz_from_matrix3_f16, euler_angles_yxz_from_matrix3_f32, euler_angles_yxz_from_matrix3_f64} +euler_angles_xzx_from_matrix3 :: proc{euler_angles_xzx_from_matrix3_f16, euler_angles_xzx_from_matrix3_f32, euler_angles_xzx_from_matrix3_f64} +euler_angles_xyx_from_matrix3 :: proc{euler_angles_xyx_from_matrix3_f16, euler_angles_xyx_from_matrix3_f32, euler_angles_xyx_from_matrix3_f64} +euler_angles_yxy_from_matrix3 :: proc{euler_angles_yxy_from_matrix3_f16, euler_angles_yxy_from_matrix3_f32, euler_angles_yxy_from_matrix3_f64} +euler_angles_yzy_from_matrix3 :: proc{euler_angles_yzy_from_matrix3_f16, euler_angles_yzy_from_matrix3_f32, euler_angles_yzy_from_matrix3_f64} +euler_angles_zyz_from_matrix3 :: proc{euler_angles_zyz_from_matrix3_f16, euler_angles_zyz_from_matrix3_f32, euler_angles_zyz_from_matrix3_f64} +euler_angles_zxz_from_matrix3 :: proc{euler_angles_zxz_from_matrix3_f16, euler_angles_zxz_from_matrix3_f32, euler_angles_zxz_from_matrix3_f64} +euler_angles_xzy_from_matrix3 :: proc{euler_angles_xzy_from_matrix3_f16, euler_angles_xzy_from_matrix3_f32, euler_angles_xzy_from_matrix3_f64} +euler_angles_yzx_from_matrix3 :: proc{euler_angles_yzx_from_matrix3_f16, euler_angles_yzx_from_matrix3_f32, euler_angles_yzx_from_matrix3_f64} +euler_angles_zyx_from_matrix3 :: proc{euler_angles_zyx_from_matrix3_f16, euler_angles_zyx_from_matrix3_f32, euler_angles_zyx_from_matrix3_f64} +euler_angles_zxy_from_matrix3 :: proc{euler_angles_zxy_from_matrix3_f16, euler_angles_zxy_from_matrix3_f32, euler_angles_zxy_from_matrix3_f64} -matrix4_from_euler_angles :: proc{matrix4_from_euler_angles_f16, matrix4_from_euler_angles_f32, matrix4_from_euler_angles_f64}; -matrix4_from_euler_angle_x :: proc{matrix4_from_euler_angle_x_f16, matrix4_from_euler_angle_x_f32, matrix4_from_euler_angle_x_f64}; -matrix4_from_euler_angle_y :: proc{matrix4_from_euler_angle_y_f16, matrix4_from_euler_angle_y_f32, matrix4_from_euler_angle_y_f64}; -matrix4_from_euler_angle_z :: proc{matrix4_from_euler_angle_z_f16, matrix4_from_euler_angle_z_f32, matrix4_from_euler_angle_z_f64}; -matrix4_from_derived_euler_angle_x :: proc{matrix4_from_derived_euler_angle_x_f16, matrix4_from_derived_euler_angle_x_f32, matrix4_from_derived_euler_angle_x_f64}; -matrix4_from_derived_euler_angle_y :: proc{matrix4_from_derived_euler_angle_y_f16, matrix4_from_derived_euler_angle_y_f32, matrix4_from_derived_euler_angle_y_f64}; -matrix4_from_derived_euler_angle_z :: proc{matrix4_from_derived_euler_angle_z_f16, matrix4_from_derived_euler_angle_z_f32, matrix4_from_derived_euler_angle_z_f64}; -matrix4_from_euler_angles_xy :: proc{matrix4_from_euler_angles_xy_f16, matrix4_from_euler_angles_xy_f32, matrix4_from_euler_angles_xy_f64}; -matrix4_from_euler_angles_yx :: proc{matrix4_from_euler_angles_yx_f16, matrix4_from_euler_angles_yx_f32, matrix4_from_euler_angles_yx_f64}; -matrix4_from_euler_angles_xz :: proc{matrix4_from_euler_angles_xz_f16, matrix4_from_euler_angles_xz_f32, matrix4_from_euler_angles_xz_f64}; -matrix4_from_euler_angles_zx :: proc{matrix4_from_euler_angles_zx_f16, matrix4_from_euler_angles_zx_f32, matrix4_from_euler_angles_zx_f64}; -matrix4_from_euler_angles_yz :: proc{matrix4_from_euler_angles_yz_f16, matrix4_from_euler_angles_yz_f32, matrix4_from_euler_angles_yz_f64}; -matrix4_from_euler_angles_zy :: proc{matrix4_from_euler_angles_zy_f16, matrix4_from_euler_angles_zy_f32, matrix4_from_euler_angles_zy_f64}; -matrix4_from_euler_angles_xyz :: proc{matrix4_from_euler_angles_xyz_f16, matrix4_from_euler_angles_xyz_f32, matrix4_from_euler_angles_xyz_f64}; -matrix4_from_euler_angles_yxz :: proc{matrix4_from_euler_angles_yxz_f16, matrix4_from_euler_angles_yxz_f32, matrix4_from_euler_angles_yxz_f64}; -matrix4_from_euler_angles_xzx :: proc{matrix4_from_euler_angles_xzx_f16, matrix4_from_euler_angles_xzx_f32, matrix4_from_euler_angles_xzx_f64}; -matrix4_from_euler_angles_xyx :: proc{matrix4_from_euler_angles_xyx_f16, matrix4_from_euler_angles_xyx_f32, matrix4_from_euler_angles_xyx_f64}; -matrix4_from_euler_angles_yxy :: proc{matrix4_from_euler_angles_yxy_f16, matrix4_from_euler_angles_yxy_f32, matrix4_from_euler_angles_yxy_f64}; -matrix4_from_euler_angles_yzy :: proc{matrix4_from_euler_angles_yzy_f16, matrix4_from_euler_angles_yzy_f32, matrix4_from_euler_angles_yzy_f64}; -matrix4_from_euler_angles_zyz :: proc{matrix4_from_euler_angles_zyz_f16, matrix4_from_euler_angles_zyz_f32, matrix4_from_euler_angles_zyz_f64}; -matrix4_from_euler_angles_zxz :: proc{matrix4_from_euler_angles_zxz_f16, matrix4_from_euler_angles_zxz_f32, matrix4_from_euler_angles_zxz_f64}; -matrix4_from_euler_angles_xzy :: proc{matrix4_from_euler_angles_xzy_f16, matrix4_from_euler_angles_xzy_f32, matrix4_from_euler_angles_xzy_f64}; -matrix4_from_euler_angles_yzx :: proc{matrix4_from_euler_angles_yzx_f16, matrix4_from_euler_angles_yzx_f32, matrix4_from_euler_angles_yzx_f64}; -matrix4_from_euler_angles_zyx :: proc{matrix4_from_euler_angles_zyx_f16, matrix4_from_euler_angles_zyx_f32, matrix4_from_euler_angles_zyx_f64}; -matrix4_from_euler_angles_zxy :: proc{matrix4_from_euler_angles_zxy_f16, matrix4_from_euler_angles_zxy_f32, matrix4_from_euler_angles_zxy_f64}; -matrix4_from_yaw_pitch_roll :: proc{matrix4_from_yaw_pitch_roll_f16, matrix4_from_yaw_pitch_roll_f32, matrix4_from_yaw_pitch_roll_f64}; +matrix4_from_euler_angles :: proc{matrix4_from_euler_angles_f16, matrix4_from_euler_angles_f32, matrix4_from_euler_angles_f64} +matrix4_from_euler_angle_x :: proc{matrix4_from_euler_angle_x_f16, matrix4_from_euler_angle_x_f32, matrix4_from_euler_angle_x_f64} +matrix4_from_euler_angle_y :: proc{matrix4_from_euler_angle_y_f16, matrix4_from_euler_angle_y_f32, matrix4_from_euler_angle_y_f64} +matrix4_from_euler_angle_z :: proc{matrix4_from_euler_angle_z_f16, matrix4_from_euler_angle_z_f32, matrix4_from_euler_angle_z_f64} +matrix4_from_derived_euler_angle_x :: proc{matrix4_from_derived_euler_angle_x_f16, matrix4_from_derived_euler_angle_x_f32, matrix4_from_derived_euler_angle_x_f64} +matrix4_from_derived_euler_angle_y :: proc{matrix4_from_derived_euler_angle_y_f16, matrix4_from_derived_euler_angle_y_f32, matrix4_from_derived_euler_angle_y_f64} +matrix4_from_derived_euler_angle_z :: proc{matrix4_from_derived_euler_angle_z_f16, matrix4_from_derived_euler_angle_z_f32, matrix4_from_derived_euler_angle_z_f64} +matrix4_from_euler_angles_xy :: proc{matrix4_from_euler_angles_xy_f16, matrix4_from_euler_angles_xy_f32, matrix4_from_euler_angles_xy_f64} +matrix4_from_euler_angles_yx :: proc{matrix4_from_euler_angles_yx_f16, matrix4_from_euler_angles_yx_f32, matrix4_from_euler_angles_yx_f64} +matrix4_from_euler_angles_xz :: proc{matrix4_from_euler_angles_xz_f16, matrix4_from_euler_angles_xz_f32, matrix4_from_euler_angles_xz_f64} +matrix4_from_euler_angles_zx :: proc{matrix4_from_euler_angles_zx_f16, matrix4_from_euler_angles_zx_f32, matrix4_from_euler_angles_zx_f64} +matrix4_from_euler_angles_yz :: proc{matrix4_from_euler_angles_yz_f16, matrix4_from_euler_angles_yz_f32, matrix4_from_euler_angles_yz_f64} +matrix4_from_euler_angles_zy :: proc{matrix4_from_euler_angles_zy_f16, matrix4_from_euler_angles_zy_f32, matrix4_from_euler_angles_zy_f64} +matrix4_from_euler_angles_xyz :: proc{matrix4_from_euler_angles_xyz_f16, matrix4_from_euler_angles_xyz_f32, matrix4_from_euler_angles_xyz_f64} +matrix4_from_euler_angles_yxz :: proc{matrix4_from_euler_angles_yxz_f16, matrix4_from_euler_angles_yxz_f32, matrix4_from_euler_angles_yxz_f64} +matrix4_from_euler_angles_xzx :: proc{matrix4_from_euler_angles_xzx_f16, matrix4_from_euler_angles_xzx_f32, matrix4_from_euler_angles_xzx_f64} +matrix4_from_euler_angles_xyx :: proc{matrix4_from_euler_angles_xyx_f16, matrix4_from_euler_angles_xyx_f32, matrix4_from_euler_angles_xyx_f64} +matrix4_from_euler_angles_yxy :: proc{matrix4_from_euler_angles_yxy_f16, matrix4_from_euler_angles_yxy_f32, matrix4_from_euler_angles_yxy_f64} +matrix4_from_euler_angles_yzy :: proc{matrix4_from_euler_angles_yzy_f16, matrix4_from_euler_angles_yzy_f32, matrix4_from_euler_angles_yzy_f64} +matrix4_from_euler_angles_zyz :: proc{matrix4_from_euler_angles_zyz_f16, matrix4_from_euler_angles_zyz_f32, matrix4_from_euler_angles_zyz_f64} +matrix4_from_euler_angles_zxz :: proc{matrix4_from_euler_angles_zxz_f16, matrix4_from_euler_angles_zxz_f32, matrix4_from_euler_angles_zxz_f64} +matrix4_from_euler_angles_xzy :: proc{matrix4_from_euler_angles_xzy_f16, matrix4_from_euler_angles_xzy_f32, matrix4_from_euler_angles_xzy_f64} +matrix4_from_euler_angles_yzx :: proc{matrix4_from_euler_angles_yzx_f16, matrix4_from_euler_angles_yzx_f32, matrix4_from_euler_angles_yzx_f64} +matrix4_from_euler_angles_zyx :: proc{matrix4_from_euler_angles_zyx_f16, matrix4_from_euler_angles_zyx_f32, matrix4_from_euler_angles_zyx_f64} +matrix4_from_euler_angles_zxy :: proc{matrix4_from_euler_angles_zxy_f16, matrix4_from_euler_angles_zxy_f32, matrix4_from_euler_angles_zxy_f64} +matrix4_from_yaw_pitch_roll :: proc{matrix4_from_yaw_pitch_roll_f16, matrix4_from_yaw_pitch_roll_f32, matrix4_from_yaw_pitch_roll_f64} -euler_angles_from_matrix4 :: proc{euler_angles_from_matrix4_f16, euler_angles_from_matrix4_f32, euler_angles_from_matrix4_f64}; -euler_angles_xyz_from_matrix4 :: proc{euler_angles_xyz_from_matrix4_f16, euler_angles_xyz_from_matrix4_f32, euler_angles_xyz_from_matrix4_f64}; -euler_angles_yxz_from_matrix4 :: proc{euler_angles_yxz_from_matrix4_f16, euler_angles_yxz_from_matrix4_f32, euler_angles_yxz_from_matrix4_f64}; -euler_angles_xzx_from_matrix4 :: proc{euler_angles_xzx_from_matrix4_f16, euler_angles_xzx_from_matrix4_f32, euler_angles_xzx_from_matrix4_f64}; -euler_angles_xyx_from_matrix4 :: proc{euler_angles_xyx_from_matrix4_f16, euler_angles_xyx_from_matrix4_f32, euler_angles_xyx_from_matrix4_f64}; -euler_angles_yxy_from_matrix4 :: proc{euler_angles_yxy_from_matrix4_f16, euler_angles_yxy_from_matrix4_f32, euler_angles_yxy_from_matrix4_f64}; -euler_angles_yzy_from_matrix4 :: proc{euler_angles_yzy_from_matrix4_f16, euler_angles_yzy_from_matrix4_f32, euler_angles_yzy_from_matrix4_f64}; -euler_angles_zyz_from_matrix4 :: proc{euler_angles_zyz_from_matrix4_f16, euler_angles_zyz_from_matrix4_f32, euler_angles_zyz_from_matrix4_f64}; -euler_angles_zxz_from_matrix4 :: proc{euler_angles_zxz_from_matrix4_f16, euler_angles_zxz_from_matrix4_f32, euler_angles_zxz_from_matrix4_f64}; -euler_angles_xzy_from_matrix4 :: proc{euler_angles_xzy_from_matrix4_f16, euler_angles_xzy_from_matrix4_f32, euler_angles_xzy_from_matrix4_f64}; -euler_angles_yzx_from_matrix4 :: proc{euler_angles_yzx_from_matrix4_f16, euler_angles_yzx_from_matrix4_f32, euler_angles_yzx_from_matrix4_f64}; -euler_angles_zyx_from_matrix4 :: proc{euler_angles_zyx_from_matrix4_f16, euler_angles_zyx_from_matrix4_f32, euler_angles_zyx_from_matrix4_f64}; -euler_angles_zxy_from_matrix4 :: proc{euler_angles_zxy_from_matrix4_f16, euler_angles_zxy_from_matrix4_f32, euler_angles_zxy_from_matrix4_f64}; +euler_angles_from_matrix4 :: proc{euler_angles_from_matrix4_f16, euler_angles_from_matrix4_f32, euler_angles_from_matrix4_f64} +euler_angles_xyz_from_matrix4 :: proc{euler_angles_xyz_from_matrix4_f16, euler_angles_xyz_from_matrix4_f32, euler_angles_xyz_from_matrix4_f64} +euler_angles_yxz_from_matrix4 :: proc{euler_angles_yxz_from_matrix4_f16, euler_angles_yxz_from_matrix4_f32, euler_angles_yxz_from_matrix4_f64} +euler_angles_xzx_from_matrix4 :: proc{euler_angles_xzx_from_matrix4_f16, euler_angles_xzx_from_matrix4_f32, euler_angles_xzx_from_matrix4_f64} +euler_angles_xyx_from_matrix4 :: proc{euler_angles_xyx_from_matrix4_f16, euler_angles_xyx_from_matrix4_f32, euler_angles_xyx_from_matrix4_f64} +euler_angles_yxy_from_matrix4 :: proc{euler_angles_yxy_from_matrix4_f16, euler_angles_yxy_from_matrix4_f32, euler_angles_yxy_from_matrix4_f64} +euler_angles_yzy_from_matrix4 :: proc{euler_angles_yzy_from_matrix4_f16, euler_angles_yzy_from_matrix4_f32, euler_angles_yzy_from_matrix4_f64} +euler_angles_zyz_from_matrix4 :: proc{euler_angles_zyz_from_matrix4_f16, euler_angles_zyz_from_matrix4_f32, euler_angles_zyz_from_matrix4_f64} +euler_angles_zxz_from_matrix4 :: proc{euler_angles_zxz_from_matrix4_f16, euler_angles_zxz_from_matrix4_f32, euler_angles_zxz_from_matrix4_f64} +euler_angles_xzy_from_matrix4 :: proc{euler_angles_xzy_from_matrix4_f16, euler_angles_xzy_from_matrix4_f32, euler_angles_xzy_from_matrix4_f64} +euler_angles_yzx_from_matrix4 :: proc{euler_angles_yzx_from_matrix4_f16, euler_angles_yzx_from_matrix4_f32, euler_angles_yzx_from_matrix4_f64} +euler_angles_zyx_from_matrix4 :: proc{euler_angles_zyx_from_matrix4_f16, euler_angles_zyx_from_matrix4_f32, euler_angles_zyx_from_matrix4_f64} +euler_angles_zxy_from_matrix4 :: proc{euler_angles_zxy_from_matrix4_f16, euler_angles_zxy_from_matrix4_f32, euler_angles_zxy_from_matrix4_f64} diff --git a/core/math/linalg/specific_euler_angles_f16.odin b/core/math/linalg/specific_euler_angles_f16.odin index bcfac6039..d0fb1beb3 100644 --- a/core/math/linalg/specific_euler_angles_f16.odin +++ b/core/math/linalg/specific_euler_angles_f16.odin @@ -4,206 +4,206 @@ import "core:math" euler_angles_from_matrix3_f16 :: proc(m: Matrix3f16, order: Euler_Angle_Order) -> (t1, t2, t3: f16) { switch order { - case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix3(m); - case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix3(m); - case .YXZ: t1, t2, t3 = euler_angles_yxz_from_matrix3(m); - case .YZX: t1, t2, t3 = euler_angles_yzx_from_matrix3(m); - case .ZXY: t1, t2, t3 = euler_angles_zxy_from_matrix3(m); - case .ZYX: t1, t2, t3 = euler_angles_zyx_from_matrix3(m); - case .XYX: t1, t2, t3 = euler_angles_xyx_from_matrix3(m); - case .XZX: t1, t2, t3 = euler_angles_xzx_from_matrix3(m); - case .YXY: t1, t2, t3 = euler_angles_yxy_from_matrix3(m); - case .YZY: t1, t2, t3 = euler_angles_yzy_from_matrix3(m); - case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_matrix3(m); - case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_matrix3(m); + case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix3(m) + case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix3(m) + case .YXZ: t1, t2, t3 = euler_angles_yxz_from_matrix3(m) + case .YZX: t1, t2, t3 = euler_angles_yzx_from_matrix3(m) + case .ZXY: t1, t2, t3 = euler_angles_zxy_from_matrix3(m) + case .ZYX: t1, t2, t3 = euler_angles_zyx_from_matrix3(m) + case .XYX: t1, t2, t3 = euler_angles_xyx_from_matrix3(m) + case .XZX: t1, t2, t3 = euler_angles_xzx_from_matrix3(m) + case .YXY: t1, t2, t3 = euler_angles_yxy_from_matrix3(m) + case .YZY: t1, t2, t3 = euler_angles_yzy_from_matrix3(m) + case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_matrix3(m) + case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_matrix3(m) } - return; + return } euler_angles_from_matrix4_f16 :: proc(m: Matrix4f16, order: Euler_Angle_Order) -> (t1, t2, t3: f16) { switch order { - case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix4(m); - case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix4(m); - case .YXZ: t1, t2, t3 = euler_angles_yxz_from_matrix4(m); - case .YZX: t1, t2, t3 = euler_angles_yzx_from_matrix4(m); - case .ZXY: t1, t2, t3 = euler_angles_zxy_from_matrix4(m); - case .ZYX: t1, t2, t3 = euler_angles_zyx_from_matrix4(m); - case .XYX: t1, t2, t3 = euler_angles_xyx_from_matrix4(m); - case .XZX: t1, t2, t3 = euler_angles_xzx_from_matrix4(m); - case .YXY: t1, t2, t3 = euler_angles_yxy_from_matrix4(m); - case .YZY: t1, t2, t3 = euler_angles_yzy_from_matrix4(m); - case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_matrix4(m); - case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_matrix4(m); + case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix4(m) + case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix4(m) + case .YXZ: t1, t2, t3 = euler_angles_yxz_from_matrix4(m) + case .YZX: t1, t2, t3 = euler_angles_yzx_from_matrix4(m) + case .ZXY: t1, t2, t3 = euler_angles_zxy_from_matrix4(m) + case .ZYX: t1, t2, t3 = euler_angles_zyx_from_matrix4(m) + case .XYX: t1, t2, t3 = euler_angles_xyx_from_matrix4(m) + case .XZX: t1, t2, t3 = euler_angles_xzx_from_matrix4(m) + case .YXY: t1, t2, t3 = euler_angles_yxy_from_matrix4(m) + case .YZY: t1, t2, t3 = euler_angles_yzy_from_matrix4(m) + case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_matrix4(m) + case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_matrix4(m) } - return; + return } euler_angles_from_quaternion_f16 :: proc(m: Quaternionf16, order: Euler_Angle_Order) -> (t1, t2, t3: f16) { switch order { - case .XYZ: t1, t2, t3 = euler_angles_xyz_from_quaternion(m); - case .XZY: t1, t2, t3 = euler_angles_xzy_from_quaternion(m); - case .YXZ: t1, t2, t3 = euler_angles_yxz_from_quaternion(m); - case .YZX: t1, t2, t3 = euler_angles_yzx_from_quaternion(m); - case .ZXY: t1, t2, t3 = euler_angles_zxy_from_quaternion(m); - case .ZYX: t1, t2, t3 = euler_angles_zyx_from_quaternion(m); - case .XYX: t1, t2, t3 = euler_angles_xyx_from_quaternion(m); - case .XZX: t1, t2, t3 = euler_angles_xzx_from_quaternion(m); - case .YXY: t1, t2, t3 = euler_angles_yxy_from_quaternion(m); - case .YZY: t1, t2, t3 = euler_angles_yzy_from_quaternion(m); - case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_quaternion(m); - case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_quaternion(m); + case .XYZ: t1, t2, t3 = euler_angles_xyz_from_quaternion(m) + case .XZY: t1, t2, t3 = euler_angles_xzy_from_quaternion(m) + case .YXZ: t1, t2, t3 = euler_angles_yxz_from_quaternion(m) + case .YZX: t1, t2, t3 = euler_angles_yzx_from_quaternion(m) + case .ZXY: t1, t2, t3 = euler_angles_zxy_from_quaternion(m) + case .ZYX: t1, t2, t3 = euler_angles_zyx_from_quaternion(m) + case .XYX: t1, t2, t3 = euler_angles_xyx_from_quaternion(m) + case .XZX: t1, t2, t3 = euler_angles_xzx_from_quaternion(m) + case .YXY: t1, t2, t3 = euler_angles_yxy_from_quaternion(m) + case .YZY: t1, t2, t3 = euler_angles_yzy_from_quaternion(m) + case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_quaternion(m) + case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_quaternion(m) } - return; + return } matrix3_from_euler_angles_f16 :: proc(t1, t2, t3: f16, order: Euler_Angle_Order) -> (m: Matrix3f16) { switch order { - case .XYZ: return matrix3_from_euler_angles_xyz(t1, t2, t3); // m1, m2, m3 = X(t1), Y(t2), Z(t3); - case .XZY: return matrix3_from_euler_angles_xzy(t1, t2, t3); // m1, m2, m3 = X(t1), Z(t2), Y(t3); - case .YXZ: return matrix3_from_euler_angles_yxz(t1, t2, t3); // m1, m2, m3 = Y(t1), X(t2), Z(t3); - case .YZX: return matrix3_from_euler_angles_yzx(t1, t2, t3); // m1, m2, m3 = Y(t1), Z(t2), X(t3); - case .ZXY: return matrix3_from_euler_angles_zxy(t1, t2, t3); // m1, m2, m3 = Z(t1), X(t2), Y(t3); - case .ZYX: return matrix3_from_euler_angles_zyx(t1, t2, t3); // m1, m2, m3 = Z(t1), Y(t2), X(t3); - case .XYX: return matrix3_from_euler_angles_xyx(t1, t2, t3); // m1, m2, m3 = X(t1), Y(t2), X(t3); - case .XZX: return matrix3_from_euler_angles_xzx(t1, t2, t3); // m1, m2, m3 = X(t1), Z(t2), X(t3); - case .YXY: return matrix3_from_euler_angles_yxy(t1, t2, t3); // m1, m2, m3 = Y(t1), X(t2), Y(t3); - case .YZY: return matrix3_from_euler_angles_yzy(t1, t2, t3); // m1, m2, m3 = Y(t1), Z(t2), Y(t3); - case .ZXZ: return matrix3_from_euler_angles_zxz(t1, t2, t3); // m1, m2, m3 = Z(t1), X(t2), Z(t3); - case .ZYZ: return matrix3_from_euler_angles_zyz(t1, t2, t3); // m1, m2, m3 = Z(t1), Y(t2), Z(t3); + case .XYZ: return matrix3_from_euler_angles_xyz(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), Z(t3); + case .XZY: return matrix3_from_euler_angles_xzy(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), Y(t3); + case .YXZ: return matrix3_from_euler_angles_yxz(t1, t2, t3) // m1, m2, m3 = Y(t1), X(t2), Z(t3); + case .YZX: return matrix3_from_euler_angles_yzx(t1, t2, t3) // m1, m2, m3 = Y(t1), Z(t2), X(t3); + case .ZXY: return matrix3_from_euler_angles_zxy(t1, t2, t3) // m1, m2, m3 = Z(t1), X(t2), Y(t3); + case .ZYX: return matrix3_from_euler_angles_zyx(t1, t2, t3) // m1, m2, m3 = Z(t1), Y(t2), X(t3); + case .XYX: return matrix3_from_euler_angles_xyx(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), X(t3); + case .XZX: return matrix3_from_euler_angles_xzx(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), X(t3); + case .YXY: return matrix3_from_euler_angles_yxy(t1, t2, t3) // m1, m2, m3 = Y(t1), X(t2), Y(t3); + case .YZY: return matrix3_from_euler_angles_yzy(t1, t2, t3) // m1, m2, m3 = Y(t1), Z(t2), Y(t3); + case .ZXZ: return matrix3_from_euler_angles_zxz(t1, t2, t3) // m1, m2, m3 = Z(t1), X(t2), Z(t3); + case .ZYZ: return matrix3_from_euler_angles_zyz(t1, t2, t3) // m1, m2, m3 = Z(t1), Y(t2), Z(t3); } - return; + return } matrix4_from_euler_angles_f16 :: proc(t1, t2, t3: f16, order: Euler_Angle_Order) -> (m: Matrix4f16) { switch order { - case .XYZ: return matrix4_from_euler_angles_xyz(t1, t2, t3); // m1, m2, m3 = X(t1), Y(t2), Z(t3); - case .XZY: return matrix4_from_euler_angles_xzy(t1, t2, t3); // m1, m2, m3 = X(t1), Z(t2), Y(t3); - case .YXZ: return matrix4_from_euler_angles_yxz(t1, t2, t3); // m1, m2, m3 = Y(t1), X(t2), Z(t3); - case .YZX: return matrix4_from_euler_angles_yzx(t1, t2, t3); // m1, m2, m3 = Y(t1), Z(t2), X(t3); - case .ZXY: return matrix4_from_euler_angles_zxy(t1, t2, t3); // m1, m2, m3 = Z(t1), X(t2), Y(t3); - case .ZYX: return matrix4_from_euler_angles_zyx(t1, t2, t3); // m1, m2, m3 = Z(t1), Y(t2), X(t3); - case .XYX: return matrix4_from_euler_angles_xyx(t1, t2, t3); // m1, m2, m3 = X(t1), Y(t2), X(t3); - case .XZX: return matrix4_from_euler_angles_xzx(t1, t2, t3); // m1, m2, m3 = X(t1), Z(t2), X(t3); - case .YXY: return matrix4_from_euler_angles_yxy(t1, t2, t3); // m1, m2, m3 = Y(t1), X(t2), Y(t3); - case .YZY: return matrix4_from_euler_angles_yzy(t1, t2, t3); // m1, m2, m3 = Y(t1), Z(t2), Y(t3); - case .ZXZ: return matrix4_from_euler_angles_zxz(t1, t2, t3); // m1, m2, m3 = Z(t1), X(t2), Z(t3); - case .ZYZ: return matrix4_from_euler_angles_zyz(t1, t2, t3); // m1, m2, m3 = Z(t1), Y(t2), Z(t3); + case .XYZ: return matrix4_from_euler_angles_xyz(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), Z(t3); + case .XZY: return matrix4_from_euler_angles_xzy(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), Y(t3); + case .YXZ: return matrix4_from_euler_angles_yxz(t1, t2, t3) // m1, m2, m3 = Y(t1), X(t2), Z(t3); + case .YZX: return matrix4_from_euler_angles_yzx(t1, t2, t3) // m1, m2, m3 = Y(t1), Z(t2), X(t3); + case .ZXY: return matrix4_from_euler_angles_zxy(t1, t2, t3) // m1, m2, m3 = Z(t1), X(t2), Y(t3); + case .ZYX: return matrix4_from_euler_angles_zyx(t1, t2, t3) // m1, m2, m3 = Z(t1), Y(t2), X(t3); + case .XYX: return matrix4_from_euler_angles_xyx(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), X(t3); + case .XZX: return matrix4_from_euler_angles_xzx(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), X(t3); + case .YXY: return matrix4_from_euler_angles_yxy(t1, t2, t3) // m1, m2, m3 = Y(t1), X(t2), Y(t3); + case .YZY: return matrix4_from_euler_angles_yzy(t1, t2, t3) // m1, m2, m3 = Y(t1), Z(t2), Y(t3); + case .ZXZ: return matrix4_from_euler_angles_zxz(t1, t2, t3) // m1, m2, m3 = Z(t1), X(t2), Z(t3); + case .ZYZ: return matrix4_from_euler_angles_zyz(t1, t2, t3) // m1, m2, m3 = Z(t1), Y(t2), Z(t3); } - return; + return } quaternion_from_euler_angles_f16 :: proc(t1, t2, t3: f16, order: Euler_Angle_Order) -> Quaternionf16 { - X :: quaternion_from_euler_angle_x; - Y :: quaternion_from_euler_angle_y; - Z :: quaternion_from_euler_angle_z; + X :: quaternion_from_euler_angle_x + Y :: quaternion_from_euler_angle_y + Z :: quaternion_from_euler_angle_z - q1, q2, q3: Quaternionf16; + q1, q2, q3: Quaternionf16 switch order { - case .XYZ: q1, q2, q3 = X(t1), Y(t2), Z(t3); - case .XZY: q1, q2, q3 = X(t1), Z(t2), Y(t3); - case .YXZ: q1, q2, q3 = Y(t1), X(t2), Z(t3); - case .YZX: q1, q2, q3 = Y(t1), Z(t2), X(t3); - case .ZXY: q1, q2, q3 = Z(t1), X(t2), Y(t3); - case .ZYX: q1, q2, q3 = Z(t1), Y(t2), X(t3); - case .XYX: q1, q2, q3 = X(t1), Y(t2), X(t3); - case .XZX: q1, q2, q3 = X(t1), Z(t2), X(t3); - case .YXY: q1, q2, q3 = Y(t1), X(t2), Y(t3); - case .YZY: q1, q2, q3 = Y(t1), Z(t2), Y(t3); - case .ZXZ: q1, q2, q3 = Z(t1), X(t2), Z(t3); - case .ZYZ: q1, q2, q3 = Z(t1), Y(t2), Z(t3); + case .XYZ: q1, q2, q3 = X(t1), Y(t2), Z(t3) + case .XZY: q1, q2, q3 = X(t1), Z(t2), Y(t3) + case .YXZ: q1, q2, q3 = Y(t1), X(t2), Z(t3) + case .YZX: q1, q2, q3 = Y(t1), Z(t2), X(t3) + case .ZXY: q1, q2, q3 = Z(t1), X(t2), Y(t3) + case .ZYX: q1, q2, q3 = Z(t1), Y(t2), X(t3) + case .XYX: q1, q2, q3 = X(t1), Y(t2), X(t3) + case .XZX: q1, q2, q3 = X(t1), Z(t2), X(t3) + case .YXY: q1, q2, q3 = Y(t1), X(t2), Y(t3) + case .YZY: q1, q2, q3 = Y(t1), Z(t2), Y(t3) + case .ZXZ: q1, q2, q3 = Z(t1), X(t2), Z(t3) + case .ZYZ: q1, q2, q3 = Z(t1), Y(t2), Z(t3) } - return q1 * (q2 * q3); + return q1 * (q2 * q3) } // Quaternionf16s quaternion_from_euler_angle_x_f16 :: proc(angle_x: f16) -> (q: Quaternionf16) { - return quaternion_angle_axis_f16(angle_x, {1, 0, 0}); + return quaternion_angle_axis_f16(angle_x, {1, 0, 0}) } quaternion_from_euler_angle_y_f16 :: proc(angle_y: f16) -> (q: Quaternionf16) { - return quaternion_angle_axis_f16(angle_y, {0, 1, 0}); + return quaternion_angle_axis_f16(angle_y, {0, 1, 0}) } quaternion_from_euler_angle_z_f16 :: proc(angle_z: f16) -> (q: Quaternionf16) { - return quaternion_angle_axis_f16(angle_z, {0, 0, 1}); + return quaternion_angle_axis_f16(angle_z, {0, 0, 1}) } quaternion_from_pitch_yaw_roll_f16 :: proc(pitch, yaw, roll: f16) -> Quaternionf16 { - a, b, c := pitch, yaw, roll; + a, b, c := pitch, yaw, roll - ca, sa := math.cos(a*0.5), math.sin(a*0.5); - cb, sb := math.cos(b*0.5), math.sin(b*0.5); - cc, sc := math.cos(c*0.5), math.sin(c*0.5); + ca, sa := math.cos(a*0.5), math.sin(a*0.5) + cb, sb := math.cos(b*0.5), math.sin(b*0.5) + cc, sc := math.cos(c*0.5), math.sin(c*0.5) - q: Quaternionf16; - q.x = sa*cb*cc - ca*sb*sc; - q.y = ca*sb*cc + sa*cb*sc; - q.z = ca*cb*sc - sa*sb*cc; - q.w = ca*cb*cc + sa*sb*sc; - return q; + q: Quaternionf16 + q.x = sa*cb*cc - ca*sb*sc + q.y = ca*sb*cc + sa*cb*sc + q.z = ca*cb*sc - sa*sb*cc + q.w = ca*cb*cc + sa*sb*sc + return q } roll_from_quaternion_f16 :: proc(q: Quaternionf16) -> f16 { - return math.atan2(2 * q.x*q.y + q.w*q.z, q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z); + return math.atan2(2 * q.x*q.y + q.w*q.z, q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z) } pitch_from_quaternion_f16 :: proc(q: Quaternionf16) -> f16 { - y := 2 * (q.y*q.z + q.w*q.w); - x := q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z; + y := 2 * (q.y*q.z + q.w*q.w) + x := q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z if abs(x) <= F16_EPSILON && abs(y) <= F16_EPSILON { - return 2 * math.atan2(q.x, q.w); + return 2 * math.atan2(q.x, q.w) } - return math.atan2(y, x); + return math.atan2(y, x) } yaw_from_quaternion_f16 :: proc(q: Quaternionf16) -> f16 { - return math.asin(clamp(-2 * (q.x*q.z - q.w*q.y), -1, 1)); + return math.asin(clamp(-2 * (q.x*q.z - q.w*q.y), -1, 1)) } pitch_yaw_roll_from_quaternion_f16 :: proc(q: Quaternionf16) -> (pitch, yaw, roll: f16) { - pitch = pitch_from_quaternion(q); - yaw = yaw_from_quaternion(q); - roll = roll_from_quaternion(q); - return; + pitch = pitch_from_quaternion(q) + yaw = yaw_from_quaternion(q) + roll = roll_from_quaternion(q) + return } euler_angles_xyz_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { - return euler_angles_xyz_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_xyz_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_yxz_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { - return euler_angles_yxz_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_yxz_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_xzx_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { - return euler_angles_xzx_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_xzx_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_xyx_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { - return euler_angles_xyx_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_xyx_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_yxy_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { - return euler_angles_yxy_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_yxy_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_yzy_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { - return euler_angles_yzy_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_yzy_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_zyz_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { - return euler_angles_zyz_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_zyz_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_zxz_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { - return euler_angles_zxz_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_zxz_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_xzy_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { - return euler_angles_xzy_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_xzy_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_yzx_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { - return euler_angles_yzx_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_yzx_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_zyx_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { - return euler_angles_zyx_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_zyx_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_zxy_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { - return euler_angles_zxy_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_zxy_from_matrix4(matrix4_from_quaternion(q)) } @@ -211,524 +211,524 @@ euler_angles_zxy_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f matrix3_from_euler_angle_x_f16 :: proc(angle_x: f16) -> (m: Matrix3f16) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - m[0][0] = 1; - m[1][1] = +cos_x; - m[2][1] = +sin_x; - m[1][2] = -sin_x; - m[2][2] = +cos_x; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + m[0][0] = 1 + m[1][1] = +cos_x + m[2][1] = +sin_x + m[1][2] = -sin_x + m[2][2] = +cos_x + return } matrix3_from_euler_angle_y_f16 :: proc(angle_y: f16) -> (m: Matrix3f16) { - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = +cos_y; - m[2][0] = -sin_y; - m[1][1] = 1; - m[0][2] = +sin_y; - m[2][2] = +cos_y; - return; + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = +cos_y + m[2][0] = -sin_y + m[1][1] = 1 + m[0][2] = +sin_y + m[2][2] = +cos_y + return } matrix3_from_euler_angle_z_f16 :: proc(angle_z: f16) -> (m: Matrix3f16) { - cos_z, sin_z := math.cos(angle_z), math.sin(angle_z); - m[0][0] = +cos_z; - m[1][0] = +sin_z; - m[1][1] = +cos_z; - m[0][1] = -sin_z; - m[2][2] = 1; - return; + cos_z, sin_z := math.cos(angle_z), math.sin(angle_z) + m[0][0] = +cos_z + m[1][0] = +sin_z + m[1][1] = +cos_z + m[0][1] = -sin_z + m[2][2] = 1 + return } matrix3_from_derived_euler_angle_x_f16 :: proc(angle_x: f16, angular_velocity_x: f16) -> (m: Matrix3f16) { - cos_x := math.cos(angle_x) * angular_velocity_x; - sin_x := math.sin(angle_x) * angular_velocity_x; - m[0][0] = 1; - m[1][1] = +cos_x; - m[2][1] = +sin_x; - m[1][2] = -sin_x; - m[2][2] = +cos_x; - return; + cos_x := math.cos(angle_x) * angular_velocity_x + sin_x := math.sin(angle_x) * angular_velocity_x + m[0][0] = 1 + m[1][1] = +cos_x + m[2][1] = +sin_x + m[1][2] = -sin_x + m[2][2] = +cos_x + return } matrix3_from_derived_euler_angle_y_f16 :: proc(angle_y: f16, angular_velocity_y: f16) -> (m: Matrix3f16) { - cos_y := math.cos(angle_y) * angular_velocity_y; - sin_y := math.sin(angle_y) * angular_velocity_y; - m[0][0] = +cos_y; - m[2][0] = -sin_y; - m[1][1] = 1; - m[0][2] = +sin_y; - m[2][2] = +cos_y; - return; + cos_y := math.cos(angle_y) * angular_velocity_y + sin_y := math.sin(angle_y) * angular_velocity_y + m[0][0] = +cos_y + m[2][0] = -sin_y + m[1][1] = 1 + m[0][2] = +sin_y + m[2][2] = +cos_y + return } matrix3_from_derived_euler_angle_z_f16 :: proc(angle_z: f16, angular_velocity_z: f16) -> (m: Matrix3f16) { - cos_z := math.cos(angle_z) * angular_velocity_z; - sin_z := math.sin(angle_z) * angular_velocity_z; - m[0][0] = +cos_z; - m[1][0] = +sin_z; - m[1][1] = +cos_z; - m[0][1] = -sin_z; - m[2][2] = 1; - return; + cos_z := math.cos(angle_z) * angular_velocity_z + sin_z := math.sin(angle_z) * angular_velocity_z + m[0][0] = +cos_z + m[1][0] = +sin_z + m[1][1] = +cos_z + m[0][1] = -sin_z + m[2][2] = 1 + return } matrix3_from_euler_angles_xy_f16 :: proc(angle_x, angle_y: f16) -> (m: Matrix3f16) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = cos_y; - m[1][0] = -sin_x * - sin_y; - m[2][0] = -cos_x * - sin_y; - m[1][1] = cos_x; - m[2][1] = sin_x; - m[0][2] = sin_y; - m[1][2] = -sin_x * cos_y; - m[2][2] = cos_x * cos_y; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = cos_y + m[1][0] = -sin_x * - sin_y + m[2][0] = -cos_x * - sin_y + m[1][1] = cos_x + m[2][1] = sin_x + m[0][2] = sin_y + m[1][2] = -sin_x * cos_y + m[2][2] = cos_x * cos_y + return } matrix3_from_euler_angles_yx_f16 :: proc(angle_y, angle_x: f16) -> (m: Matrix3f16) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = cos_y; - m[2][0] = -sin_y; - m[0][1] = sin_y*sin_x; - m[1][1] = cos_x; - m[2][1] = cos_y*sin_x; - m[0][2] = sin_y*cos_x; - m[1][2] = -sin_x; - m[2][2] = cos_y*cos_x; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = cos_y + m[2][0] = -sin_y + m[0][1] = sin_y*sin_x + m[1][1] = cos_x + m[2][1] = cos_y*sin_x + m[0][2] = sin_y*cos_x + m[1][2] = -sin_x + m[2][2] = cos_y*cos_x + return } matrix3_from_euler_angles_xz_f16 :: proc(angle_x, angle_z: f16) -> (m: Matrix3f16) { - return mul(matrix3_from_euler_angle_x(angle_x), matrix3_from_euler_angle_z(angle_z)); + return mul(matrix3_from_euler_angle_x(angle_x), matrix3_from_euler_angle_z(angle_z)) } matrix3_from_euler_angles_zx_f16 :: proc(angle_z, angle_x: f16) -> (m: Matrix3f16) { - return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_x(angle_x)); + return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_x(angle_x)) } matrix3_from_euler_angles_yz_f16 :: proc(angle_y, angle_z: f16) -> (m: Matrix3f16) { - return mul(matrix3_from_euler_angle_y(angle_y), matrix3_from_euler_angle_z(angle_z)); + return mul(matrix3_from_euler_angle_y(angle_y), matrix3_from_euler_angle_z(angle_z)) } matrix3_from_euler_angles_zy_f16 :: proc(angle_z, angle_y: f16) -> (m: Matrix3f16) { - return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_y(angle_y)); + return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_y(angle_y)) } matrix3_from_euler_angles_xyz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { - c1 := math.cos(-t1); - c2 := math.cos(-t2); - c3 := math.cos(-t3); - s1 := math.sin(-t1); - s2 := math.sin(-t2); - s3 := math.sin(-t3); - - m[0][0] = c2 * c3; - m[0][1] =-c1 * s3 + s1 * s2 * c3; - m[0][2] = s1 * s3 + c1 * s2 * c3; - m[1][0] = c2 * s3; - m[1][1] = c1 * c3 + s1 * s2 * s3; - m[1][2] =-s1 * c3 + c1 * s2 * s3; - m[2][0] =-s2; - m[2][1] = s1 * c2; - m[2][2] = c1 * c2; - return; + c1 := math.cos(-t1) + c2 := math.cos(-t2) + c3 := math.cos(-t3) + s1 := math.sin(-t1) + s2 := math.sin(-t2) + s3 := math.sin(-t3) + + m[0][0] = c2 * c3 + m[0][1] =-c1 * s3 + s1 * s2 * c3 + m[0][2] = s1 * s3 + c1 * s2 * c3 + m[1][0] = c2 * s3 + m[1][1] = c1 * c3 + s1 * s2 * s3 + m[1][2] =-s1 * c3 + c1 * s2 * s3 + m[2][0] =-s2 + m[2][1] = s1 * c2 + m[2][2] = c1 * c2 + return } matrix3_from_euler_angles_yxz_f16 :: proc(yaw, pitch, roll: f16) -> (m: Matrix3f16) { - ch := math.cos(yaw); - sh := math.sin(yaw); - cp := math.cos(pitch); - sp := math.sin(pitch); - cb := math.cos(roll); - sb := math.sin(roll); - - m[0][0] = ch * cb + sh * sp * sb; - m[0][1] = sb * cp; - m[0][2] = -sh * cb + ch * sp * sb; - m[1][0] = -ch * sb + sh * sp * cb; - m[1][1] = cb * cp; - m[1][2] = sb * sh + ch * sp * cb; - m[2][0] = sh * cp; - m[2][1] = -sp; - m[2][2] = ch * cp; - return; + ch := math.cos(yaw) + sh := math.sin(yaw) + cp := math.cos(pitch) + sp := math.sin(pitch) + cb := math.cos(roll) + sb := math.sin(roll) + + m[0][0] = ch * cb + sh * sp * sb + m[0][1] = sb * cp + m[0][2] = -sh * cb + ch * sp * sb + m[1][0] = -ch * sb + sh * sp * cb + m[1][1] = cb * cp + m[1][2] = sb * sh + ch * sp * cb + m[2][0] = sh * cp + m[2][1] = -sp + m[2][2] = ch * cp + return } matrix3_from_euler_angles_xzx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2; - m[0][1] = c1 * s2; - m[0][2] = s1 * s2; - m[1][0] =-c3 * s2; - m[1][1] = c1 * c2 * c3 - s1 * s3; - m[1][2] = c1 * s3 + c2 * c3 * s1; - m[2][0] = s2 * s3; - m[2][1] =-c3 * s1 - c1 * c2 * s3; - m[2][2] = c1 * c3 - c2 * s1 * s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 + m[0][1] = c1 * s2 + m[0][2] = s1 * s2 + m[1][0] =-c3 * s2 + m[1][1] = c1 * c2 * c3 - s1 * s3 + m[1][2] = c1 * s3 + c2 * c3 * s1 + m[2][0] = s2 * s3 + m[2][1] =-c3 * s1 - c1 * c2 * s3 + m[2][2] = c1 * c3 - c2 * s1 * s3 + return } matrix3_from_euler_angles_xyx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2; - m[0][1] = s1 * s2; - m[0][2] =-c1 * s2; - m[1][0] = s2 * s3; - m[1][1] = c1 * c3 - c2 * s1 * s3; - m[1][2] = c3 * s1 + c1 * c2 * s3; - m[2][0] = c3 * s2; - m[2][1] =-c1 * s3 - c2 * c3 * s1; - m[2][2] = c1 * c2 * c3 - s1 * s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 + m[0][1] = s1 * s2 + m[0][2] =-c1 * s2 + m[1][0] = s2 * s3 + m[1][1] = c1 * c3 - c2 * s1 * s3 + m[1][2] = c3 * s1 + c1 * c2 * s3 + m[2][0] = c3 * s2 + m[2][1] =-c1 * s3 - c2 * c3 * s1 + m[2][2] = c1 * c2 * c3 - s1 * s3 + return } matrix3_from_euler_angles_yxy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - c2 * s1 * s3; - m[0][1] = s2* s3; - m[0][2] =-c3 * s1 - c1 * c2 * s3; - m[1][0] = s1 * s2; - m[1][1] = c2; - m[1][2] = c1 * s2; - m[2][0] = c1 * s3 + c2 * c3 * s1; - m[2][1] =-c3 * s2; - m[2][2] = c1 * c2 * c3 - s1 * s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - c2 * s1 * s3 + m[0][1] = s2* s3 + m[0][2] =-c3 * s1 - c1 * c2 * s3 + m[1][0] = s1 * s2 + m[1][1] = c2 + m[1][2] = c1 * s2 + m[2][0] = c1 * s3 + c2 * c3 * s1 + m[2][1] =-c3 * s2 + m[2][2] = c1 * c2 * c3 - s1 * s3 + return } matrix3_from_euler_angles_yzy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2 * c3 - s1 * s3; - m[0][1] = c3 * s2; - m[0][2] =-c1 * s3 - c2 * c3 * s1; - m[1][0] =-c1 * s2; - m[1][1] = c2; - m[1][2] = s1 * s2; - m[2][0] = c3 * s1 + c1 * c2 * s3; - m[2][1] = s2 * s3; - m[2][2] = c1 * c3 - c2 * s1 * s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 * c3 - s1 * s3 + m[0][1] = c3 * s2 + m[0][2] =-c1 * s3 - c2 * c3 * s1 + m[1][0] =-c1 * s2 + m[1][1] = c2 + m[1][2] = s1 * s2 + m[2][0] = c3 * s1 + c1 * c2 * s3 + m[2][1] = s2 * s3 + m[2][2] = c1 * c3 - c2 * s1 * s3 + return } matrix3_from_euler_angles_zyz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2 * c3 - s1 * s3; - m[0][1] = c1 * s3 + c2 * c3 * s1; - m[0][2] =-c3 * s2; - m[1][0] =-c3 * s1 - c1 * c2 * s3; - m[1][1] = c1 * c3 - c2 * s1 * s3; - m[1][2] = s2 * s3; - m[2][0] = c1 * s2; - m[2][1] = s1 * s2; - m[2][2] = c2; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 * c3 - s1 * s3 + m[0][1] = c1 * s3 + c2 * c3 * s1 + m[0][2] =-c3 * s2 + m[1][0] =-c3 * s1 - c1 * c2 * s3 + m[1][1] = c1 * c3 - c2 * s1 * s3 + m[1][2] = s2 * s3 + m[2][0] = c1 * s2 + m[2][1] = s1 * s2 + m[2][2] = c2 + return } matrix3_from_euler_angles_zxz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - c2 * s1 * s3; - m[0][1] = c3 * s1 + c1 * c2 * s3; - m[0][2] = s2 *s3; - m[1][0] =-c1 * s3 - c2 * c3 * s1; - m[1][1] = c1 * c2 * c3 - s1 * s3; - m[1][2] = c3 * s2; - m[2][0] = s1 * s2; - m[2][1] =-c1 * s2; - m[2][2] = c2; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - c2 * s1 * s3 + m[0][1] = c3 * s1 + c1 * c2 * s3 + m[0][2] = s2 *s3 + m[1][0] =-c1 * s3 - c2 * c3 * s1 + m[1][1] = c1 * c2 * c3 - s1 * s3 + m[1][2] = c3 * s2 + m[2][0] = s1 * s2 + m[2][1] =-c1 * s2 + m[2][2] = c2 + return } matrix3_from_euler_angles_xzy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2 * c3; - m[0][1] = s1 * s3 + c1 * c3 * s2; - m[0][2] = c3 * s1 * s2 - c1 * s3; - m[1][0] =-s2; - m[1][1] = c1 * c2; - m[1][2] = c2 * s1; - m[2][0] = c2 * s3; - m[2][1] = c1 * s2 * s3 - c3 * s1; - m[2][2] = c1 * c3 + s1 * s2 *s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 * c3 + m[0][1] = s1 * s3 + c1 * c3 * s2 + m[0][2] = c3 * s1 * s2 - c1 * s3 + m[1][0] =-s2 + m[1][1] = c1 * c2 + m[1][2] = c2 * s1 + m[2][0] = c2 * s3 + m[2][1] = c1 * s2 * s3 - c3 * s1 + m[2][2] = c1 * c3 + s1 * s2 *s3 + return } matrix3_from_euler_angles_yzx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2; - m[0][1] = s2; - m[0][2] =-c2 * s1; - m[1][0] = s1 * s3 - c1 * c3 * s2; - m[1][1] = c2 * c3; - m[1][2] = c1 * s3 + c3 * s1 * s2; - m[2][0] = c3 * s1 + c1 * s2 * s3; - m[2][1] =-c2 * s3; - m[2][2] = c1 * c3 - s1 * s2 * s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 + m[0][1] = s2 + m[0][2] =-c2 * s1 + m[1][0] = s1 * s3 - c1 * c3 * s2 + m[1][1] = c2 * c3 + m[1][2] = c1 * s3 + c3 * s1 * s2 + m[2][0] = c3 * s1 + c1 * s2 * s3 + m[2][1] =-c2 * s3 + m[2][2] = c1 * c3 - s1 * s2 * s3 + return } matrix3_from_euler_angles_zyx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2; - m[0][1] = c2 * s1; - m[0][2] =-s2; - m[1][0] = c1 * s2 * s3 - c3 * s1; - m[1][1] = c1 * c3 + s1 * s2 * s3; - m[1][2] = c2 * s3; - m[2][0] = s1 * s3 + c1 * c3 * s2; - m[2][1] = c3 * s1 * s2 - c1 * s3; - m[2][2] = c2 * c3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 + m[0][1] = c2 * s1 + m[0][2] =-s2 + m[1][0] = c1 * s2 * s3 - c3 * s1 + m[1][1] = c1 * c3 + s1 * s2 * s3 + m[1][2] = c2 * s3 + m[2][0] = s1 * s3 + c1 * c3 * s2 + m[2][1] = c3 * s1 * s2 - c1 * s3 + m[2][2] = c2 * c3 + return } matrix3_from_euler_angles_zxy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - s1 * s2 * s3; - m[0][1] = c3 * s1 + c1 * s2 * s3; - m[0][2] =-c2 * s3; - m[1][0] =-c2 * s1; - m[1][1] = c1 * c2; - m[1][2] = s2; - m[2][0] = c1 * s3 + c3 * s1 * s2; - m[2][1] = s1 * s3 - c1 * c3 * s2; - m[2][2] = c2 * c3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - s1 * s2 * s3 + m[0][1] = c3 * s1 + c1 * s2 * s3 + m[0][2] =-c2 * s3 + m[1][0] =-c2 * s1 + m[1][1] = c1 * c2 + m[1][2] = s2 + m[2][0] = c1 * s3 + c3 * s1 * s2 + m[2][1] = s1 * s3 - c1 * c3 * s2 + m[2][2] = c2 * c3 + return } matrix3_from_yaw_pitch_roll_f16 :: proc(yaw, pitch, roll: f16) -> (m: Matrix3f16) { - ch := math.cos(yaw); - sh := math.sin(yaw); - cp := math.cos(pitch); - sp := math.sin(pitch); - cb := math.cos(roll); - sb := math.sin(roll); - - m[0][0] = ch * cb + sh * sp * sb; - m[0][1] = sb * cp; - m[0][2] = -sh * cb + ch * sp * sb; - m[1][0] = -ch * sb + sh * sp * cb; - m[1][1] = cb * cp; - m[1][2] = sb * sh + ch * sp * cb; - m[2][0] = sh * cp; - m[2][1] = -sp; - m[2][2] = ch * cp; - return m; + ch := math.cos(yaw) + sh := math.sin(yaw) + cp := math.cos(pitch) + sp := math.sin(pitch) + cb := math.cos(roll) + sb := math.sin(roll) + + m[0][0] = ch * cb + sh * sp * sb + m[0][1] = sb * cp + m[0][2] = -sh * cb + ch * sp * sb + m[1][0] = -ch * sb + sh * sp * cb + m[1][1] = cb * cp + m[1][2] = sb * sh + ch * sp * cb + m[2][0] = sh * cp + m[2][1] = -sp + m[2][2] = ch * cp + return m } euler_angles_xyz_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[2][1], m[2][2]); - C2 := math.sqrt(m[0][0]*m[0][0] + m[1][0]*m[1][0]); - T2 := math.atan2(-m[2][0], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[0][2] - C1*m[0][1], C1*m[1][1] - S1*m[1][2]); - t1 = -T1; - t2 = -T2; - t3 = -T3; - return; + T1 := math.atan2(m[2][1], m[2][2]) + C2 := math.sqrt(m[0][0]*m[0][0] + m[1][0]*m[1][0]) + T2 := math.atan2(-m[2][0], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[0][2] - C1*m[0][1], C1*m[1][1] - S1*m[1][2]) + t1 = -T1 + t2 = -T2 + t3 = -T3 + return } euler_angles_yxz_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[2][0], m[2][2]); - C2 := math.sqrt(m[0][1]*m[0][1] + m[1][1]*m[1][1]); - T2 := math.atan2(-m[2][1], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[1][2] - C1*m[1][0], C1*m[0][0] - S1*m[0][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][0], m[2][2]) + C2 := math.sqrt(m[0][1]*m[0][1] + m[1][1]*m[1][1]) + T2 := math.atan2(-m[2][1], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[1][2] - C1*m[1][0], C1*m[0][0] - S1*m[0][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xzx_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[0][2], m[0][1]); - S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]); - T2 := math.atan2(S2, m[0][0]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[1][2] - S1*m[1][1], C1*m[2][2] - S1*m[2][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][2], m[0][1]) + S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]) + T2 := math.atan2(S2, m[0][0]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[1][2] - S1*m[1][1], C1*m[2][2] - S1*m[2][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xyx_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[0][1], -m[0][2]); - S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]); - T2 := math.atan2(S2, m[0][0]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-C1*m[2][1] - S1*m[2][2], C1*m[1][1] + S1*m[1][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][1], -m[0][2]) + S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]) + T2 := math.atan2(S2, m[0][0]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-C1*m[2][1] - S1*m[2][2], C1*m[1][1] + S1*m[1][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yxy_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[1][0], m[1][2]); - S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]); - T2 := math.atan2(S2, m[1][1]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[2][0] - S1*m[2][2], C1*m[0][0] - S1*m[0][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][0], m[1][2]) + S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]) + T2 := math.atan2(S2, m[1][1]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[2][0] - S1*m[2][2], C1*m[0][0] - S1*m[0][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yzy_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[1][2], -m[1][0]); - S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]); - T2 := math.atan2(S2, m[1][1]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-S1*m[0][0] - C1*m[0][2], S1*m[2][0] + C1*m[2][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][2], -m[1][0]) + S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]) + T2 := math.atan2(S2, m[1][1]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-S1*m[0][0] - C1*m[0][2], S1*m[2][0] + C1*m[2][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zyz_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[2][1], m[2][0]); - S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]); - T2 := math.atan2(S2, m[2][2]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[0][1] - S1*m[0][0], C1*m[1][1] - S1*m[1][0]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][1], m[2][0]) + S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]) + T2 := math.atan2(S2, m[2][2]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[0][1] - S1*m[0][0], C1*m[1][1] - S1*m[1][0]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zxz_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[2][0], -m[2][1]); - S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]); - T2 := math.atan2(S2, m[2][2]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-C1*m[1][0] - S1*m[1][1], C1*m[0][0] + S1*m[0][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][0], -m[2][1]) + S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]) + T2 := math.atan2(S2, m[2][2]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-C1*m[1][0] - S1*m[1][1], C1*m[0][0] + S1*m[0][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xzy_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[1][2], m[1][1]); - C2 := math.sqrt(m[0][0]*m[0][0] + m[2][0]*m[2][0]); - T2 := math.atan2(-m[1][0], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[0][1] - C1*m[0][2], C1*m[2][2] - S1*m[2][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][2], m[1][1]) + C2 := math.sqrt(m[0][0]*m[0][0] + m[2][0]*m[2][0]) + T2 := math.atan2(-m[1][0], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[0][1] - C1*m[0][2], C1*m[2][2] - S1*m[2][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yzx_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(-m[0][2], m[0][0]); - C2 := math.sqrt(m[1][1]*m[1][1] + m[2][1]*m[2][1]); - T2 := math.atan2(m[0][1], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[1][0] + C1*m[1][2], S1*m[2][0] + C1*m[2][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(-m[0][2], m[0][0]) + C2 := math.sqrt(m[1][1]*m[1][1] + m[2][1]*m[2][1]) + T2 := math.atan2(m[0][1], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[1][0] + C1*m[1][2], S1*m[2][0] + C1*m[2][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zyx_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[0][1], m[0][0]); - C2 := math.sqrt(m[1][2]*m[1][2] + m[2][2]*m[2][2]); - T2 := math.atan2(-m[0][2], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[2][0] - C1*m[2][1], C1*m[1][1] - S1*m[1][0]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][1], m[0][0]) + C2 := math.sqrt(m[1][2]*m[1][2] + m[2][2]*m[2][2]) + T2 := math.atan2(-m[0][2], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[2][0] - C1*m[2][1], C1*m[1][1] - S1*m[1][0]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zxy_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(-m[1][0], m[1][1]); - C2 := math.sqrt(m[0][2]*m[0][2] + m[2][2]*m[2][2]); - T2 := math.atan2(m[1][2], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[2][0] + S1*m[2][1], C1*m[0][0] + S1*m[0][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(-m[1][0], m[1][1]) + C2 := math.sqrt(m[0][2]*m[0][2] + m[2][2]*m[2][2]) + T2 := math.atan2(m[1][2], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[2][0] + S1*m[2][1], C1*m[0][0] + S1*m[0][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } @@ -736,621 +736,621 @@ euler_angles_zxy_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { matrix4_from_euler_angle_x_f16 :: proc(angle_x: f16) -> (m: Matrix4f16) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - m[0][0] = 1; - m[1][1] = +cos_x; - m[2][1] = +sin_x; - m[1][2] = -sin_x; - m[2][2] = +cos_x; - m[3][3] = 1; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + m[0][0] = 1 + m[1][1] = +cos_x + m[2][1] = +sin_x + m[1][2] = -sin_x + m[2][2] = +cos_x + m[3][3] = 1 + return } matrix4_from_euler_angle_y_f16 :: proc(angle_y: f16) -> (m: Matrix4f16) { - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = +cos_y; - m[2][0] = -sin_y; - m[1][1] = 1; - m[0][2] = +sin_y; - m[2][2] = +cos_y; - m[3][3] = 1; - return; + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = +cos_y + m[2][0] = -sin_y + m[1][1] = 1 + m[0][2] = +sin_y + m[2][2] = +cos_y + m[3][3] = 1 + return } matrix4_from_euler_angle_z_f16 :: proc(angle_z: f16) -> (m: Matrix4f16) { - cos_z, sin_z := math.cos(angle_z), math.sin(angle_z); - m[0][0] = +cos_z; - m[1][0] = +sin_z; - m[1][1] = +cos_z; - m[0][1] = -sin_z; - m[2][2] = 1; - m[3][3] = 1; - return; + cos_z, sin_z := math.cos(angle_z), math.sin(angle_z) + m[0][0] = +cos_z + m[1][0] = +sin_z + m[1][1] = +cos_z + m[0][1] = -sin_z + m[2][2] = 1 + m[3][3] = 1 + return } matrix4_from_derived_euler_angle_x_f16 :: proc(angle_x: f16, angular_velocity_x: f16) -> (m: Matrix4f16) { - cos_x := math.cos(angle_x) * angular_velocity_x; - sin_x := math.sin(angle_x) * angular_velocity_x; - m[0][0] = 1; - m[1][1] = +cos_x; - m[2][1] = +sin_x; - m[1][2] = -sin_x; - m[2][2] = +cos_x; - m[3][3] = 1; - return; + cos_x := math.cos(angle_x) * angular_velocity_x + sin_x := math.sin(angle_x) * angular_velocity_x + m[0][0] = 1 + m[1][1] = +cos_x + m[2][1] = +sin_x + m[1][2] = -sin_x + m[2][2] = +cos_x + m[3][3] = 1 + return } matrix4_from_derived_euler_angle_y_f16 :: proc(angle_y: f16, angular_velocity_y: f16) -> (m: Matrix4f16) { - cos_y := math.cos(angle_y) * angular_velocity_y; - sin_y := math.sin(angle_y) * angular_velocity_y; - m[0][0] = +cos_y; - m[2][0] = -sin_y; - m[1][1] = 1; - m[0][2] = +sin_y; - m[2][2] = +cos_y; - m[3][3] = 1; - return; + cos_y := math.cos(angle_y) * angular_velocity_y + sin_y := math.sin(angle_y) * angular_velocity_y + m[0][0] = +cos_y + m[2][0] = -sin_y + m[1][1] = 1 + m[0][2] = +sin_y + m[2][2] = +cos_y + m[3][3] = 1 + return } matrix4_from_derived_euler_angle_z_f16 :: proc(angle_z: f16, angular_velocity_z: f16) -> (m: Matrix4f16) { - cos_z := math.cos(angle_z) * angular_velocity_z; - sin_z := math.sin(angle_z) * angular_velocity_z; - m[0][0] = +cos_z; - m[1][0] = +sin_z; - m[1][1] = +cos_z; - m[0][1] = -sin_z; - m[2][2] = 1; - m[3][3] = 1; - return; + cos_z := math.cos(angle_z) * angular_velocity_z + sin_z := math.sin(angle_z) * angular_velocity_z + m[0][0] = +cos_z + m[1][0] = +sin_z + m[1][1] = +cos_z + m[0][1] = -sin_z + m[2][2] = 1 + m[3][3] = 1 + return } matrix4_from_euler_angles_xy_f16 :: proc(angle_x, angle_y: f16) -> (m: Matrix4f16) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = cos_y; - m[1][0] = -sin_x * - sin_y; - m[2][0] = -cos_x * - sin_y; - m[1][1] = cos_x; - m[2][1] = sin_x; - m[0][2] = sin_y; - m[1][2] = -sin_x * cos_y; - m[2][2] = cos_x * cos_y; - m[3][3] = 1; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = cos_y + m[1][0] = -sin_x * - sin_y + m[2][0] = -cos_x * - sin_y + m[1][1] = cos_x + m[2][1] = sin_x + m[0][2] = sin_y + m[1][2] = -sin_x * cos_y + m[2][2] = cos_x * cos_y + m[3][3] = 1 + return } matrix4_from_euler_angles_yx_f16 :: proc(angle_y, angle_x: f16) -> (m: Matrix4f16) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = cos_y; - m[2][0] = -sin_y; - m[0][1] = sin_y*sin_x; - m[1][1] = cos_x; - m[2][1] = cos_y*sin_x; - m[0][2] = sin_y*cos_x; - m[1][2] = -sin_x; - m[2][2] = cos_y*cos_x; - m[3][3] = 1; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = cos_y + m[2][0] = -sin_y + m[0][1] = sin_y*sin_x + m[1][1] = cos_x + m[2][1] = cos_y*sin_x + m[0][2] = sin_y*cos_x + m[1][2] = -sin_x + m[2][2] = cos_y*cos_x + m[3][3] = 1 + return } matrix4_from_euler_angles_xz_f16 :: proc(angle_x, angle_z: f16) -> (m: Matrix4f16) { - return mul(matrix4_from_euler_angle_x(angle_x), matrix4_from_euler_angle_z(angle_z)); + return mul(matrix4_from_euler_angle_x(angle_x), matrix4_from_euler_angle_z(angle_z)) } matrix4_from_euler_angles_zx_f16 :: proc(angle_z, angle_x: f16) -> (m: Matrix4f16) { - return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_x(angle_x)); + return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_x(angle_x)) } matrix4_from_euler_angles_yz_f16 :: proc(angle_y, angle_z: f16) -> (m: Matrix4f16) { - return mul(matrix4_from_euler_angle_y(angle_y), matrix4_from_euler_angle_z(angle_z)); + return mul(matrix4_from_euler_angle_y(angle_y), matrix4_from_euler_angle_z(angle_z)) } matrix4_from_euler_angles_zy_f16 :: proc(angle_z, angle_y: f16) -> (m: Matrix4f16) { - return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_y(angle_y)); + return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_y(angle_y)) } matrix4_from_euler_angles_xyz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { - c1 := math.cos(-t1); - c2 := math.cos(-t2); - c3 := math.cos(-t3); - s1 := math.sin(-t1); - s2 := math.sin(-t2); - s3 := math.sin(-t3); - - m[0][0] = c2 * c3; - m[0][1] =-c1 * s3 + s1 * s2 * c3; - m[0][2] = s1 * s3 + c1 * s2 * c3; - m[0][3] = 0; - m[1][0] = c2 * s3; - m[1][1] = c1 * c3 + s1 * s2 * s3; - m[1][2] =-s1 * c3 + c1 * s2 * s3; - m[1][3] = 0; - m[2][0] =-s2; - m[2][1] = s1 * c2; - m[2][2] = c1 * c2; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(-t1) + c2 := math.cos(-t2) + c3 := math.cos(-t3) + s1 := math.sin(-t1) + s2 := math.sin(-t2) + s3 := math.sin(-t3) + + m[0][0] = c2 * c3 + m[0][1] =-c1 * s3 + s1 * s2 * c3 + m[0][2] = s1 * s3 + c1 * s2 * c3 + m[0][3] = 0 + m[1][0] = c2 * s3 + m[1][1] = c1 * c3 + s1 * s2 * s3 + m[1][2] =-s1 * c3 + c1 * s2 * s3 + m[1][3] = 0 + m[2][0] =-s2 + m[2][1] = s1 * c2 + m[2][2] = c1 * c2 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_yxz_f16 :: proc(yaw, pitch, roll: f16) -> (m: Matrix4f16) { - ch := math.cos(yaw); - sh := math.sin(yaw); - cp := math.cos(pitch); - sp := math.sin(pitch); - cb := math.cos(roll); - sb := math.sin(roll); - - m[0][0] = ch * cb + sh * sp * sb; - m[0][1] = sb * cp; - m[0][2] = -sh * cb + ch * sp * sb; - m[0][3] = 0; - m[1][0] = -ch * sb + sh * sp * cb; - m[1][1] = cb * cp; - m[1][2] = sb * sh + ch * sp * cb; - m[1][3] = 0; - m[2][0] = sh * cp; - m[2][1] = -sp; - m[2][2] = ch * cp; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + ch := math.cos(yaw) + sh := math.sin(yaw) + cp := math.cos(pitch) + sp := math.sin(pitch) + cb := math.cos(roll) + sb := math.sin(roll) + + m[0][0] = ch * cb + sh * sp * sb + m[0][1] = sb * cp + m[0][2] = -sh * cb + ch * sp * sb + m[0][3] = 0 + m[1][0] = -ch * sb + sh * sp * cb + m[1][1] = cb * cp + m[1][2] = sb * sh + ch * sp * cb + m[1][3] = 0 + m[2][0] = sh * cp + m[2][1] = -sp + m[2][2] = ch * cp + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_xzx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2; - m[0][1] = c1 * s2; - m[0][2] = s1 * s2; - m[0][3] = 0; - m[1][0] =-c3 * s2; - m[1][1] = c1 * c2 * c3 - s1 * s3; - m[1][2] = c1 * s3 + c2 * c3 * s1; - m[1][3] = 0; - m[2][0] = s2 * s3; - m[2][1] =-c3 * s1 - c1 * c2 * s3; - m[2][2] = c1 * c3 - c2 * s1 * s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 + m[0][1] = c1 * s2 + m[0][2] = s1 * s2 + m[0][3] = 0 + m[1][0] =-c3 * s2 + m[1][1] = c1 * c2 * c3 - s1 * s3 + m[1][2] = c1 * s3 + c2 * c3 * s1 + m[1][3] = 0 + m[2][0] = s2 * s3 + m[2][1] =-c3 * s1 - c1 * c2 * s3 + m[2][2] = c1 * c3 - c2 * s1 * s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_xyx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2; - m[0][1] = s1 * s2; - m[0][2] =-c1 * s2; - m[0][3] = 0; - m[1][0] = s2 * s3; - m[1][1] = c1 * c3 - c2 * s1 * s3; - m[1][2] = c3 * s1 + c1 * c2 * s3; - m[1][3] = 0; - m[2][0] = c3 * s2; - m[2][1] =-c1 * s3 - c2 * c3 * s1; - m[2][2] = c1 * c2 * c3 - s1 * s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 + m[0][1] = s1 * s2 + m[0][2] =-c1 * s2 + m[0][3] = 0 + m[1][0] = s2 * s3 + m[1][1] = c1 * c3 - c2 * s1 * s3 + m[1][2] = c3 * s1 + c1 * c2 * s3 + m[1][3] = 0 + m[2][0] = c3 * s2 + m[2][1] =-c1 * s3 - c2 * c3 * s1 + m[2][2] = c1 * c2 * c3 - s1 * s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_yxy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - c2 * s1 * s3; - m[0][1] = s2* s3; - m[0][2] =-c3 * s1 - c1 * c2 * s3; - m[0][3] = 0; - m[1][0] = s1 * s2; - m[1][1] = c2; - m[1][2] = c1 * s2; - m[1][3] = 0; - m[2][0] = c1 * s3 + c2 * c3 * s1; - m[2][1] =-c3 * s2; - m[2][2] = c1 * c2 * c3 - s1 * s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - c2 * s1 * s3 + m[0][1] = s2* s3 + m[0][2] =-c3 * s1 - c1 * c2 * s3 + m[0][3] = 0 + m[1][0] = s1 * s2 + m[1][1] = c2 + m[1][2] = c1 * s2 + m[1][3] = 0 + m[2][0] = c1 * s3 + c2 * c3 * s1 + m[2][1] =-c3 * s2 + m[2][2] = c1 * c2 * c3 - s1 * s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_yzy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2 * c3 - s1 * s3; - m[0][1] = c3 * s2; - m[0][2] =-c1 * s3 - c2 * c3 * s1; - m[0][3] = 0; - m[1][0] =-c1 * s2; - m[1][1] = c2; - m[1][2] = s1 * s2; - m[1][3] = 0; - m[2][0] = c3 * s1 + c1 * c2 * s3; - m[2][1] = s2 * s3; - m[2][2] = c1 * c3 - c2 * s1 * s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 * c3 - s1 * s3 + m[0][1] = c3 * s2 + m[0][2] =-c1 * s3 - c2 * c3 * s1 + m[0][3] = 0 + m[1][0] =-c1 * s2 + m[1][1] = c2 + m[1][2] = s1 * s2 + m[1][3] = 0 + m[2][0] = c3 * s1 + c1 * c2 * s3 + m[2][1] = s2 * s3 + m[2][2] = c1 * c3 - c2 * s1 * s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_zyz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2 * c3 - s1 * s3; - m[0][1] = c1 * s3 + c2 * c3 * s1; - m[0][2] =-c3 * s2; - m[0][3] = 0; - m[1][0] =-c3 * s1 - c1 * c2 * s3; - m[1][1] = c1 * c3 - c2 * s1 * s3; - m[1][2] = s2 * s3; - m[1][3] = 0; - m[2][0] = c1 * s2; - m[2][1] = s1 * s2; - m[2][2] = c2; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 * c3 - s1 * s3 + m[0][1] = c1 * s3 + c2 * c3 * s1 + m[0][2] =-c3 * s2 + m[0][3] = 0 + m[1][0] =-c3 * s1 - c1 * c2 * s3 + m[1][1] = c1 * c3 - c2 * s1 * s3 + m[1][2] = s2 * s3 + m[1][3] = 0 + m[2][0] = c1 * s2 + m[2][1] = s1 * s2 + m[2][2] = c2 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_zxz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - c2 * s1 * s3; - m[0][1] = c3 * s1 + c1 * c2 * s3; - m[0][2] = s2 *s3; - m[0][3] = 0; - m[1][0] =-c1 * s3 - c2 * c3 * s1; - m[1][1] = c1 * c2 * c3 - s1 * s3; - m[1][2] = c3 * s2; - m[1][3] = 0; - m[2][0] = s1 * s2; - m[2][1] =-c1 * s2; - m[2][2] = c2; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - c2 * s1 * s3 + m[0][1] = c3 * s1 + c1 * c2 * s3 + m[0][2] = s2 *s3 + m[0][3] = 0 + m[1][0] =-c1 * s3 - c2 * c3 * s1 + m[1][1] = c1 * c2 * c3 - s1 * s3 + m[1][2] = c3 * s2 + m[1][3] = 0 + m[2][0] = s1 * s2 + m[2][1] =-c1 * s2 + m[2][2] = c2 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_xzy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2 * c3; - m[0][1] = s1 * s3 + c1 * c3 * s2; - m[0][2] = c3 * s1 * s2 - c1 * s3; - m[0][3] = 0; - m[1][0] =-s2; - m[1][1] = c1 * c2; - m[1][2] = c2 * s1; - m[1][3] = 0; - m[2][0] = c2 * s3; - m[2][1] = c1 * s2 * s3 - c3 * s1; - m[2][2] = c1 * c3 + s1 * s2 *s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 * c3 + m[0][1] = s1 * s3 + c1 * c3 * s2 + m[0][2] = c3 * s1 * s2 - c1 * s3 + m[0][3] = 0 + m[1][0] =-s2 + m[1][1] = c1 * c2 + m[1][2] = c2 * s1 + m[1][3] = 0 + m[2][0] = c2 * s3 + m[2][1] = c1 * s2 * s3 - c3 * s1 + m[2][2] = c1 * c3 + s1 * s2 *s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_yzx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2; - m[0][1] = s2; - m[0][2] =-c2 * s1; - m[0][3] = 0; - m[1][0] = s1 * s3 - c1 * c3 * s2; - m[1][1] = c2 * c3; - m[1][2] = c1 * s3 + c3 * s1 * s2; - m[1][3] = 0; - m[2][0] = c3 * s1 + c1 * s2 * s3; - m[2][1] =-c2 * s3; - m[2][2] = c1 * c3 - s1 * s2 * s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 + m[0][1] = s2 + m[0][2] =-c2 * s1 + m[0][3] = 0 + m[1][0] = s1 * s3 - c1 * c3 * s2 + m[1][1] = c2 * c3 + m[1][2] = c1 * s3 + c3 * s1 * s2 + m[1][3] = 0 + m[2][0] = c3 * s1 + c1 * s2 * s3 + m[2][1] =-c2 * s3 + m[2][2] = c1 * c3 - s1 * s2 * s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_zyx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2; - m[0][1] = c2 * s1; - m[0][2] =-s2; - m[0][3] = 0; - m[1][0] = c1 * s2 * s3 - c3 * s1; - m[1][1] = c1 * c3 + s1 * s2 * s3; - m[1][2] = c2 * s3; - m[1][3] = 0; - m[2][0] = s1 * s3 + c1 * c3 * s2; - m[2][1] = c3 * s1 * s2 - c1 * s3; - m[2][2] = c2 * c3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 + m[0][1] = c2 * s1 + m[0][2] =-s2 + m[0][3] = 0 + m[1][0] = c1 * s2 * s3 - c3 * s1 + m[1][1] = c1 * c3 + s1 * s2 * s3 + m[1][2] = c2 * s3 + m[1][3] = 0 + m[2][0] = s1 * s3 + c1 * c3 * s2 + m[2][1] = c3 * s1 * s2 - c1 * s3 + m[2][2] = c2 * c3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_zxy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - s1 * s2 * s3; - m[0][1] = c3 * s1 + c1 * s2 * s3; - m[0][2] =-c2 * s3; - m[0][3] = 0; - m[1][0] =-c2 * s1; - m[1][1] = c1 * c2; - m[1][2] = s2; - m[1][3] = 0; - m[2][0] = c1 * s3 + c3 * s1 * s2; - m[2][1] = s1 * s3 - c1 * c3 * s2; - m[2][2] = c2 * c3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - s1 * s2 * s3 + m[0][1] = c3 * s1 + c1 * s2 * s3 + m[0][2] =-c2 * s3 + m[0][3] = 0 + m[1][0] =-c2 * s1 + m[1][1] = c1 * c2 + m[1][2] = s2 + m[1][3] = 0 + m[2][0] = c1 * s3 + c3 * s1 * s2 + m[2][1] = s1 * s3 - c1 * c3 * s2 + m[2][2] = c2 * c3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_yaw_pitch_roll_f16 :: proc(yaw, pitch, roll: f16) -> (m: Matrix4f16) { - ch := math.cos(yaw); - sh := math.sin(yaw); - cp := math.cos(pitch); - sp := math.sin(pitch); - cb := math.cos(roll); - sb := math.sin(roll); - - m[0][0] = ch * cb + sh * sp * sb; - m[0][1] = sb * cp; - m[0][2] = -sh * cb + ch * sp * sb; - m[0][3] = 0; - m[1][0] = -ch * sb + sh * sp * cb; - m[1][1] = cb * cp; - m[1][2] = sb * sh + ch * sp * cb; - m[1][3] = 0; - m[2][0] = sh * cp; - m[2][1] = -sp; - m[2][2] = ch * cp; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return m; + ch := math.cos(yaw) + sh := math.sin(yaw) + cp := math.cos(pitch) + sp := math.sin(pitch) + cb := math.cos(roll) + sb := math.sin(roll) + + m[0][0] = ch * cb + sh * sp * sb + m[0][1] = sb * cp + m[0][2] = -sh * cb + ch * sp * sb + m[0][3] = 0 + m[1][0] = -ch * sb + sh * sp * cb + m[1][1] = cb * cp + m[1][2] = sb * sh + ch * sp * cb + m[1][3] = 0 + m[2][0] = sh * cp + m[2][1] = -sp + m[2][2] = ch * cp + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return m } euler_angles_xyz_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[2][1], m[2][2]); - C2 := math.sqrt(m[0][0]*m[0][0] + m[1][0]*m[1][0]); - T2 := math.atan2(-m[2][0], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[0][2] - C1*m[0][1], C1*m[1][1] - S1*m[1][2]); - t1 = -T1; - t2 = -T2; - t3 = -T3; - return; + T1 := math.atan2(m[2][1], m[2][2]) + C2 := math.sqrt(m[0][0]*m[0][0] + m[1][0]*m[1][0]) + T2 := math.atan2(-m[2][0], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[0][2] - C1*m[0][1], C1*m[1][1] - S1*m[1][2]) + t1 = -T1 + t2 = -T2 + t3 = -T3 + return } euler_angles_yxz_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[2][0], m[2][2]); - C2 := math.sqrt(m[0][1]*m[0][1] + m[1][1]*m[1][1]); - T2 := math.atan2(-m[2][1], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[1][2] - C1*m[1][0], C1*m[0][0] - S1*m[0][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][0], m[2][2]) + C2 := math.sqrt(m[0][1]*m[0][1] + m[1][1]*m[1][1]) + T2 := math.atan2(-m[2][1], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[1][2] - C1*m[1][0], C1*m[0][0] - S1*m[0][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xzx_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[0][2], m[0][1]); - S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]); - T2 := math.atan2(S2, m[0][0]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[1][2] - S1*m[1][1], C1*m[2][2] - S1*m[2][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][2], m[0][1]) + S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]) + T2 := math.atan2(S2, m[0][0]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[1][2] - S1*m[1][1], C1*m[2][2] - S1*m[2][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xyx_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[0][1], -m[0][2]); - S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]); - T2 := math.atan2(S2, m[0][0]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-C1*m[2][1] - S1*m[2][2], C1*m[1][1] + S1*m[1][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][1], -m[0][2]) + S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]) + T2 := math.atan2(S2, m[0][0]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-C1*m[2][1] - S1*m[2][2], C1*m[1][1] + S1*m[1][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yxy_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[1][0], m[1][2]); - S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]); - T2 := math.atan2(S2, m[1][1]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[2][0] - S1*m[2][2], C1*m[0][0] - S1*m[0][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][0], m[1][2]) + S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]) + T2 := math.atan2(S2, m[1][1]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[2][0] - S1*m[2][2], C1*m[0][0] - S1*m[0][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yzy_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[1][2], -m[1][0]); - S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]); - T2 := math.atan2(S2, m[1][1]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-S1*m[0][0] - C1*m[0][2], S1*m[2][0] + C1*m[2][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][2], -m[1][0]) + S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]) + T2 := math.atan2(S2, m[1][1]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-S1*m[0][0] - C1*m[0][2], S1*m[2][0] + C1*m[2][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zyz_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[2][1], m[2][0]); - S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]); - T2 := math.atan2(S2, m[2][2]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[0][1] - S1*m[0][0], C1*m[1][1] - S1*m[1][0]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][1], m[2][0]) + S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]) + T2 := math.atan2(S2, m[2][2]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[0][1] - S1*m[0][0], C1*m[1][1] - S1*m[1][0]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zxz_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[2][0], -m[2][1]); - S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]); - T2 := math.atan2(S2, m[2][2]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-C1*m[1][0] - S1*m[1][1], C1*m[0][0] + S1*m[0][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][0], -m[2][1]) + S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]) + T2 := math.atan2(S2, m[2][2]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-C1*m[1][0] - S1*m[1][1], C1*m[0][0] + S1*m[0][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xzy_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[1][2], m[1][1]); - C2 := math.sqrt(m[0][0]*m[0][0] + m[2][0]*m[2][0]); - T2 := math.atan2(-m[1][0], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[0][1] - C1*m[0][2], C1*m[2][2] - S1*m[2][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][2], m[1][1]) + C2 := math.sqrt(m[0][0]*m[0][0] + m[2][0]*m[2][0]) + T2 := math.atan2(-m[1][0], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[0][1] - C1*m[0][2], C1*m[2][2] - S1*m[2][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yzx_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(-m[0][2], m[0][0]); - C2 := math.sqrt(m[1][1]*m[1][1] + m[2][1]*m[2][1]); - T2 := math.atan2(m[0][1], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[1][0] + C1*m[1][2], S1*m[2][0] + C1*m[2][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(-m[0][2], m[0][0]) + C2 := math.sqrt(m[1][1]*m[1][1] + m[2][1]*m[2][1]) + T2 := math.atan2(m[0][1], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[1][0] + C1*m[1][2], S1*m[2][0] + C1*m[2][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zyx_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[0][1], m[0][0]); - C2 := math.sqrt(m[1][2]*m[1][2] + m[2][2]*m[2][2]); - T2 := math.atan2(-m[0][2], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[2][0] - C1*m[2][1], C1*m[1][1] - S1*m[1][0]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][1], m[0][0]) + C2 := math.sqrt(m[1][2]*m[1][2] + m[2][2]*m[2][2]) + T2 := math.atan2(-m[0][2], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[2][0] - C1*m[2][1], C1*m[1][1] - S1*m[1][0]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zxy_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(-m[1][0], m[1][1]); - C2 := math.sqrt(m[0][2]*m[0][2] + m[2][2]*m[2][2]); - T2 := math.atan2(m[1][2], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[2][0] + S1*m[2][1], C1*m[0][0] + S1*m[0][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(-m[1][0], m[1][1]) + C2 := math.sqrt(m[0][2]*m[0][2] + m[2][2]*m[2][2]) + T2 := math.atan2(m[1][2], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[2][0] + S1*m[2][1], C1*m[0][0] + S1*m[0][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } diff --git a/core/math/linalg/specific_euler_angles_f32.odin b/core/math/linalg/specific_euler_angles_f32.odin index e7069bd81..6ae1b0fa0 100644 --- a/core/math/linalg/specific_euler_angles_f32.odin +++ b/core/math/linalg/specific_euler_angles_f32.odin @@ -4,206 +4,206 @@ import "core:math" euler_angles_from_matrix3_f32 :: proc(m: Matrix3f32, order: Euler_Angle_Order) -> (t1, t2, t3: f32) { switch order { - case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix3(m); - case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix3(m); - case .YXZ: t1, t2, t3 = euler_angles_yxz_from_matrix3(m); - case .YZX: t1, t2, t3 = euler_angles_yzx_from_matrix3(m); - case .ZXY: t1, t2, t3 = euler_angles_zxy_from_matrix3(m); - case .ZYX: t1, t2, t3 = euler_angles_zyx_from_matrix3(m); - case .XYX: t1, t2, t3 = euler_angles_xyx_from_matrix3(m); - case .XZX: t1, t2, t3 = euler_angles_xzx_from_matrix3(m); - case .YXY: t1, t2, t3 = euler_angles_yxy_from_matrix3(m); - case .YZY: t1, t2, t3 = euler_angles_yzy_from_matrix3(m); - case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_matrix3(m); - case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_matrix3(m); + case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix3(m) + case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix3(m) + case .YXZ: t1, t2, t3 = euler_angles_yxz_from_matrix3(m) + case .YZX: t1, t2, t3 = euler_angles_yzx_from_matrix3(m) + case .ZXY: t1, t2, t3 = euler_angles_zxy_from_matrix3(m) + case .ZYX: t1, t2, t3 = euler_angles_zyx_from_matrix3(m) + case .XYX: t1, t2, t3 = euler_angles_xyx_from_matrix3(m) + case .XZX: t1, t2, t3 = euler_angles_xzx_from_matrix3(m) + case .YXY: t1, t2, t3 = euler_angles_yxy_from_matrix3(m) + case .YZY: t1, t2, t3 = euler_angles_yzy_from_matrix3(m) + case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_matrix3(m) + case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_matrix3(m) } - return; + return } euler_angles_from_matrix4_f32 :: proc(m: Matrix4f32, order: Euler_Angle_Order) -> (t1, t2, t3: f32) { switch order { - case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix4(m); - case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix4(m); - case .YXZ: t1, t2, t3 = euler_angles_yxz_from_matrix4(m); - case .YZX: t1, t2, t3 = euler_angles_yzx_from_matrix4(m); - case .ZXY: t1, t2, t3 = euler_angles_zxy_from_matrix4(m); - case .ZYX: t1, t2, t3 = euler_angles_zyx_from_matrix4(m); - case .XYX: t1, t2, t3 = euler_angles_xyx_from_matrix4(m); - case .XZX: t1, t2, t3 = euler_angles_xzx_from_matrix4(m); - case .YXY: t1, t2, t3 = euler_angles_yxy_from_matrix4(m); - case .YZY: t1, t2, t3 = euler_angles_yzy_from_matrix4(m); - case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_matrix4(m); - case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_matrix4(m); + case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix4(m) + case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix4(m) + case .YXZ: t1, t2, t3 = euler_angles_yxz_from_matrix4(m) + case .YZX: t1, t2, t3 = euler_angles_yzx_from_matrix4(m) + case .ZXY: t1, t2, t3 = euler_angles_zxy_from_matrix4(m) + case .ZYX: t1, t2, t3 = euler_angles_zyx_from_matrix4(m) + case .XYX: t1, t2, t3 = euler_angles_xyx_from_matrix4(m) + case .XZX: t1, t2, t3 = euler_angles_xzx_from_matrix4(m) + case .YXY: t1, t2, t3 = euler_angles_yxy_from_matrix4(m) + case .YZY: t1, t2, t3 = euler_angles_yzy_from_matrix4(m) + case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_matrix4(m) + case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_matrix4(m) } - return; + return } euler_angles_from_quaternion_f32 :: proc(m: Quaternionf32, order: Euler_Angle_Order) -> (t1, t2, t3: f32) { switch order { - case .XYZ: t1, t2, t3 = euler_angles_xyz_from_quaternion(m); - case .XZY: t1, t2, t3 = euler_angles_xzy_from_quaternion(m); - case .YXZ: t1, t2, t3 = euler_angles_yxz_from_quaternion(m); - case .YZX: t1, t2, t3 = euler_angles_yzx_from_quaternion(m); - case .ZXY: t1, t2, t3 = euler_angles_zxy_from_quaternion(m); - case .ZYX: t1, t2, t3 = euler_angles_zyx_from_quaternion(m); - case .XYX: t1, t2, t3 = euler_angles_xyx_from_quaternion(m); - case .XZX: t1, t2, t3 = euler_angles_xzx_from_quaternion(m); - case .YXY: t1, t2, t3 = euler_angles_yxy_from_quaternion(m); - case .YZY: t1, t2, t3 = euler_angles_yzy_from_quaternion(m); - case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_quaternion(m); - case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_quaternion(m); + case .XYZ: t1, t2, t3 = euler_angles_xyz_from_quaternion(m) + case .XZY: t1, t2, t3 = euler_angles_xzy_from_quaternion(m) + case .YXZ: t1, t2, t3 = euler_angles_yxz_from_quaternion(m) + case .YZX: t1, t2, t3 = euler_angles_yzx_from_quaternion(m) + case .ZXY: t1, t2, t3 = euler_angles_zxy_from_quaternion(m) + case .ZYX: t1, t2, t3 = euler_angles_zyx_from_quaternion(m) + case .XYX: t1, t2, t3 = euler_angles_xyx_from_quaternion(m) + case .XZX: t1, t2, t3 = euler_angles_xzx_from_quaternion(m) + case .YXY: t1, t2, t3 = euler_angles_yxy_from_quaternion(m) + case .YZY: t1, t2, t3 = euler_angles_yzy_from_quaternion(m) + case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_quaternion(m) + case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_quaternion(m) } - return; + return } matrix3_from_euler_angles_f32 :: proc(t1, t2, t3: f32, order: Euler_Angle_Order) -> (m: Matrix3f32) { switch order { - case .XYZ: return matrix3_from_euler_angles_xyz(t1, t2, t3); // m1, m2, m3 = X(t1), Y(t2), Z(t3); - case .XZY: return matrix3_from_euler_angles_xzy(t1, t2, t3); // m1, m2, m3 = X(t1), Z(t2), Y(t3); - case .YXZ: return matrix3_from_euler_angles_yxz(t1, t2, t3); // m1, m2, m3 = Y(t1), X(t2), Z(t3); - case .YZX: return matrix3_from_euler_angles_yzx(t1, t2, t3); // m1, m2, m3 = Y(t1), Z(t2), X(t3); - case .ZXY: return matrix3_from_euler_angles_zxy(t1, t2, t3); // m1, m2, m3 = Z(t1), X(t2), Y(t3); - case .ZYX: return matrix3_from_euler_angles_zyx(t1, t2, t3); // m1, m2, m3 = Z(t1), Y(t2), X(t3); - case .XYX: return matrix3_from_euler_angles_xyx(t1, t2, t3); // m1, m2, m3 = X(t1), Y(t2), X(t3); - case .XZX: return matrix3_from_euler_angles_xzx(t1, t2, t3); // m1, m2, m3 = X(t1), Z(t2), X(t3); - case .YXY: return matrix3_from_euler_angles_yxy(t1, t2, t3); // m1, m2, m3 = Y(t1), X(t2), Y(t3); - case .YZY: return matrix3_from_euler_angles_yzy(t1, t2, t3); // m1, m2, m3 = Y(t1), Z(t2), Y(t3); - case .ZXZ: return matrix3_from_euler_angles_zxz(t1, t2, t3); // m1, m2, m3 = Z(t1), X(t2), Z(t3); - case .ZYZ: return matrix3_from_euler_angles_zyz(t1, t2, t3); // m1, m2, m3 = Z(t1), Y(t2), Z(t3); + case .XYZ: return matrix3_from_euler_angles_xyz(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), Z(t3); + case .XZY: return matrix3_from_euler_angles_xzy(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), Y(t3); + case .YXZ: return matrix3_from_euler_angles_yxz(t1, t2, t3) // m1, m2, m3 = Y(t1), X(t2), Z(t3); + case .YZX: return matrix3_from_euler_angles_yzx(t1, t2, t3) // m1, m2, m3 = Y(t1), Z(t2), X(t3); + case .ZXY: return matrix3_from_euler_angles_zxy(t1, t2, t3) // m1, m2, m3 = Z(t1), X(t2), Y(t3); + case .ZYX: return matrix3_from_euler_angles_zyx(t1, t2, t3) // m1, m2, m3 = Z(t1), Y(t2), X(t3); + case .XYX: return matrix3_from_euler_angles_xyx(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), X(t3); + case .XZX: return matrix3_from_euler_angles_xzx(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), X(t3); + case .YXY: return matrix3_from_euler_angles_yxy(t1, t2, t3) // m1, m2, m3 = Y(t1), X(t2), Y(t3); + case .YZY: return matrix3_from_euler_angles_yzy(t1, t2, t3) // m1, m2, m3 = Y(t1), Z(t2), Y(t3); + case .ZXZ: return matrix3_from_euler_angles_zxz(t1, t2, t3) // m1, m2, m3 = Z(t1), X(t2), Z(t3); + case .ZYZ: return matrix3_from_euler_angles_zyz(t1, t2, t3) // m1, m2, m3 = Z(t1), Y(t2), Z(t3); } - return; + return } matrix4_from_euler_angles_f32 :: proc(t1, t2, t3: f32, order: Euler_Angle_Order) -> (m: Matrix4f32) { switch order { - case .XYZ: return matrix4_from_euler_angles_xyz(t1, t2, t3); // m1, m2, m3 = X(t1), Y(t2), Z(t3); - case .XZY: return matrix4_from_euler_angles_xzy(t1, t2, t3); // m1, m2, m3 = X(t1), Z(t2), Y(t3); - case .YXZ: return matrix4_from_euler_angles_yxz(t1, t2, t3); // m1, m2, m3 = Y(t1), X(t2), Z(t3); - case .YZX: return matrix4_from_euler_angles_yzx(t1, t2, t3); // m1, m2, m3 = Y(t1), Z(t2), X(t3); - case .ZXY: return matrix4_from_euler_angles_zxy(t1, t2, t3); // m1, m2, m3 = Z(t1), X(t2), Y(t3); - case .ZYX: return matrix4_from_euler_angles_zyx(t1, t2, t3); // m1, m2, m3 = Z(t1), Y(t2), X(t3); - case .XYX: return matrix4_from_euler_angles_xyx(t1, t2, t3); // m1, m2, m3 = X(t1), Y(t2), X(t3); - case .XZX: return matrix4_from_euler_angles_xzx(t1, t2, t3); // m1, m2, m3 = X(t1), Z(t2), X(t3); - case .YXY: return matrix4_from_euler_angles_yxy(t1, t2, t3); // m1, m2, m3 = Y(t1), X(t2), Y(t3); - case .YZY: return matrix4_from_euler_angles_yzy(t1, t2, t3); // m1, m2, m3 = Y(t1), Z(t2), Y(t3); - case .ZXZ: return matrix4_from_euler_angles_zxz(t1, t2, t3); // m1, m2, m3 = Z(t1), X(t2), Z(t3); - case .ZYZ: return matrix4_from_euler_angles_zyz(t1, t2, t3); // m1, m2, m3 = Z(t1), Y(t2), Z(t3); + case .XYZ: return matrix4_from_euler_angles_xyz(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), Z(t3); + case .XZY: return matrix4_from_euler_angles_xzy(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), Y(t3); + case .YXZ: return matrix4_from_euler_angles_yxz(t1, t2, t3) // m1, m2, m3 = Y(t1), X(t2), Z(t3); + case .YZX: return matrix4_from_euler_angles_yzx(t1, t2, t3) // m1, m2, m3 = Y(t1), Z(t2), X(t3); + case .ZXY: return matrix4_from_euler_angles_zxy(t1, t2, t3) // m1, m2, m3 = Z(t1), X(t2), Y(t3); + case .ZYX: return matrix4_from_euler_angles_zyx(t1, t2, t3) // m1, m2, m3 = Z(t1), Y(t2), X(t3); + case .XYX: return matrix4_from_euler_angles_xyx(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), X(t3); + case .XZX: return matrix4_from_euler_angles_xzx(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), X(t3); + case .YXY: return matrix4_from_euler_angles_yxy(t1, t2, t3) // m1, m2, m3 = Y(t1), X(t2), Y(t3); + case .YZY: return matrix4_from_euler_angles_yzy(t1, t2, t3) // m1, m2, m3 = Y(t1), Z(t2), Y(t3); + case .ZXZ: return matrix4_from_euler_angles_zxz(t1, t2, t3) // m1, m2, m3 = Z(t1), X(t2), Z(t3); + case .ZYZ: return matrix4_from_euler_angles_zyz(t1, t2, t3) // m1, m2, m3 = Z(t1), Y(t2), Z(t3); } - return; + return } quaternion_from_euler_angles_f32 :: proc(t1, t2, t3: f32, order: Euler_Angle_Order) -> Quaternionf32 { - X :: quaternion_from_euler_angle_x; - Y :: quaternion_from_euler_angle_y; - Z :: quaternion_from_euler_angle_z; + X :: quaternion_from_euler_angle_x + Y :: quaternion_from_euler_angle_y + Z :: quaternion_from_euler_angle_z - q1, q2, q3: Quaternionf32; + q1, q2, q3: Quaternionf32 switch order { - case .XYZ: q1, q2, q3 = X(t1), Y(t2), Z(t3); - case .XZY: q1, q2, q3 = X(t1), Z(t2), Y(t3); - case .YXZ: q1, q2, q3 = Y(t1), X(t2), Z(t3); - case .YZX: q1, q2, q3 = Y(t1), Z(t2), X(t3); - case .ZXY: q1, q2, q3 = Z(t1), X(t2), Y(t3); - case .ZYX: q1, q2, q3 = Z(t1), Y(t2), X(t3); - case .XYX: q1, q2, q3 = X(t1), Y(t2), X(t3); - case .XZX: q1, q2, q3 = X(t1), Z(t2), X(t3); - case .YXY: q1, q2, q3 = Y(t1), X(t2), Y(t3); - case .YZY: q1, q2, q3 = Y(t1), Z(t2), Y(t3); - case .ZXZ: q1, q2, q3 = Z(t1), X(t2), Z(t3); - case .ZYZ: q1, q2, q3 = Z(t1), Y(t2), Z(t3); + case .XYZ: q1, q2, q3 = X(t1), Y(t2), Z(t3) + case .XZY: q1, q2, q3 = X(t1), Z(t2), Y(t3) + case .YXZ: q1, q2, q3 = Y(t1), X(t2), Z(t3) + case .YZX: q1, q2, q3 = Y(t1), Z(t2), X(t3) + case .ZXY: q1, q2, q3 = Z(t1), X(t2), Y(t3) + case .ZYX: q1, q2, q3 = Z(t1), Y(t2), X(t3) + case .XYX: q1, q2, q3 = X(t1), Y(t2), X(t3) + case .XZX: q1, q2, q3 = X(t1), Z(t2), X(t3) + case .YXY: q1, q2, q3 = Y(t1), X(t2), Y(t3) + case .YZY: q1, q2, q3 = Y(t1), Z(t2), Y(t3) + case .ZXZ: q1, q2, q3 = Z(t1), X(t2), Z(t3) + case .ZYZ: q1, q2, q3 = Z(t1), Y(t2), Z(t3) } - return q1 * (q2 * q3); + return q1 * (q2 * q3) } // Quaternionf32s quaternion_from_euler_angle_x_f32 :: proc(angle_x: f32) -> (q: Quaternionf32) { - return quaternion_angle_axis_f32(angle_x, {1, 0, 0}); + return quaternion_angle_axis_f32(angle_x, {1, 0, 0}) } quaternion_from_euler_angle_y_f32 :: proc(angle_y: f32) -> (q: Quaternionf32) { - return quaternion_angle_axis_f32(angle_y, {0, 1, 0}); + return quaternion_angle_axis_f32(angle_y, {0, 1, 0}) } quaternion_from_euler_angle_z_f32 :: proc(angle_z: f32) -> (q: Quaternionf32) { - return quaternion_angle_axis_f32(angle_z, {0, 0, 1}); + return quaternion_angle_axis_f32(angle_z, {0, 0, 1}) } quaternion_from_pitch_yaw_roll_f32 :: proc(pitch, yaw, roll: f32) -> Quaternionf32 { - a, b, c := pitch, yaw, roll; + a, b, c := pitch, yaw, roll - ca, sa := math.cos(a*0.5), math.sin(a*0.5); - cb, sb := math.cos(b*0.5), math.sin(b*0.5); - cc, sc := math.cos(c*0.5), math.sin(c*0.5); + ca, sa := math.cos(a*0.5), math.sin(a*0.5) + cb, sb := math.cos(b*0.5), math.sin(b*0.5) + cc, sc := math.cos(c*0.5), math.sin(c*0.5) - q: Quaternionf32; - q.x = sa*cb*cc - ca*sb*sc; - q.y = ca*sb*cc + sa*cb*sc; - q.z = ca*cb*sc - sa*sb*cc; - q.w = ca*cb*cc + sa*sb*sc; - return q; + q: Quaternionf32 + q.x = sa*cb*cc - ca*sb*sc + q.y = ca*sb*cc + sa*cb*sc + q.z = ca*cb*sc - sa*sb*cc + q.w = ca*cb*cc + sa*sb*sc + return q } roll_from_quaternion_f32 :: proc(q: Quaternionf32) -> f32 { - return math.atan2(2 * q.x*q.y + q.w*q.z, q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z); + return math.atan2(2 * q.x*q.y + q.w*q.z, q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z) } pitch_from_quaternion_f32 :: proc(q: Quaternionf32) -> f32 { - y := 2 * (q.y*q.z + q.w*q.w); - x := q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z; + y := 2 * (q.y*q.z + q.w*q.w) + x := q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z if abs(x) <= F32_EPSILON && abs(y) <= F32_EPSILON { - return 2 * math.atan2(q.x, q.w); + return 2 * math.atan2(q.x, q.w) } - return math.atan2(y, x); + return math.atan2(y, x) } yaw_from_quaternion_f32 :: proc(q: Quaternionf32) -> f32 { - return math.asin(clamp(-2 * (q.x*q.z - q.w*q.y), -1, 1)); + return math.asin(clamp(-2 * (q.x*q.z - q.w*q.y), -1, 1)) } pitch_yaw_roll_from_quaternion_f32 :: proc(q: Quaternionf32) -> (pitch, yaw, roll: f32) { - pitch = pitch_from_quaternion(q); - yaw = yaw_from_quaternion(q); - roll = roll_from_quaternion(q); - return; + pitch = pitch_from_quaternion(q) + yaw = yaw_from_quaternion(q) + roll = roll_from_quaternion(q) + return } euler_angles_xyz_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { - return euler_angles_xyz_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_xyz_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_yxz_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { - return euler_angles_yxz_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_yxz_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_xzx_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { - return euler_angles_xzx_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_xzx_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_xyx_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { - return euler_angles_xyx_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_xyx_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_yxy_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { - return euler_angles_yxy_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_yxy_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_yzy_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { - return euler_angles_yzy_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_yzy_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_zyz_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { - return euler_angles_zyz_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_zyz_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_zxz_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { - return euler_angles_zxz_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_zxz_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_xzy_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { - return euler_angles_xzy_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_xzy_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_yzx_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { - return euler_angles_yzx_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_yzx_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_zyx_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { - return euler_angles_zyx_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_zyx_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_zxy_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { - return euler_angles_zxy_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_zxy_from_matrix4(matrix4_from_quaternion(q)) } @@ -211,524 +211,524 @@ euler_angles_zxy_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f matrix3_from_euler_angle_x_f32 :: proc(angle_x: f32) -> (m: Matrix3f32) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - m[0][0] = 1; - m[1][1] = +cos_x; - m[2][1] = +sin_x; - m[1][2] = -sin_x; - m[2][2] = +cos_x; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + m[0][0] = 1 + m[1][1] = +cos_x + m[2][1] = +sin_x + m[1][2] = -sin_x + m[2][2] = +cos_x + return } matrix3_from_euler_angle_y_f32 :: proc(angle_y: f32) -> (m: Matrix3f32) { - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = +cos_y; - m[2][0] = -sin_y; - m[1][1] = 1; - m[0][2] = +sin_y; - m[2][2] = +cos_y; - return; + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = +cos_y + m[2][0] = -sin_y + m[1][1] = 1 + m[0][2] = +sin_y + m[2][2] = +cos_y + return } matrix3_from_euler_angle_z_f32 :: proc(angle_z: f32) -> (m: Matrix3f32) { - cos_z, sin_z := math.cos(angle_z), math.sin(angle_z); - m[0][0] = +cos_z; - m[1][0] = +sin_z; - m[1][1] = +cos_z; - m[0][1] = -sin_z; - m[2][2] = 1; - return; + cos_z, sin_z := math.cos(angle_z), math.sin(angle_z) + m[0][0] = +cos_z + m[1][0] = +sin_z + m[1][1] = +cos_z + m[0][1] = -sin_z + m[2][2] = 1 + return } matrix3_from_derived_euler_angle_x_f32 :: proc(angle_x: f32, angular_velocity_x: f32) -> (m: Matrix3f32) { - cos_x := math.cos(angle_x) * angular_velocity_x; - sin_x := math.sin(angle_x) * angular_velocity_x; - m[0][0] = 1; - m[1][1] = +cos_x; - m[2][1] = +sin_x; - m[1][2] = -sin_x; - m[2][2] = +cos_x; - return; + cos_x := math.cos(angle_x) * angular_velocity_x + sin_x := math.sin(angle_x) * angular_velocity_x + m[0][0] = 1 + m[1][1] = +cos_x + m[2][1] = +sin_x + m[1][2] = -sin_x + m[2][2] = +cos_x + return } matrix3_from_derived_euler_angle_y_f32 :: proc(angle_y: f32, angular_velocity_y: f32) -> (m: Matrix3f32) { - cos_y := math.cos(angle_y) * angular_velocity_y; - sin_y := math.sin(angle_y) * angular_velocity_y; - m[0][0] = +cos_y; - m[2][0] = -sin_y; - m[1][1] = 1; - m[0][2] = +sin_y; - m[2][2] = +cos_y; - return; + cos_y := math.cos(angle_y) * angular_velocity_y + sin_y := math.sin(angle_y) * angular_velocity_y + m[0][0] = +cos_y + m[2][0] = -sin_y + m[1][1] = 1 + m[0][2] = +sin_y + m[2][2] = +cos_y + return } matrix3_from_derived_euler_angle_z_f32 :: proc(angle_z: f32, angular_velocity_z: f32) -> (m: Matrix3f32) { - cos_z := math.cos(angle_z) * angular_velocity_z; - sin_z := math.sin(angle_z) * angular_velocity_z; - m[0][0] = +cos_z; - m[1][0] = +sin_z; - m[1][1] = +cos_z; - m[0][1] = -sin_z; - m[2][2] = 1; - return; + cos_z := math.cos(angle_z) * angular_velocity_z + sin_z := math.sin(angle_z) * angular_velocity_z + m[0][0] = +cos_z + m[1][0] = +sin_z + m[1][1] = +cos_z + m[0][1] = -sin_z + m[2][2] = 1 + return } matrix3_from_euler_angles_xy_f32 :: proc(angle_x, angle_y: f32) -> (m: Matrix3f32) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = cos_y; - m[1][0] = -sin_x * - sin_y; - m[2][0] = -cos_x * - sin_y; - m[1][1] = cos_x; - m[2][1] = sin_x; - m[0][2] = sin_y; - m[1][2] = -sin_x * cos_y; - m[2][2] = cos_x * cos_y; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = cos_y + m[1][0] = -sin_x * - sin_y + m[2][0] = -cos_x * - sin_y + m[1][1] = cos_x + m[2][1] = sin_x + m[0][2] = sin_y + m[1][2] = -sin_x * cos_y + m[2][2] = cos_x * cos_y + return } matrix3_from_euler_angles_yx_f32 :: proc(angle_y, angle_x: f32) -> (m: Matrix3f32) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = cos_y; - m[2][0] = -sin_y; - m[0][1] = sin_y*sin_x; - m[1][1] = cos_x; - m[2][1] = cos_y*sin_x; - m[0][2] = sin_y*cos_x; - m[1][2] = -sin_x; - m[2][2] = cos_y*cos_x; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = cos_y + m[2][0] = -sin_y + m[0][1] = sin_y*sin_x + m[1][1] = cos_x + m[2][1] = cos_y*sin_x + m[0][2] = sin_y*cos_x + m[1][2] = -sin_x + m[2][2] = cos_y*cos_x + return } matrix3_from_euler_angles_xz_f32 :: proc(angle_x, angle_z: f32) -> (m: Matrix3f32) { - return mul(matrix3_from_euler_angle_x(angle_x), matrix3_from_euler_angle_z(angle_z)); + return mul(matrix3_from_euler_angle_x(angle_x), matrix3_from_euler_angle_z(angle_z)) } matrix3_from_euler_angles_zx_f32 :: proc(angle_z, angle_x: f32) -> (m: Matrix3f32) { - return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_x(angle_x)); + return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_x(angle_x)) } matrix3_from_euler_angles_yz_f32 :: proc(angle_y, angle_z: f32) -> (m: Matrix3f32) { - return mul(matrix3_from_euler_angle_y(angle_y), matrix3_from_euler_angle_z(angle_z)); + return mul(matrix3_from_euler_angle_y(angle_y), matrix3_from_euler_angle_z(angle_z)) } matrix3_from_euler_angles_zy_f32 :: proc(angle_z, angle_y: f32) -> (m: Matrix3f32) { - return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_y(angle_y)); + return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_y(angle_y)) } matrix3_from_euler_angles_xyz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { - c1 := math.cos(-t1); - c2 := math.cos(-t2); - c3 := math.cos(-t3); - s1 := math.sin(-t1); - s2 := math.sin(-t2); - s3 := math.sin(-t3); - - m[0][0] = c2 * c3; - m[0][1] =-c1 * s3 + s1 * s2 * c3; - m[0][2] = s1 * s3 + c1 * s2 * c3; - m[1][0] = c2 * s3; - m[1][1] = c1 * c3 + s1 * s2 * s3; - m[1][2] =-s1 * c3 + c1 * s2 * s3; - m[2][0] =-s2; - m[2][1] = s1 * c2; - m[2][2] = c1 * c2; - return; + c1 := math.cos(-t1) + c2 := math.cos(-t2) + c3 := math.cos(-t3) + s1 := math.sin(-t1) + s2 := math.sin(-t2) + s3 := math.sin(-t3) + + m[0][0] = c2 * c3 + m[0][1] =-c1 * s3 + s1 * s2 * c3 + m[0][2] = s1 * s3 + c1 * s2 * c3 + m[1][0] = c2 * s3 + m[1][1] = c1 * c3 + s1 * s2 * s3 + m[1][2] =-s1 * c3 + c1 * s2 * s3 + m[2][0] =-s2 + m[2][1] = s1 * c2 + m[2][2] = c1 * c2 + return } matrix3_from_euler_angles_yxz_f32 :: proc(yaw, pitch, roll: f32) -> (m: Matrix3f32) { - ch := math.cos(yaw); - sh := math.sin(yaw); - cp := math.cos(pitch); - sp := math.sin(pitch); - cb := math.cos(roll); - sb := math.sin(roll); - - m[0][0] = ch * cb + sh * sp * sb; - m[0][1] = sb * cp; - m[0][2] = -sh * cb + ch * sp * sb; - m[1][0] = -ch * sb + sh * sp * cb; - m[1][1] = cb * cp; - m[1][2] = sb * sh + ch * sp * cb; - m[2][0] = sh * cp; - m[2][1] = -sp; - m[2][2] = ch * cp; - return; + ch := math.cos(yaw) + sh := math.sin(yaw) + cp := math.cos(pitch) + sp := math.sin(pitch) + cb := math.cos(roll) + sb := math.sin(roll) + + m[0][0] = ch * cb + sh * sp * sb + m[0][1] = sb * cp + m[0][2] = -sh * cb + ch * sp * sb + m[1][0] = -ch * sb + sh * sp * cb + m[1][1] = cb * cp + m[1][2] = sb * sh + ch * sp * cb + m[2][0] = sh * cp + m[2][1] = -sp + m[2][2] = ch * cp + return } matrix3_from_euler_angles_xzx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2; - m[0][1] = c1 * s2; - m[0][2] = s1 * s2; - m[1][0] =-c3 * s2; - m[1][1] = c1 * c2 * c3 - s1 * s3; - m[1][2] = c1 * s3 + c2 * c3 * s1; - m[2][0] = s2 * s3; - m[2][1] =-c3 * s1 - c1 * c2 * s3; - m[2][2] = c1 * c3 - c2 * s1 * s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 + m[0][1] = c1 * s2 + m[0][2] = s1 * s2 + m[1][0] =-c3 * s2 + m[1][1] = c1 * c2 * c3 - s1 * s3 + m[1][2] = c1 * s3 + c2 * c3 * s1 + m[2][0] = s2 * s3 + m[2][1] =-c3 * s1 - c1 * c2 * s3 + m[2][2] = c1 * c3 - c2 * s1 * s3 + return } matrix3_from_euler_angles_xyx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2; - m[0][1] = s1 * s2; - m[0][2] =-c1 * s2; - m[1][0] = s2 * s3; - m[1][1] = c1 * c3 - c2 * s1 * s3; - m[1][2] = c3 * s1 + c1 * c2 * s3; - m[2][0] = c3 * s2; - m[2][1] =-c1 * s3 - c2 * c3 * s1; - m[2][2] = c1 * c2 * c3 - s1 * s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 + m[0][1] = s1 * s2 + m[0][2] =-c1 * s2 + m[1][0] = s2 * s3 + m[1][1] = c1 * c3 - c2 * s1 * s3 + m[1][2] = c3 * s1 + c1 * c2 * s3 + m[2][0] = c3 * s2 + m[2][1] =-c1 * s3 - c2 * c3 * s1 + m[2][2] = c1 * c2 * c3 - s1 * s3 + return } matrix3_from_euler_angles_yxy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - c2 * s1 * s3; - m[0][1] = s2* s3; - m[0][2] =-c3 * s1 - c1 * c2 * s3; - m[1][0] = s1 * s2; - m[1][1] = c2; - m[1][2] = c1 * s2; - m[2][0] = c1 * s3 + c2 * c3 * s1; - m[2][1] =-c3 * s2; - m[2][2] = c1 * c2 * c3 - s1 * s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - c2 * s1 * s3 + m[0][1] = s2* s3 + m[0][2] =-c3 * s1 - c1 * c2 * s3 + m[1][0] = s1 * s2 + m[1][1] = c2 + m[1][2] = c1 * s2 + m[2][0] = c1 * s3 + c2 * c3 * s1 + m[2][1] =-c3 * s2 + m[2][2] = c1 * c2 * c3 - s1 * s3 + return } matrix3_from_euler_angles_yzy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2 * c3 - s1 * s3; - m[0][1] = c3 * s2; - m[0][2] =-c1 * s3 - c2 * c3 * s1; - m[1][0] =-c1 * s2; - m[1][1] = c2; - m[1][2] = s1 * s2; - m[2][0] = c3 * s1 + c1 * c2 * s3; - m[2][1] = s2 * s3; - m[2][2] = c1 * c3 - c2 * s1 * s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 * c3 - s1 * s3 + m[0][1] = c3 * s2 + m[0][2] =-c1 * s3 - c2 * c3 * s1 + m[1][0] =-c1 * s2 + m[1][1] = c2 + m[1][2] = s1 * s2 + m[2][0] = c3 * s1 + c1 * c2 * s3 + m[2][1] = s2 * s3 + m[2][2] = c1 * c3 - c2 * s1 * s3 + return } matrix3_from_euler_angles_zyz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2 * c3 - s1 * s3; - m[0][1] = c1 * s3 + c2 * c3 * s1; - m[0][2] =-c3 * s2; - m[1][0] =-c3 * s1 - c1 * c2 * s3; - m[1][1] = c1 * c3 - c2 * s1 * s3; - m[1][2] = s2 * s3; - m[2][0] = c1 * s2; - m[2][1] = s1 * s2; - m[2][2] = c2; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 * c3 - s1 * s3 + m[0][1] = c1 * s3 + c2 * c3 * s1 + m[0][2] =-c3 * s2 + m[1][0] =-c3 * s1 - c1 * c2 * s3 + m[1][1] = c1 * c3 - c2 * s1 * s3 + m[1][2] = s2 * s3 + m[2][0] = c1 * s2 + m[2][1] = s1 * s2 + m[2][2] = c2 + return } matrix3_from_euler_angles_zxz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - c2 * s1 * s3; - m[0][1] = c3 * s1 + c1 * c2 * s3; - m[0][2] = s2 *s3; - m[1][0] =-c1 * s3 - c2 * c3 * s1; - m[1][1] = c1 * c2 * c3 - s1 * s3; - m[1][2] = c3 * s2; - m[2][0] = s1 * s2; - m[2][1] =-c1 * s2; - m[2][2] = c2; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - c2 * s1 * s3 + m[0][1] = c3 * s1 + c1 * c2 * s3 + m[0][2] = s2 *s3 + m[1][0] =-c1 * s3 - c2 * c3 * s1 + m[1][1] = c1 * c2 * c3 - s1 * s3 + m[1][2] = c3 * s2 + m[2][0] = s1 * s2 + m[2][1] =-c1 * s2 + m[2][2] = c2 + return } matrix3_from_euler_angles_xzy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2 * c3; - m[0][1] = s1 * s3 + c1 * c3 * s2; - m[0][2] = c3 * s1 * s2 - c1 * s3; - m[1][0] =-s2; - m[1][1] = c1 * c2; - m[1][2] = c2 * s1; - m[2][0] = c2 * s3; - m[2][1] = c1 * s2 * s3 - c3 * s1; - m[2][2] = c1 * c3 + s1 * s2 *s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 * c3 + m[0][1] = s1 * s3 + c1 * c3 * s2 + m[0][2] = c3 * s1 * s2 - c1 * s3 + m[1][0] =-s2 + m[1][1] = c1 * c2 + m[1][2] = c2 * s1 + m[2][0] = c2 * s3 + m[2][1] = c1 * s2 * s3 - c3 * s1 + m[2][2] = c1 * c3 + s1 * s2 *s3 + return } matrix3_from_euler_angles_yzx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2; - m[0][1] = s2; - m[0][2] =-c2 * s1; - m[1][0] = s1 * s3 - c1 * c3 * s2; - m[1][1] = c2 * c3; - m[1][2] = c1 * s3 + c3 * s1 * s2; - m[2][0] = c3 * s1 + c1 * s2 * s3; - m[2][1] =-c2 * s3; - m[2][2] = c1 * c3 - s1 * s2 * s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 + m[0][1] = s2 + m[0][2] =-c2 * s1 + m[1][0] = s1 * s3 - c1 * c3 * s2 + m[1][1] = c2 * c3 + m[1][2] = c1 * s3 + c3 * s1 * s2 + m[2][0] = c3 * s1 + c1 * s2 * s3 + m[2][1] =-c2 * s3 + m[2][2] = c1 * c3 - s1 * s2 * s3 + return } matrix3_from_euler_angles_zyx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2; - m[0][1] = c2 * s1; - m[0][2] =-s2; - m[1][0] = c1 * s2 * s3 - c3 * s1; - m[1][1] = c1 * c3 + s1 * s2 * s3; - m[1][2] = c2 * s3; - m[2][0] = s1 * s3 + c1 * c3 * s2; - m[2][1] = c3 * s1 * s2 - c1 * s3; - m[2][2] = c2 * c3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 + m[0][1] = c2 * s1 + m[0][2] =-s2 + m[1][0] = c1 * s2 * s3 - c3 * s1 + m[1][1] = c1 * c3 + s1 * s2 * s3 + m[1][2] = c2 * s3 + m[2][0] = s1 * s3 + c1 * c3 * s2 + m[2][1] = c3 * s1 * s2 - c1 * s3 + m[2][2] = c2 * c3 + return } matrix3_from_euler_angles_zxy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - s1 * s2 * s3; - m[0][1] = c3 * s1 + c1 * s2 * s3; - m[0][2] =-c2 * s3; - m[1][0] =-c2 * s1; - m[1][1] = c1 * c2; - m[1][2] = s2; - m[2][0] = c1 * s3 + c3 * s1 * s2; - m[2][1] = s1 * s3 - c1 * c3 * s2; - m[2][2] = c2 * c3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - s1 * s2 * s3 + m[0][1] = c3 * s1 + c1 * s2 * s3 + m[0][2] =-c2 * s3 + m[1][0] =-c2 * s1 + m[1][1] = c1 * c2 + m[1][2] = s2 + m[2][0] = c1 * s3 + c3 * s1 * s2 + m[2][1] = s1 * s3 - c1 * c3 * s2 + m[2][2] = c2 * c3 + return } matrix3_from_yaw_pitch_roll_f32 :: proc(yaw, pitch, roll: f32) -> (m: Matrix3f32) { - ch := math.cos(yaw); - sh := math.sin(yaw); - cp := math.cos(pitch); - sp := math.sin(pitch); - cb := math.cos(roll); - sb := math.sin(roll); - - m[0][0] = ch * cb + sh * sp * sb; - m[0][1] = sb * cp; - m[0][2] = -sh * cb + ch * sp * sb; - m[1][0] = -ch * sb + sh * sp * cb; - m[1][1] = cb * cp; - m[1][2] = sb * sh + ch * sp * cb; - m[2][0] = sh * cp; - m[2][1] = -sp; - m[2][2] = ch * cp; - return m; + ch := math.cos(yaw) + sh := math.sin(yaw) + cp := math.cos(pitch) + sp := math.sin(pitch) + cb := math.cos(roll) + sb := math.sin(roll) + + m[0][0] = ch * cb + sh * sp * sb + m[0][1] = sb * cp + m[0][2] = -sh * cb + ch * sp * sb + m[1][0] = -ch * sb + sh * sp * cb + m[1][1] = cb * cp + m[1][2] = sb * sh + ch * sp * cb + m[2][0] = sh * cp + m[2][1] = -sp + m[2][2] = ch * cp + return m } euler_angles_xyz_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[2][1], m[2][2]); - C2 := math.sqrt(m[0][0]*m[0][0] + m[1][0]*m[1][0]); - T2 := math.atan2(-m[2][0], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[0][2] - C1*m[0][1], C1*m[1][1] - S1*m[1][2]); - t1 = -T1; - t2 = -T2; - t3 = -T3; - return; + T1 := math.atan2(m[2][1], m[2][2]) + C2 := math.sqrt(m[0][0]*m[0][0] + m[1][0]*m[1][0]) + T2 := math.atan2(-m[2][0], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[0][2] - C1*m[0][1], C1*m[1][1] - S1*m[1][2]) + t1 = -T1 + t2 = -T2 + t3 = -T3 + return } euler_angles_yxz_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[2][0], m[2][2]); - C2 := math.sqrt(m[0][1]*m[0][1] + m[1][1]*m[1][1]); - T2 := math.atan2(-m[2][1], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[1][2] - C1*m[1][0], C1*m[0][0] - S1*m[0][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][0], m[2][2]) + C2 := math.sqrt(m[0][1]*m[0][1] + m[1][1]*m[1][1]) + T2 := math.atan2(-m[2][1], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[1][2] - C1*m[1][0], C1*m[0][0] - S1*m[0][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xzx_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[0][2], m[0][1]); - S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]); - T2 := math.atan2(S2, m[0][0]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[1][2] - S1*m[1][1], C1*m[2][2] - S1*m[2][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][2], m[0][1]) + S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]) + T2 := math.atan2(S2, m[0][0]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[1][2] - S1*m[1][1], C1*m[2][2] - S1*m[2][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xyx_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[0][1], -m[0][2]); - S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]); - T2 := math.atan2(S2, m[0][0]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-C1*m[2][1] - S1*m[2][2], C1*m[1][1] + S1*m[1][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][1], -m[0][2]) + S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]) + T2 := math.atan2(S2, m[0][0]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-C1*m[2][1] - S1*m[2][2], C1*m[1][1] + S1*m[1][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yxy_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[1][0], m[1][2]); - S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]); - T2 := math.atan2(S2, m[1][1]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[2][0] - S1*m[2][2], C1*m[0][0] - S1*m[0][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][0], m[1][2]) + S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]) + T2 := math.atan2(S2, m[1][1]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[2][0] - S1*m[2][2], C1*m[0][0] - S1*m[0][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yzy_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[1][2], -m[1][0]); - S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]); - T2 := math.atan2(S2, m[1][1]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-S1*m[0][0] - C1*m[0][2], S1*m[2][0] + C1*m[2][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][2], -m[1][0]) + S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]) + T2 := math.atan2(S2, m[1][1]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-S1*m[0][0] - C1*m[0][2], S1*m[2][0] + C1*m[2][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zyz_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[2][1], m[2][0]); - S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]); - T2 := math.atan2(S2, m[2][2]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[0][1] - S1*m[0][0], C1*m[1][1] - S1*m[1][0]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][1], m[2][0]) + S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]) + T2 := math.atan2(S2, m[2][2]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[0][1] - S1*m[0][0], C1*m[1][1] - S1*m[1][0]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zxz_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[2][0], -m[2][1]); - S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]); - T2 := math.atan2(S2, m[2][2]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-C1*m[1][0] - S1*m[1][1], C1*m[0][0] + S1*m[0][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][0], -m[2][1]) + S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]) + T2 := math.atan2(S2, m[2][2]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-C1*m[1][0] - S1*m[1][1], C1*m[0][0] + S1*m[0][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xzy_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[1][2], m[1][1]); - C2 := math.sqrt(m[0][0]*m[0][0] + m[2][0]*m[2][0]); - T2 := math.atan2(-m[1][0], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[0][1] - C1*m[0][2], C1*m[2][2] - S1*m[2][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][2], m[1][1]) + C2 := math.sqrt(m[0][0]*m[0][0] + m[2][0]*m[2][0]) + T2 := math.atan2(-m[1][0], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[0][1] - C1*m[0][2], C1*m[2][2] - S1*m[2][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yzx_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(-m[0][2], m[0][0]); - C2 := math.sqrt(m[1][1]*m[1][1] + m[2][1]*m[2][1]); - T2 := math.atan2(m[0][1], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[1][0] + C1*m[1][2], S1*m[2][0] + C1*m[2][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(-m[0][2], m[0][0]) + C2 := math.sqrt(m[1][1]*m[1][1] + m[2][1]*m[2][1]) + T2 := math.atan2(m[0][1], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[1][0] + C1*m[1][2], S1*m[2][0] + C1*m[2][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zyx_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[0][1], m[0][0]); - C2 := math.sqrt(m[1][2]*m[1][2] + m[2][2]*m[2][2]); - T2 := math.atan2(-m[0][2], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[2][0] - C1*m[2][1], C1*m[1][1] - S1*m[1][0]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][1], m[0][0]) + C2 := math.sqrt(m[1][2]*m[1][2] + m[2][2]*m[2][2]) + T2 := math.atan2(-m[0][2], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[2][0] - C1*m[2][1], C1*m[1][1] - S1*m[1][0]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zxy_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(-m[1][0], m[1][1]); - C2 := math.sqrt(m[0][2]*m[0][2] + m[2][2]*m[2][2]); - T2 := math.atan2(m[1][2], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[2][0] + S1*m[2][1], C1*m[0][0] + S1*m[0][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(-m[1][0], m[1][1]) + C2 := math.sqrt(m[0][2]*m[0][2] + m[2][2]*m[2][2]) + T2 := math.atan2(m[1][2], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[2][0] + S1*m[2][1], C1*m[0][0] + S1*m[0][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } @@ -736,621 +736,621 @@ euler_angles_zxy_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { matrix4_from_euler_angle_x_f32 :: proc(angle_x: f32) -> (m: Matrix4f32) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - m[0][0] = 1; - m[1][1] = +cos_x; - m[2][1] = +sin_x; - m[1][2] = -sin_x; - m[2][2] = +cos_x; - m[3][3] = 1; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + m[0][0] = 1 + m[1][1] = +cos_x + m[2][1] = +sin_x + m[1][2] = -sin_x + m[2][2] = +cos_x + m[3][3] = 1 + return } matrix4_from_euler_angle_y_f32 :: proc(angle_y: f32) -> (m: Matrix4f32) { - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = +cos_y; - m[2][0] = -sin_y; - m[1][1] = 1; - m[0][2] = +sin_y; - m[2][2] = +cos_y; - m[3][3] = 1; - return; + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = +cos_y + m[2][0] = -sin_y + m[1][1] = 1 + m[0][2] = +sin_y + m[2][2] = +cos_y + m[3][3] = 1 + return } matrix4_from_euler_angle_z_f32 :: proc(angle_z: f32) -> (m: Matrix4f32) { - cos_z, sin_z := math.cos(angle_z), math.sin(angle_z); - m[0][0] = +cos_z; - m[1][0] = +sin_z; - m[1][1] = +cos_z; - m[0][1] = -sin_z; - m[2][2] = 1; - m[3][3] = 1; - return; + cos_z, sin_z := math.cos(angle_z), math.sin(angle_z) + m[0][0] = +cos_z + m[1][0] = +sin_z + m[1][1] = +cos_z + m[0][1] = -sin_z + m[2][2] = 1 + m[3][3] = 1 + return } matrix4_from_derived_euler_angle_x_f32 :: proc(angle_x: f32, angular_velocity_x: f32) -> (m: Matrix4f32) { - cos_x := math.cos(angle_x) * angular_velocity_x; - sin_x := math.sin(angle_x) * angular_velocity_x; - m[0][0] = 1; - m[1][1] = +cos_x; - m[2][1] = +sin_x; - m[1][2] = -sin_x; - m[2][2] = +cos_x; - m[3][3] = 1; - return; + cos_x := math.cos(angle_x) * angular_velocity_x + sin_x := math.sin(angle_x) * angular_velocity_x + m[0][0] = 1 + m[1][1] = +cos_x + m[2][1] = +sin_x + m[1][2] = -sin_x + m[2][2] = +cos_x + m[3][3] = 1 + return } matrix4_from_derived_euler_angle_y_f32 :: proc(angle_y: f32, angular_velocity_y: f32) -> (m: Matrix4f32) { - cos_y := math.cos(angle_y) * angular_velocity_y; - sin_y := math.sin(angle_y) * angular_velocity_y; - m[0][0] = +cos_y; - m[2][0] = -sin_y; - m[1][1] = 1; - m[0][2] = +sin_y; - m[2][2] = +cos_y; - m[3][3] = 1; - return; + cos_y := math.cos(angle_y) * angular_velocity_y + sin_y := math.sin(angle_y) * angular_velocity_y + m[0][0] = +cos_y + m[2][0] = -sin_y + m[1][1] = 1 + m[0][2] = +sin_y + m[2][2] = +cos_y + m[3][3] = 1 + return } matrix4_from_derived_euler_angle_z_f32 :: proc(angle_z: f32, angular_velocity_z: f32) -> (m: Matrix4f32) { - cos_z := math.cos(angle_z) * angular_velocity_z; - sin_z := math.sin(angle_z) * angular_velocity_z; - m[0][0] = +cos_z; - m[1][0] = +sin_z; - m[1][1] = +cos_z; - m[0][1] = -sin_z; - m[2][2] = 1; - m[3][3] = 1; - return; + cos_z := math.cos(angle_z) * angular_velocity_z + sin_z := math.sin(angle_z) * angular_velocity_z + m[0][0] = +cos_z + m[1][0] = +sin_z + m[1][1] = +cos_z + m[0][1] = -sin_z + m[2][2] = 1 + m[3][3] = 1 + return } matrix4_from_euler_angles_xy_f32 :: proc(angle_x, angle_y: f32) -> (m: Matrix4f32) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = cos_y; - m[1][0] = -sin_x * - sin_y; - m[2][0] = -cos_x * - sin_y; - m[1][1] = cos_x; - m[2][1] = sin_x; - m[0][2] = sin_y; - m[1][2] = -sin_x * cos_y; - m[2][2] = cos_x * cos_y; - m[3][3] = 1; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = cos_y + m[1][0] = -sin_x * - sin_y + m[2][0] = -cos_x * - sin_y + m[1][1] = cos_x + m[2][1] = sin_x + m[0][2] = sin_y + m[1][2] = -sin_x * cos_y + m[2][2] = cos_x * cos_y + m[3][3] = 1 + return } matrix4_from_euler_angles_yx_f32 :: proc(angle_y, angle_x: f32) -> (m: Matrix4f32) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = cos_y; - m[2][0] = -sin_y; - m[0][1] = sin_y*sin_x; - m[1][1] = cos_x; - m[2][1] = cos_y*sin_x; - m[0][2] = sin_y*cos_x; - m[1][2] = -sin_x; - m[2][2] = cos_y*cos_x; - m[3][3] = 1; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = cos_y + m[2][0] = -sin_y + m[0][1] = sin_y*sin_x + m[1][1] = cos_x + m[2][1] = cos_y*sin_x + m[0][2] = sin_y*cos_x + m[1][2] = -sin_x + m[2][2] = cos_y*cos_x + m[3][3] = 1 + return } matrix4_from_euler_angles_xz_f32 :: proc(angle_x, angle_z: f32) -> (m: Matrix4f32) { - return mul(matrix4_from_euler_angle_x(angle_x), matrix4_from_euler_angle_z(angle_z)); + return mul(matrix4_from_euler_angle_x(angle_x), matrix4_from_euler_angle_z(angle_z)) } matrix4_from_euler_angles_zx_f32 :: proc(angle_z, angle_x: f32) -> (m: Matrix4f32) { - return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_x(angle_x)); + return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_x(angle_x)) } matrix4_from_euler_angles_yz_f32 :: proc(angle_y, angle_z: f32) -> (m: Matrix4f32) { - return mul(matrix4_from_euler_angle_y(angle_y), matrix4_from_euler_angle_z(angle_z)); + return mul(matrix4_from_euler_angle_y(angle_y), matrix4_from_euler_angle_z(angle_z)) } matrix4_from_euler_angles_zy_f32 :: proc(angle_z, angle_y: f32) -> (m: Matrix4f32) { - return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_y(angle_y)); + return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_y(angle_y)) } matrix4_from_euler_angles_xyz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { - c1 := math.cos(-t1); - c2 := math.cos(-t2); - c3 := math.cos(-t3); - s1 := math.sin(-t1); - s2 := math.sin(-t2); - s3 := math.sin(-t3); - - m[0][0] = c2 * c3; - m[0][1] =-c1 * s3 + s1 * s2 * c3; - m[0][2] = s1 * s3 + c1 * s2 * c3; - m[0][3] = 0; - m[1][0] = c2 * s3; - m[1][1] = c1 * c3 + s1 * s2 * s3; - m[1][2] =-s1 * c3 + c1 * s2 * s3; - m[1][3] = 0; - m[2][0] =-s2; - m[2][1] = s1 * c2; - m[2][2] = c1 * c2; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(-t1) + c2 := math.cos(-t2) + c3 := math.cos(-t3) + s1 := math.sin(-t1) + s2 := math.sin(-t2) + s3 := math.sin(-t3) + + m[0][0] = c2 * c3 + m[0][1] =-c1 * s3 + s1 * s2 * c3 + m[0][2] = s1 * s3 + c1 * s2 * c3 + m[0][3] = 0 + m[1][0] = c2 * s3 + m[1][1] = c1 * c3 + s1 * s2 * s3 + m[1][2] =-s1 * c3 + c1 * s2 * s3 + m[1][3] = 0 + m[2][0] =-s2 + m[2][1] = s1 * c2 + m[2][2] = c1 * c2 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_yxz_f32 :: proc(yaw, pitch, roll: f32) -> (m: Matrix4f32) { - ch := math.cos(yaw); - sh := math.sin(yaw); - cp := math.cos(pitch); - sp := math.sin(pitch); - cb := math.cos(roll); - sb := math.sin(roll); - - m[0][0] = ch * cb + sh * sp * sb; - m[0][1] = sb * cp; - m[0][2] = -sh * cb + ch * sp * sb; - m[0][3] = 0; - m[1][0] = -ch * sb + sh * sp * cb; - m[1][1] = cb * cp; - m[1][2] = sb * sh + ch * sp * cb; - m[1][3] = 0; - m[2][0] = sh * cp; - m[2][1] = -sp; - m[2][2] = ch * cp; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + ch := math.cos(yaw) + sh := math.sin(yaw) + cp := math.cos(pitch) + sp := math.sin(pitch) + cb := math.cos(roll) + sb := math.sin(roll) + + m[0][0] = ch * cb + sh * sp * sb + m[0][1] = sb * cp + m[0][2] = -sh * cb + ch * sp * sb + m[0][3] = 0 + m[1][0] = -ch * sb + sh * sp * cb + m[1][1] = cb * cp + m[1][2] = sb * sh + ch * sp * cb + m[1][3] = 0 + m[2][0] = sh * cp + m[2][1] = -sp + m[2][2] = ch * cp + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_xzx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2; - m[0][1] = c1 * s2; - m[0][2] = s1 * s2; - m[0][3] = 0; - m[1][0] =-c3 * s2; - m[1][1] = c1 * c2 * c3 - s1 * s3; - m[1][2] = c1 * s3 + c2 * c3 * s1; - m[1][3] = 0; - m[2][0] = s2 * s3; - m[2][1] =-c3 * s1 - c1 * c2 * s3; - m[2][2] = c1 * c3 - c2 * s1 * s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 + m[0][1] = c1 * s2 + m[0][2] = s1 * s2 + m[0][3] = 0 + m[1][0] =-c3 * s2 + m[1][1] = c1 * c2 * c3 - s1 * s3 + m[1][2] = c1 * s3 + c2 * c3 * s1 + m[1][3] = 0 + m[2][0] = s2 * s3 + m[2][1] =-c3 * s1 - c1 * c2 * s3 + m[2][2] = c1 * c3 - c2 * s1 * s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_xyx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2; - m[0][1] = s1 * s2; - m[0][2] =-c1 * s2; - m[0][3] = 0; - m[1][0] = s2 * s3; - m[1][1] = c1 * c3 - c2 * s1 * s3; - m[1][2] = c3 * s1 + c1 * c2 * s3; - m[1][3] = 0; - m[2][0] = c3 * s2; - m[2][1] =-c1 * s3 - c2 * c3 * s1; - m[2][2] = c1 * c2 * c3 - s1 * s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 + m[0][1] = s1 * s2 + m[0][2] =-c1 * s2 + m[0][3] = 0 + m[1][0] = s2 * s3 + m[1][1] = c1 * c3 - c2 * s1 * s3 + m[1][2] = c3 * s1 + c1 * c2 * s3 + m[1][3] = 0 + m[2][0] = c3 * s2 + m[2][1] =-c1 * s3 - c2 * c3 * s1 + m[2][2] = c1 * c2 * c3 - s1 * s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_yxy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - c2 * s1 * s3; - m[0][1] = s2* s3; - m[0][2] =-c3 * s1 - c1 * c2 * s3; - m[0][3] = 0; - m[1][0] = s1 * s2; - m[1][1] = c2; - m[1][2] = c1 * s2; - m[1][3] = 0; - m[2][0] = c1 * s3 + c2 * c3 * s1; - m[2][1] =-c3 * s2; - m[2][2] = c1 * c2 * c3 - s1 * s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - c2 * s1 * s3 + m[0][1] = s2* s3 + m[0][2] =-c3 * s1 - c1 * c2 * s3 + m[0][3] = 0 + m[1][0] = s1 * s2 + m[1][1] = c2 + m[1][2] = c1 * s2 + m[1][3] = 0 + m[2][0] = c1 * s3 + c2 * c3 * s1 + m[2][1] =-c3 * s2 + m[2][2] = c1 * c2 * c3 - s1 * s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_yzy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2 * c3 - s1 * s3; - m[0][1] = c3 * s2; - m[0][2] =-c1 * s3 - c2 * c3 * s1; - m[0][3] = 0; - m[1][0] =-c1 * s2; - m[1][1] = c2; - m[1][2] = s1 * s2; - m[1][3] = 0; - m[2][0] = c3 * s1 + c1 * c2 * s3; - m[2][1] = s2 * s3; - m[2][2] = c1 * c3 - c2 * s1 * s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 * c3 - s1 * s3 + m[0][1] = c3 * s2 + m[0][2] =-c1 * s3 - c2 * c3 * s1 + m[0][3] = 0 + m[1][0] =-c1 * s2 + m[1][1] = c2 + m[1][2] = s1 * s2 + m[1][3] = 0 + m[2][0] = c3 * s1 + c1 * c2 * s3 + m[2][1] = s2 * s3 + m[2][2] = c1 * c3 - c2 * s1 * s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_zyz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2 * c3 - s1 * s3; - m[0][1] = c1 * s3 + c2 * c3 * s1; - m[0][2] =-c3 * s2; - m[0][3] = 0; - m[1][0] =-c3 * s1 - c1 * c2 * s3; - m[1][1] = c1 * c3 - c2 * s1 * s3; - m[1][2] = s2 * s3; - m[1][3] = 0; - m[2][0] = c1 * s2; - m[2][1] = s1 * s2; - m[2][2] = c2; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 * c3 - s1 * s3 + m[0][1] = c1 * s3 + c2 * c3 * s1 + m[0][2] =-c3 * s2 + m[0][3] = 0 + m[1][0] =-c3 * s1 - c1 * c2 * s3 + m[1][1] = c1 * c3 - c2 * s1 * s3 + m[1][2] = s2 * s3 + m[1][3] = 0 + m[2][0] = c1 * s2 + m[2][1] = s1 * s2 + m[2][2] = c2 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_zxz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - c2 * s1 * s3; - m[0][1] = c3 * s1 + c1 * c2 * s3; - m[0][2] = s2 *s3; - m[0][3] = 0; - m[1][0] =-c1 * s3 - c2 * c3 * s1; - m[1][1] = c1 * c2 * c3 - s1 * s3; - m[1][2] = c3 * s2; - m[1][3] = 0; - m[2][0] = s1 * s2; - m[2][1] =-c1 * s2; - m[2][2] = c2; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - c2 * s1 * s3 + m[0][1] = c3 * s1 + c1 * c2 * s3 + m[0][2] = s2 *s3 + m[0][3] = 0 + m[1][0] =-c1 * s3 - c2 * c3 * s1 + m[1][1] = c1 * c2 * c3 - s1 * s3 + m[1][2] = c3 * s2 + m[1][3] = 0 + m[2][0] = s1 * s2 + m[2][1] =-c1 * s2 + m[2][2] = c2 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_xzy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2 * c3; - m[0][1] = s1 * s3 + c1 * c3 * s2; - m[0][2] = c3 * s1 * s2 - c1 * s3; - m[0][3] = 0; - m[1][0] =-s2; - m[1][1] = c1 * c2; - m[1][2] = c2 * s1; - m[1][3] = 0; - m[2][0] = c2 * s3; - m[2][1] = c1 * s2 * s3 - c3 * s1; - m[2][2] = c1 * c3 + s1 * s2 *s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 * c3 + m[0][1] = s1 * s3 + c1 * c3 * s2 + m[0][2] = c3 * s1 * s2 - c1 * s3 + m[0][3] = 0 + m[1][0] =-s2 + m[1][1] = c1 * c2 + m[1][2] = c2 * s1 + m[1][3] = 0 + m[2][0] = c2 * s3 + m[2][1] = c1 * s2 * s3 - c3 * s1 + m[2][2] = c1 * c3 + s1 * s2 *s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_yzx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2; - m[0][1] = s2; - m[0][2] =-c2 * s1; - m[0][3] = 0; - m[1][0] = s1 * s3 - c1 * c3 * s2; - m[1][1] = c2 * c3; - m[1][2] = c1 * s3 + c3 * s1 * s2; - m[1][3] = 0; - m[2][0] = c3 * s1 + c1 * s2 * s3; - m[2][1] =-c2 * s3; - m[2][2] = c1 * c3 - s1 * s2 * s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 + m[0][1] = s2 + m[0][2] =-c2 * s1 + m[0][3] = 0 + m[1][0] = s1 * s3 - c1 * c3 * s2 + m[1][1] = c2 * c3 + m[1][2] = c1 * s3 + c3 * s1 * s2 + m[1][3] = 0 + m[2][0] = c3 * s1 + c1 * s2 * s3 + m[2][1] =-c2 * s3 + m[2][2] = c1 * c3 - s1 * s2 * s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_zyx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2; - m[0][1] = c2 * s1; - m[0][2] =-s2; - m[0][3] = 0; - m[1][0] = c1 * s2 * s3 - c3 * s1; - m[1][1] = c1 * c3 + s1 * s2 * s3; - m[1][2] = c2 * s3; - m[1][3] = 0; - m[2][0] = s1 * s3 + c1 * c3 * s2; - m[2][1] = c3 * s1 * s2 - c1 * s3; - m[2][2] = c2 * c3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 + m[0][1] = c2 * s1 + m[0][2] =-s2 + m[0][3] = 0 + m[1][0] = c1 * s2 * s3 - c3 * s1 + m[1][1] = c1 * c3 + s1 * s2 * s3 + m[1][2] = c2 * s3 + m[1][3] = 0 + m[2][0] = s1 * s3 + c1 * c3 * s2 + m[2][1] = c3 * s1 * s2 - c1 * s3 + m[2][2] = c2 * c3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_zxy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - s1 * s2 * s3; - m[0][1] = c3 * s1 + c1 * s2 * s3; - m[0][2] =-c2 * s3; - m[0][3] = 0; - m[1][0] =-c2 * s1; - m[1][1] = c1 * c2; - m[1][2] = s2; - m[1][3] = 0; - m[2][0] = c1 * s3 + c3 * s1 * s2; - m[2][1] = s1 * s3 - c1 * c3 * s2; - m[2][2] = c2 * c3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - s1 * s2 * s3 + m[0][1] = c3 * s1 + c1 * s2 * s3 + m[0][2] =-c2 * s3 + m[0][3] = 0 + m[1][0] =-c2 * s1 + m[1][1] = c1 * c2 + m[1][2] = s2 + m[1][3] = 0 + m[2][0] = c1 * s3 + c3 * s1 * s2 + m[2][1] = s1 * s3 - c1 * c3 * s2 + m[2][2] = c2 * c3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_yaw_pitch_roll_f32 :: proc(yaw, pitch, roll: f32) -> (m: Matrix4f32) { - ch := math.cos(yaw); - sh := math.sin(yaw); - cp := math.cos(pitch); - sp := math.sin(pitch); - cb := math.cos(roll); - sb := math.sin(roll); - - m[0][0] = ch * cb + sh * sp * sb; - m[0][1] = sb * cp; - m[0][2] = -sh * cb + ch * sp * sb; - m[0][3] = 0; - m[1][0] = -ch * sb + sh * sp * cb; - m[1][1] = cb * cp; - m[1][2] = sb * sh + ch * sp * cb; - m[1][3] = 0; - m[2][0] = sh * cp; - m[2][1] = -sp; - m[2][2] = ch * cp; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return m; + ch := math.cos(yaw) + sh := math.sin(yaw) + cp := math.cos(pitch) + sp := math.sin(pitch) + cb := math.cos(roll) + sb := math.sin(roll) + + m[0][0] = ch * cb + sh * sp * sb + m[0][1] = sb * cp + m[0][2] = -sh * cb + ch * sp * sb + m[0][3] = 0 + m[1][0] = -ch * sb + sh * sp * cb + m[1][1] = cb * cp + m[1][2] = sb * sh + ch * sp * cb + m[1][3] = 0 + m[2][0] = sh * cp + m[2][1] = -sp + m[2][2] = ch * cp + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return m } euler_angles_xyz_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[2][1], m[2][2]); - C2 := math.sqrt(m[0][0]*m[0][0] + m[1][0]*m[1][0]); - T2 := math.atan2(-m[2][0], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[0][2] - C1*m[0][1], C1*m[1][1] - S1*m[1][2]); - t1 = -T1; - t2 = -T2; - t3 = -T3; - return; + T1 := math.atan2(m[2][1], m[2][2]) + C2 := math.sqrt(m[0][0]*m[0][0] + m[1][0]*m[1][0]) + T2 := math.atan2(-m[2][0], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[0][2] - C1*m[0][1], C1*m[1][1] - S1*m[1][2]) + t1 = -T1 + t2 = -T2 + t3 = -T3 + return } euler_angles_yxz_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[2][0], m[2][2]); - C2 := math.sqrt(m[0][1]*m[0][1] + m[1][1]*m[1][1]); - T2 := math.atan2(-m[2][1], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[1][2] - C1*m[1][0], C1*m[0][0] - S1*m[0][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][0], m[2][2]) + C2 := math.sqrt(m[0][1]*m[0][1] + m[1][1]*m[1][1]) + T2 := math.atan2(-m[2][1], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[1][2] - C1*m[1][0], C1*m[0][0] - S1*m[0][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xzx_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[0][2], m[0][1]); - S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]); - T2 := math.atan2(S2, m[0][0]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[1][2] - S1*m[1][1], C1*m[2][2] - S1*m[2][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][2], m[0][1]) + S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]) + T2 := math.atan2(S2, m[0][0]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[1][2] - S1*m[1][1], C1*m[2][2] - S1*m[2][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xyx_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[0][1], -m[0][2]); - S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]); - T2 := math.atan2(S2, m[0][0]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-C1*m[2][1] - S1*m[2][2], C1*m[1][1] + S1*m[1][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][1], -m[0][2]) + S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]) + T2 := math.atan2(S2, m[0][0]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-C1*m[2][1] - S1*m[2][2], C1*m[1][1] + S1*m[1][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yxy_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[1][0], m[1][2]); - S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]); - T2 := math.atan2(S2, m[1][1]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[2][0] - S1*m[2][2], C1*m[0][0] - S1*m[0][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][0], m[1][2]) + S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]) + T2 := math.atan2(S2, m[1][1]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[2][0] - S1*m[2][2], C1*m[0][0] - S1*m[0][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yzy_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[1][2], -m[1][0]); - S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]); - T2 := math.atan2(S2, m[1][1]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-S1*m[0][0] - C1*m[0][2], S1*m[2][0] + C1*m[2][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][2], -m[1][0]) + S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]) + T2 := math.atan2(S2, m[1][1]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-S1*m[0][0] - C1*m[0][2], S1*m[2][0] + C1*m[2][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zyz_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[2][1], m[2][0]); - S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]); - T2 := math.atan2(S2, m[2][2]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[0][1] - S1*m[0][0], C1*m[1][1] - S1*m[1][0]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][1], m[2][0]) + S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]) + T2 := math.atan2(S2, m[2][2]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[0][1] - S1*m[0][0], C1*m[1][1] - S1*m[1][0]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zxz_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[2][0], -m[2][1]); - S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]); - T2 := math.atan2(S2, m[2][2]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-C1*m[1][0] - S1*m[1][1], C1*m[0][0] + S1*m[0][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][0], -m[2][1]) + S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]) + T2 := math.atan2(S2, m[2][2]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-C1*m[1][0] - S1*m[1][1], C1*m[0][0] + S1*m[0][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xzy_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[1][2], m[1][1]); - C2 := math.sqrt(m[0][0]*m[0][0] + m[2][0]*m[2][0]); - T2 := math.atan2(-m[1][0], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[0][1] - C1*m[0][2], C1*m[2][2] - S1*m[2][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][2], m[1][1]) + C2 := math.sqrt(m[0][0]*m[0][0] + m[2][0]*m[2][0]) + T2 := math.atan2(-m[1][0], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[0][1] - C1*m[0][2], C1*m[2][2] - S1*m[2][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yzx_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(-m[0][2], m[0][0]); - C2 := math.sqrt(m[1][1]*m[1][1] + m[2][1]*m[2][1]); - T2 := math.atan2(m[0][1], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[1][0] + C1*m[1][2], S1*m[2][0] + C1*m[2][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(-m[0][2], m[0][0]) + C2 := math.sqrt(m[1][1]*m[1][1] + m[2][1]*m[2][1]) + T2 := math.atan2(m[0][1], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[1][0] + C1*m[1][2], S1*m[2][0] + C1*m[2][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zyx_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[0][1], m[0][0]); - C2 := math.sqrt(m[1][2]*m[1][2] + m[2][2]*m[2][2]); - T2 := math.atan2(-m[0][2], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[2][0] - C1*m[2][1], C1*m[1][1] - S1*m[1][0]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][1], m[0][0]) + C2 := math.sqrt(m[1][2]*m[1][2] + m[2][2]*m[2][2]) + T2 := math.atan2(-m[0][2], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[2][0] - C1*m[2][1], C1*m[1][1] - S1*m[1][0]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zxy_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(-m[1][0], m[1][1]); - C2 := math.sqrt(m[0][2]*m[0][2] + m[2][2]*m[2][2]); - T2 := math.atan2(m[1][2], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[2][0] + S1*m[2][1], C1*m[0][0] + S1*m[0][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(-m[1][0], m[1][1]) + C2 := math.sqrt(m[0][2]*m[0][2] + m[2][2]*m[2][2]) + T2 := math.atan2(m[1][2], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[2][0] + S1*m[2][1], C1*m[0][0] + S1*m[0][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } diff --git a/core/math/linalg/specific_euler_angles_f64.odin b/core/math/linalg/specific_euler_angles_f64.odin index a62c2d5e8..efaddd651 100644 --- a/core/math/linalg/specific_euler_angles_f64.odin +++ b/core/math/linalg/specific_euler_angles_f64.odin @@ -4,206 +4,206 @@ import "core:math" euler_angles_from_matrix3_f64 :: proc(m: Matrix3f64, order: Euler_Angle_Order) -> (t1, t2, t3: f64) { switch order { - case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix3(m); - case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix3(m); - case .YXZ: t1, t2, t3 = euler_angles_yxz_from_matrix3(m); - case .YZX: t1, t2, t3 = euler_angles_yzx_from_matrix3(m); - case .ZXY: t1, t2, t3 = euler_angles_zxy_from_matrix3(m); - case .ZYX: t1, t2, t3 = euler_angles_zyx_from_matrix3(m); - case .XYX: t1, t2, t3 = euler_angles_xyx_from_matrix3(m); - case .XZX: t1, t2, t3 = euler_angles_xzx_from_matrix3(m); - case .YXY: t1, t2, t3 = euler_angles_yxy_from_matrix3(m); - case .YZY: t1, t2, t3 = euler_angles_yzy_from_matrix3(m); - case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_matrix3(m); - case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_matrix3(m); + case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix3(m) + case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix3(m) + case .YXZ: t1, t2, t3 = euler_angles_yxz_from_matrix3(m) + case .YZX: t1, t2, t3 = euler_angles_yzx_from_matrix3(m) + case .ZXY: t1, t2, t3 = euler_angles_zxy_from_matrix3(m) + case .ZYX: t1, t2, t3 = euler_angles_zyx_from_matrix3(m) + case .XYX: t1, t2, t3 = euler_angles_xyx_from_matrix3(m) + case .XZX: t1, t2, t3 = euler_angles_xzx_from_matrix3(m) + case .YXY: t1, t2, t3 = euler_angles_yxy_from_matrix3(m) + case .YZY: t1, t2, t3 = euler_angles_yzy_from_matrix3(m) + case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_matrix3(m) + case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_matrix3(m) } - return; + return } euler_angles_from_matrix4_f64 :: proc(m: Matrix4f64, order: Euler_Angle_Order) -> (t1, t2, t3: f64) { switch order { - case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix4(m); - case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix4(m); - case .YXZ: t1, t2, t3 = euler_angles_yxz_from_matrix4(m); - case .YZX: t1, t2, t3 = euler_angles_yzx_from_matrix4(m); - case .ZXY: t1, t2, t3 = euler_angles_zxy_from_matrix4(m); - case .ZYX: t1, t2, t3 = euler_angles_zyx_from_matrix4(m); - case .XYX: t1, t2, t3 = euler_angles_xyx_from_matrix4(m); - case .XZX: t1, t2, t3 = euler_angles_xzx_from_matrix4(m); - case .YXY: t1, t2, t3 = euler_angles_yxy_from_matrix4(m); - case .YZY: t1, t2, t3 = euler_angles_yzy_from_matrix4(m); - case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_matrix4(m); - case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_matrix4(m); + case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix4(m) + case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix4(m) + case .YXZ: t1, t2, t3 = euler_angles_yxz_from_matrix4(m) + case .YZX: t1, t2, t3 = euler_angles_yzx_from_matrix4(m) + case .ZXY: t1, t2, t3 = euler_angles_zxy_from_matrix4(m) + case .ZYX: t1, t2, t3 = euler_angles_zyx_from_matrix4(m) + case .XYX: t1, t2, t3 = euler_angles_xyx_from_matrix4(m) + case .XZX: t1, t2, t3 = euler_angles_xzx_from_matrix4(m) + case .YXY: t1, t2, t3 = euler_angles_yxy_from_matrix4(m) + case .YZY: t1, t2, t3 = euler_angles_yzy_from_matrix4(m) + case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_matrix4(m) + case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_matrix4(m) } - return; + return } euler_angles_from_quaternion_f64 :: proc(m: Quaternionf64, order: Euler_Angle_Order) -> (t1, t2, t3: f64) { switch order { - case .XYZ: t1, t2, t3 = euler_angles_xyz_from_quaternion(m); - case .XZY: t1, t2, t3 = euler_angles_xzy_from_quaternion(m); - case .YXZ: t1, t2, t3 = euler_angles_yxz_from_quaternion(m); - case .YZX: t1, t2, t3 = euler_angles_yzx_from_quaternion(m); - case .ZXY: t1, t2, t3 = euler_angles_zxy_from_quaternion(m); - case .ZYX: t1, t2, t3 = euler_angles_zyx_from_quaternion(m); - case .XYX: t1, t2, t3 = euler_angles_xyx_from_quaternion(m); - case .XZX: t1, t2, t3 = euler_angles_xzx_from_quaternion(m); - case .YXY: t1, t2, t3 = euler_angles_yxy_from_quaternion(m); - case .YZY: t1, t2, t3 = euler_angles_yzy_from_quaternion(m); - case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_quaternion(m); - case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_quaternion(m); + case .XYZ: t1, t2, t3 = euler_angles_xyz_from_quaternion(m) + case .XZY: t1, t2, t3 = euler_angles_xzy_from_quaternion(m) + case .YXZ: t1, t2, t3 = euler_angles_yxz_from_quaternion(m) + case .YZX: t1, t2, t3 = euler_angles_yzx_from_quaternion(m) + case .ZXY: t1, t2, t3 = euler_angles_zxy_from_quaternion(m) + case .ZYX: t1, t2, t3 = euler_angles_zyx_from_quaternion(m) + case .XYX: t1, t2, t3 = euler_angles_xyx_from_quaternion(m) + case .XZX: t1, t2, t3 = euler_angles_xzx_from_quaternion(m) + case .YXY: t1, t2, t3 = euler_angles_yxy_from_quaternion(m) + case .YZY: t1, t2, t3 = euler_angles_yzy_from_quaternion(m) + case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_quaternion(m) + case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_quaternion(m) } - return; + return } matrix3_from_euler_angles_f64 :: proc(t1, t2, t3: f64, order: Euler_Angle_Order) -> (m: Matrix3f64) { switch order { - case .XYZ: return matrix3_from_euler_angles_xyz(t1, t2, t3); // m1, m2, m3 = X(t1), Y(t2), Z(t3); - case .XZY: return matrix3_from_euler_angles_xzy(t1, t2, t3); // m1, m2, m3 = X(t1), Z(t2), Y(t3); - case .YXZ: return matrix3_from_euler_angles_yxz(t1, t2, t3); // m1, m2, m3 = Y(t1), X(t2), Z(t3); - case .YZX: return matrix3_from_euler_angles_yzx(t1, t2, t3); // m1, m2, m3 = Y(t1), Z(t2), X(t3); - case .ZXY: return matrix3_from_euler_angles_zxy(t1, t2, t3); // m1, m2, m3 = Z(t1), X(t2), Y(t3); - case .ZYX: return matrix3_from_euler_angles_zyx(t1, t2, t3); // m1, m2, m3 = Z(t1), Y(t2), X(t3); - case .XYX: return matrix3_from_euler_angles_xyx(t1, t2, t3); // m1, m2, m3 = X(t1), Y(t2), X(t3); - case .XZX: return matrix3_from_euler_angles_xzx(t1, t2, t3); // m1, m2, m3 = X(t1), Z(t2), X(t3); - case .YXY: return matrix3_from_euler_angles_yxy(t1, t2, t3); // m1, m2, m3 = Y(t1), X(t2), Y(t3); - case .YZY: return matrix3_from_euler_angles_yzy(t1, t2, t3); // m1, m2, m3 = Y(t1), Z(t2), Y(t3); - case .ZXZ: return matrix3_from_euler_angles_zxz(t1, t2, t3); // m1, m2, m3 = Z(t1), X(t2), Z(t3); - case .ZYZ: return matrix3_from_euler_angles_zyz(t1, t2, t3); // m1, m2, m3 = Z(t1), Y(t2), Z(t3); + case .XYZ: return matrix3_from_euler_angles_xyz(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), Z(t3); + case .XZY: return matrix3_from_euler_angles_xzy(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), Y(t3); + case .YXZ: return matrix3_from_euler_angles_yxz(t1, t2, t3) // m1, m2, m3 = Y(t1), X(t2), Z(t3); + case .YZX: return matrix3_from_euler_angles_yzx(t1, t2, t3) // m1, m2, m3 = Y(t1), Z(t2), X(t3); + case .ZXY: return matrix3_from_euler_angles_zxy(t1, t2, t3) // m1, m2, m3 = Z(t1), X(t2), Y(t3); + case .ZYX: return matrix3_from_euler_angles_zyx(t1, t2, t3) // m1, m2, m3 = Z(t1), Y(t2), X(t3); + case .XYX: return matrix3_from_euler_angles_xyx(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), X(t3); + case .XZX: return matrix3_from_euler_angles_xzx(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), X(t3); + case .YXY: return matrix3_from_euler_angles_yxy(t1, t2, t3) // m1, m2, m3 = Y(t1), X(t2), Y(t3); + case .YZY: return matrix3_from_euler_angles_yzy(t1, t2, t3) // m1, m2, m3 = Y(t1), Z(t2), Y(t3); + case .ZXZ: return matrix3_from_euler_angles_zxz(t1, t2, t3) // m1, m2, m3 = Z(t1), X(t2), Z(t3); + case .ZYZ: return matrix3_from_euler_angles_zyz(t1, t2, t3) // m1, m2, m3 = Z(t1), Y(t2), Z(t3); } - return; + return } matrix4_from_euler_angles_f64 :: proc(t1, t2, t3: f64, order: Euler_Angle_Order) -> (m: Matrix4f64) { switch order { - case .XYZ: return matrix4_from_euler_angles_xyz(t1, t2, t3); // m1, m2, m3 = X(t1), Y(t2), Z(t3); - case .XZY: return matrix4_from_euler_angles_xzy(t1, t2, t3); // m1, m2, m3 = X(t1), Z(t2), Y(t3); - case .YXZ: return matrix4_from_euler_angles_yxz(t1, t2, t3); // m1, m2, m3 = Y(t1), X(t2), Z(t3); - case .YZX: return matrix4_from_euler_angles_yzx(t1, t2, t3); // m1, m2, m3 = Y(t1), Z(t2), X(t3); - case .ZXY: return matrix4_from_euler_angles_zxy(t1, t2, t3); // m1, m2, m3 = Z(t1), X(t2), Y(t3); - case .ZYX: return matrix4_from_euler_angles_zyx(t1, t2, t3); // m1, m2, m3 = Z(t1), Y(t2), X(t3); - case .XYX: return matrix4_from_euler_angles_xyx(t1, t2, t3); // m1, m2, m3 = X(t1), Y(t2), X(t3); - case .XZX: return matrix4_from_euler_angles_xzx(t1, t2, t3); // m1, m2, m3 = X(t1), Z(t2), X(t3); - case .YXY: return matrix4_from_euler_angles_yxy(t1, t2, t3); // m1, m2, m3 = Y(t1), X(t2), Y(t3); - case .YZY: return matrix4_from_euler_angles_yzy(t1, t2, t3); // m1, m2, m3 = Y(t1), Z(t2), Y(t3); - case .ZXZ: return matrix4_from_euler_angles_zxz(t1, t2, t3); // m1, m2, m3 = Z(t1), X(t2), Z(t3); - case .ZYZ: return matrix4_from_euler_angles_zyz(t1, t2, t3); // m1, m2, m3 = Z(t1), Y(t2), Z(t3); + case .XYZ: return matrix4_from_euler_angles_xyz(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), Z(t3); + case .XZY: return matrix4_from_euler_angles_xzy(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), Y(t3); + case .YXZ: return matrix4_from_euler_angles_yxz(t1, t2, t3) // m1, m2, m3 = Y(t1), X(t2), Z(t3); + case .YZX: return matrix4_from_euler_angles_yzx(t1, t2, t3) // m1, m2, m3 = Y(t1), Z(t2), X(t3); + case .ZXY: return matrix4_from_euler_angles_zxy(t1, t2, t3) // m1, m2, m3 = Z(t1), X(t2), Y(t3); + case .ZYX: return matrix4_from_euler_angles_zyx(t1, t2, t3) // m1, m2, m3 = Z(t1), Y(t2), X(t3); + case .XYX: return matrix4_from_euler_angles_xyx(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), X(t3); + case .XZX: return matrix4_from_euler_angles_xzx(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), X(t3); + case .YXY: return matrix4_from_euler_angles_yxy(t1, t2, t3) // m1, m2, m3 = Y(t1), X(t2), Y(t3); + case .YZY: return matrix4_from_euler_angles_yzy(t1, t2, t3) // m1, m2, m3 = Y(t1), Z(t2), Y(t3); + case .ZXZ: return matrix4_from_euler_angles_zxz(t1, t2, t3) // m1, m2, m3 = Z(t1), X(t2), Z(t3); + case .ZYZ: return matrix4_from_euler_angles_zyz(t1, t2, t3) // m1, m2, m3 = Z(t1), Y(t2), Z(t3); } - return; + return } quaternion_from_euler_angles_f64 :: proc(t1, t2, t3: f64, order: Euler_Angle_Order) -> Quaternionf64 { - X :: quaternion_from_euler_angle_x; - Y :: quaternion_from_euler_angle_y; - Z :: quaternion_from_euler_angle_z; + X :: quaternion_from_euler_angle_x + Y :: quaternion_from_euler_angle_y + Z :: quaternion_from_euler_angle_z - q1, q2, q3: Quaternionf64; + q1, q2, q3: Quaternionf64 switch order { - case .XYZ: q1, q2, q3 = X(t1), Y(t2), Z(t3); - case .XZY: q1, q2, q3 = X(t1), Z(t2), Y(t3); - case .YXZ: q1, q2, q3 = Y(t1), X(t2), Z(t3); - case .YZX: q1, q2, q3 = Y(t1), Z(t2), X(t3); - case .ZXY: q1, q2, q3 = Z(t1), X(t2), Y(t3); - case .ZYX: q1, q2, q3 = Z(t1), Y(t2), X(t3); - case .XYX: q1, q2, q3 = X(t1), Y(t2), X(t3); - case .XZX: q1, q2, q3 = X(t1), Z(t2), X(t3); - case .YXY: q1, q2, q3 = Y(t1), X(t2), Y(t3); - case .YZY: q1, q2, q3 = Y(t1), Z(t2), Y(t3); - case .ZXZ: q1, q2, q3 = Z(t1), X(t2), Z(t3); - case .ZYZ: q1, q2, q3 = Z(t1), Y(t2), Z(t3); + case .XYZ: q1, q2, q3 = X(t1), Y(t2), Z(t3) + case .XZY: q1, q2, q3 = X(t1), Z(t2), Y(t3) + case .YXZ: q1, q2, q3 = Y(t1), X(t2), Z(t3) + case .YZX: q1, q2, q3 = Y(t1), Z(t2), X(t3) + case .ZXY: q1, q2, q3 = Z(t1), X(t2), Y(t3) + case .ZYX: q1, q2, q3 = Z(t1), Y(t2), X(t3) + case .XYX: q1, q2, q3 = X(t1), Y(t2), X(t3) + case .XZX: q1, q2, q3 = X(t1), Z(t2), X(t3) + case .YXY: q1, q2, q3 = Y(t1), X(t2), Y(t3) + case .YZY: q1, q2, q3 = Y(t1), Z(t2), Y(t3) + case .ZXZ: q1, q2, q3 = Z(t1), X(t2), Z(t3) + case .ZYZ: q1, q2, q3 = Z(t1), Y(t2), Z(t3) } - return q1 * (q2 * q3); + return q1 * (q2 * q3) } // Quaternionf64s quaternion_from_euler_angle_x_f64 :: proc(angle_x: f64) -> (q: Quaternionf64) { - return quaternion_angle_axis_f64(angle_x, {1, 0, 0}); + return quaternion_angle_axis_f64(angle_x, {1, 0, 0}) } quaternion_from_euler_angle_y_f64 :: proc(angle_y: f64) -> (q: Quaternionf64) { - return quaternion_angle_axis_f64(angle_y, {0, 1, 0}); + return quaternion_angle_axis_f64(angle_y, {0, 1, 0}) } quaternion_from_euler_angle_z_f64 :: proc(angle_z: f64) -> (q: Quaternionf64) { - return quaternion_angle_axis_f64(angle_z, {0, 0, 1}); + return quaternion_angle_axis_f64(angle_z, {0, 0, 1}) } quaternion_from_pitch_yaw_roll_f64 :: proc(pitch, yaw, roll: f64) -> Quaternionf64 { - a, b, c := pitch, yaw, roll; + a, b, c := pitch, yaw, roll - ca, sa := math.cos(a*0.5), math.sin(a*0.5); - cb, sb := math.cos(b*0.5), math.sin(b*0.5); - cc, sc := math.cos(c*0.5), math.sin(c*0.5); + ca, sa := math.cos(a*0.5), math.sin(a*0.5) + cb, sb := math.cos(b*0.5), math.sin(b*0.5) + cc, sc := math.cos(c*0.5), math.sin(c*0.5) - q: Quaternionf64; - q.x = sa*cb*cc - ca*sb*sc; - q.y = ca*sb*cc + sa*cb*sc; - q.z = ca*cb*sc - sa*sb*cc; - q.w = ca*cb*cc + sa*sb*sc; - return q; + q: Quaternionf64 + q.x = sa*cb*cc - ca*sb*sc + q.y = ca*sb*cc + sa*cb*sc + q.z = ca*cb*sc - sa*sb*cc + q.w = ca*cb*cc + sa*sb*sc + return q } roll_from_quaternion_f64 :: proc(q: Quaternionf64) -> f64 { - return math.atan2(2 * q.x*q.y + q.w*q.z, q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z); + return math.atan2(2 * q.x*q.y + q.w*q.z, q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z) } pitch_from_quaternion_f64 :: proc(q: Quaternionf64) -> f64 { - y := 2 * (q.y*q.z + q.w*q.w); - x := q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z; + y := 2 * (q.y*q.z + q.w*q.w) + x := q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z if abs(x) <= F64_EPSILON && abs(y) <= F64_EPSILON { - return 2 * math.atan2(q.x, q.w); + return 2 * math.atan2(q.x, q.w) } - return math.atan2(y, x); + return math.atan2(y, x) } yaw_from_quaternion_f64 :: proc(q: Quaternionf64) -> f64 { - return math.asin(clamp(-2 * (q.x*q.z - q.w*q.y), -1, 1)); + return math.asin(clamp(-2 * (q.x*q.z - q.w*q.y), -1, 1)) } pitch_yaw_roll_from_quaternion_f64 :: proc(q: Quaternionf64) -> (pitch, yaw, roll: f64) { - pitch = pitch_from_quaternion(q); - yaw = yaw_from_quaternion(q); - roll = roll_from_quaternion(q); - return; + pitch = pitch_from_quaternion(q) + yaw = yaw_from_quaternion(q) + roll = roll_from_quaternion(q) + return } euler_angles_xyz_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { - return euler_angles_xyz_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_xyz_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_yxz_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { - return euler_angles_yxz_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_yxz_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_xzx_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { - return euler_angles_xzx_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_xzx_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_xyx_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { - return euler_angles_xyx_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_xyx_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_yxy_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { - return euler_angles_yxy_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_yxy_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_yzy_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { - return euler_angles_yzy_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_yzy_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_zyz_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { - return euler_angles_zyz_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_zyz_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_zxz_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { - return euler_angles_zxz_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_zxz_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_xzy_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { - return euler_angles_xzy_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_xzy_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_yzx_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { - return euler_angles_yzx_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_yzx_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_zyx_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { - return euler_angles_zyx_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_zyx_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_zxy_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { - return euler_angles_zxy_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_zxy_from_matrix4(matrix4_from_quaternion(q)) } @@ -211,524 +211,524 @@ euler_angles_zxy_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f matrix3_from_euler_angle_x_f64 :: proc(angle_x: f64) -> (m: Matrix3f64) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - m[0][0] = 1; - m[1][1] = +cos_x; - m[2][1] = +sin_x; - m[1][2] = -sin_x; - m[2][2] = +cos_x; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + m[0][0] = 1 + m[1][1] = +cos_x + m[2][1] = +sin_x + m[1][2] = -sin_x + m[2][2] = +cos_x + return } matrix3_from_euler_angle_y_f64 :: proc(angle_y: f64) -> (m: Matrix3f64) { - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = +cos_y; - m[2][0] = -sin_y; - m[1][1] = 1; - m[0][2] = +sin_y; - m[2][2] = +cos_y; - return; + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = +cos_y + m[2][0] = -sin_y + m[1][1] = 1 + m[0][2] = +sin_y + m[2][2] = +cos_y + return } matrix3_from_euler_angle_z_f64 :: proc(angle_z: f64) -> (m: Matrix3f64) { - cos_z, sin_z := math.cos(angle_z), math.sin(angle_z); - m[0][0] = +cos_z; - m[1][0] = +sin_z; - m[1][1] = +cos_z; - m[0][1] = -sin_z; - m[2][2] = 1; - return; + cos_z, sin_z := math.cos(angle_z), math.sin(angle_z) + m[0][0] = +cos_z + m[1][0] = +sin_z + m[1][1] = +cos_z + m[0][1] = -sin_z + m[2][2] = 1 + return } matrix3_from_derived_euler_angle_x_f64 :: proc(angle_x: f64, angular_velocity_x: f64) -> (m: Matrix3f64) { - cos_x := math.cos(angle_x) * angular_velocity_x; - sin_x := math.sin(angle_x) * angular_velocity_x; - m[0][0] = 1; - m[1][1] = +cos_x; - m[2][1] = +sin_x; - m[1][2] = -sin_x; - m[2][2] = +cos_x; - return; + cos_x := math.cos(angle_x) * angular_velocity_x + sin_x := math.sin(angle_x) * angular_velocity_x + m[0][0] = 1 + m[1][1] = +cos_x + m[2][1] = +sin_x + m[1][2] = -sin_x + m[2][2] = +cos_x + return } matrix3_from_derived_euler_angle_y_f64 :: proc(angle_y: f64, angular_velocity_y: f64) -> (m: Matrix3f64) { - cos_y := math.cos(angle_y) * angular_velocity_y; - sin_y := math.sin(angle_y) * angular_velocity_y; - m[0][0] = +cos_y; - m[2][0] = -sin_y; - m[1][1] = 1; - m[0][2] = +sin_y; - m[2][2] = +cos_y; - return; + cos_y := math.cos(angle_y) * angular_velocity_y + sin_y := math.sin(angle_y) * angular_velocity_y + m[0][0] = +cos_y + m[2][0] = -sin_y + m[1][1] = 1 + m[0][2] = +sin_y + m[2][2] = +cos_y + return } matrix3_from_derived_euler_angle_z_f64 :: proc(angle_z: f64, angular_velocity_z: f64) -> (m: Matrix3f64) { - cos_z := math.cos(angle_z) * angular_velocity_z; - sin_z := math.sin(angle_z) * angular_velocity_z; - m[0][0] = +cos_z; - m[1][0] = +sin_z; - m[1][1] = +cos_z; - m[0][1] = -sin_z; - m[2][2] = 1; - return; + cos_z := math.cos(angle_z) * angular_velocity_z + sin_z := math.sin(angle_z) * angular_velocity_z + m[0][0] = +cos_z + m[1][0] = +sin_z + m[1][1] = +cos_z + m[0][1] = -sin_z + m[2][2] = 1 + return } matrix3_from_euler_angles_xy_f64 :: proc(angle_x, angle_y: f64) -> (m: Matrix3f64) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = cos_y; - m[1][0] = -sin_x * - sin_y; - m[2][0] = -cos_x * - sin_y; - m[1][1] = cos_x; - m[2][1] = sin_x; - m[0][2] = sin_y; - m[1][2] = -sin_x * cos_y; - m[2][2] = cos_x * cos_y; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = cos_y + m[1][0] = -sin_x * - sin_y + m[2][0] = -cos_x * - sin_y + m[1][1] = cos_x + m[2][1] = sin_x + m[0][2] = sin_y + m[1][2] = -sin_x * cos_y + m[2][2] = cos_x * cos_y + return } matrix3_from_euler_angles_yx_f64 :: proc(angle_y, angle_x: f64) -> (m: Matrix3f64) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = cos_y; - m[2][0] = -sin_y; - m[0][1] = sin_y*sin_x; - m[1][1] = cos_x; - m[2][1] = cos_y*sin_x; - m[0][2] = sin_y*cos_x; - m[1][2] = -sin_x; - m[2][2] = cos_y*cos_x; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = cos_y + m[2][0] = -sin_y + m[0][1] = sin_y*sin_x + m[1][1] = cos_x + m[2][1] = cos_y*sin_x + m[0][2] = sin_y*cos_x + m[1][2] = -sin_x + m[2][2] = cos_y*cos_x + return } matrix3_from_euler_angles_xz_f64 :: proc(angle_x, angle_z: f64) -> (m: Matrix3f64) { - return mul(matrix3_from_euler_angle_x(angle_x), matrix3_from_euler_angle_z(angle_z)); + return mul(matrix3_from_euler_angle_x(angle_x), matrix3_from_euler_angle_z(angle_z)) } matrix3_from_euler_angles_zx_f64 :: proc(angle_z, angle_x: f64) -> (m: Matrix3f64) { - return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_x(angle_x)); + return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_x(angle_x)) } matrix3_from_euler_angles_yz_f64 :: proc(angle_y, angle_z: f64) -> (m: Matrix3f64) { - return mul(matrix3_from_euler_angle_y(angle_y), matrix3_from_euler_angle_z(angle_z)); + return mul(matrix3_from_euler_angle_y(angle_y), matrix3_from_euler_angle_z(angle_z)) } matrix3_from_euler_angles_zy_f64 :: proc(angle_z, angle_y: f64) -> (m: Matrix3f64) { - return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_y(angle_y)); + return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_y(angle_y)) } matrix3_from_euler_angles_xyz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { - c1 := math.cos(-t1); - c2 := math.cos(-t2); - c3 := math.cos(-t3); - s1 := math.sin(-t1); - s2 := math.sin(-t2); - s3 := math.sin(-t3); - - m[0][0] = c2 * c3; - m[0][1] =-c1 * s3 + s1 * s2 * c3; - m[0][2] = s1 * s3 + c1 * s2 * c3; - m[1][0] = c2 * s3; - m[1][1] = c1 * c3 + s1 * s2 * s3; - m[1][2] =-s1 * c3 + c1 * s2 * s3; - m[2][0] =-s2; - m[2][1] = s1 * c2; - m[2][2] = c1 * c2; - return; + c1 := math.cos(-t1) + c2 := math.cos(-t2) + c3 := math.cos(-t3) + s1 := math.sin(-t1) + s2 := math.sin(-t2) + s3 := math.sin(-t3) + + m[0][0] = c2 * c3 + m[0][1] =-c1 * s3 + s1 * s2 * c3 + m[0][2] = s1 * s3 + c1 * s2 * c3 + m[1][0] = c2 * s3 + m[1][1] = c1 * c3 + s1 * s2 * s3 + m[1][2] =-s1 * c3 + c1 * s2 * s3 + m[2][0] =-s2 + m[2][1] = s1 * c2 + m[2][2] = c1 * c2 + return } matrix3_from_euler_angles_yxz_f64 :: proc(yaw, pitch, roll: f64) -> (m: Matrix3f64) { - ch := math.cos(yaw); - sh := math.sin(yaw); - cp := math.cos(pitch); - sp := math.sin(pitch); - cb := math.cos(roll); - sb := math.sin(roll); - - m[0][0] = ch * cb + sh * sp * sb; - m[0][1] = sb * cp; - m[0][2] = -sh * cb + ch * sp * sb; - m[1][0] = -ch * sb + sh * sp * cb; - m[1][1] = cb * cp; - m[1][2] = sb * sh + ch * sp * cb; - m[2][0] = sh * cp; - m[2][1] = -sp; - m[2][2] = ch * cp; - return; + ch := math.cos(yaw) + sh := math.sin(yaw) + cp := math.cos(pitch) + sp := math.sin(pitch) + cb := math.cos(roll) + sb := math.sin(roll) + + m[0][0] = ch * cb + sh * sp * sb + m[0][1] = sb * cp + m[0][2] = -sh * cb + ch * sp * sb + m[1][0] = -ch * sb + sh * sp * cb + m[1][1] = cb * cp + m[1][2] = sb * sh + ch * sp * cb + m[2][0] = sh * cp + m[2][1] = -sp + m[2][2] = ch * cp + return } matrix3_from_euler_angles_xzx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2; - m[0][1] = c1 * s2; - m[0][2] = s1 * s2; - m[1][0] =-c3 * s2; - m[1][1] = c1 * c2 * c3 - s1 * s3; - m[1][2] = c1 * s3 + c2 * c3 * s1; - m[2][0] = s2 * s3; - m[2][1] =-c3 * s1 - c1 * c2 * s3; - m[2][2] = c1 * c3 - c2 * s1 * s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 + m[0][1] = c1 * s2 + m[0][2] = s1 * s2 + m[1][0] =-c3 * s2 + m[1][1] = c1 * c2 * c3 - s1 * s3 + m[1][2] = c1 * s3 + c2 * c3 * s1 + m[2][0] = s2 * s3 + m[2][1] =-c3 * s1 - c1 * c2 * s3 + m[2][2] = c1 * c3 - c2 * s1 * s3 + return } matrix3_from_euler_angles_xyx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2; - m[0][1] = s1 * s2; - m[0][2] =-c1 * s2; - m[1][0] = s2 * s3; - m[1][1] = c1 * c3 - c2 * s1 * s3; - m[1][2] = c3 * s1 + c1 * c2 * s3; - m[2][0] = c3 * s2; - m[2][1] =-c1 * s3 - c2 * c3 * s1; - m[2][2] = c1 * c2 * c3 - s1 * s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 + m[0][1] = s1 * s2 + m[0][2] =-c1 * s2 + m[1][0] = s2 * s3 + m[1][1] = c1 * c3 - c2 * s1 * s3 + m[1][2] = c3 * s1 + c1 * c2 * s3 + m[2][0] = c3 * s2 + m[2][1] =-c1 * s3 - c2 * c3 * s1 + m[2][2] = c1 * c2 * c3 - s1 * s3 + return } matrix3_from_euler_angles_yxy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - c2 * s1 * s3; - m[0][1] = s2* s3; - m[0][2] =-c3 * s1 - c1 * c2 * s3; - m[1][0] = s1 * s2; - m[1][1] = c2; - m[1][2] = c1 * s2; - m[2][0] = c1 * s3 + c2 * c3 * s1; - m[2][1] =-c3 * s2; - m[2][2] = c1 * c2 * c3 - s1 * s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - c2 * s1 * s3 + m[0][1] = s2* s3 + m[0][2] =-c3 * s1 - c1 * c2 * s3 + m[1][0] = s1 * s2 + m[1][1] = c2 + m[1][2] = c1 * s2 + m[2][0] = c1 * s3 + c2 * c3 * s1 + m[2][1] =-c3 * s2 + m[2][2] = c1 * c2 * c3 - s1 * s3 + return } matrix3_from_euler_angles_yzy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2 * c3 - s1 * s3; - m[0][1] = c3 * s2; - m[0][2] =-c1 * s3 - c2 * c3 * s1; - m[1][0] =-c1 * s2; - m[1][1] = c2; - m[1][2] = s1 * s2; - m[2][0] = c3 * s1 + c1 * c2 * s3; - m[2][1] = s2 * s3; - m[2][2] = c1 * c3 - c2 * s1 * s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 * c3 - s1 * s3 + m[0][1] = c3 * s2 + m[0][2] =-c1 * s3 - c2 * c3 * s1 + m[1][0] =-c1 * s2 + m[1][1] = c2 + m[1][2] = s1 * s2 + m[2][0] = c3 * s1 + c1 * c2 * s3 + m[2][1] = s2 * s3 + m[2][2] = c1 * c3 - c2 * s1 * s3 + return } matrix3_from_euler_angles_zyz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2 * c3 - s1 * s3; - m[0][1] = c1 * s3 + c2 * c3 * s1; - m[0][2] =-c3 * s2; - m[1][0] =-c3 * s1 - c1 * c2 * s3; - m[1][1] = c1 * c3 - c2 * s1 * s3; - m[1][2] = s2 * s3; - m[2][0] = c1 * s2; - m[2][1] = s1 * s2; - m[2][2] = c2; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 * c3 - s1 * s3 + m[0][1] = c1 * s3 + c2 * c3 * s1 + m[0][2] =-c3 * s2 + m[1][0] =-c3 * s1 - c1 * c2 * s3 + m[1][1] = c1 * c3 - c2 * s1 * s3 + m[1][2] = s2 * s3 + m[2][0] = c1 * s2 + m[2][1] = s1 * s2 + m[2][2] = c2 + return } matrix3_from_euler_angles_zxz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - c2 * s1 * s3; - m[0][1] = c3 * s1 + c1 * c2 * s3; - m[0][2] = s2 *s3; - m[1][0] =-c1 * s3 - c2 * c3 * s1; - m[1][1] = c1 * c2 * c3 - s1 * s3; - m[1][2] = c3 * s2; - m[2][0] = s1 * s2; - m[2][1] =-c1 * s2; - m[2][2] = c2; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - c2 * s1 * s3 + m[0][1] = c3 * s1 + c1 * c2 * s3 + m[0][2] = s2 *s3 + m[1][0] =-c1 * s3 - c2 * c3 * s1 + m[1][1] = c1 * c2 * c3 - s1 * s3 + m[1][2] = c3 * s2 + m[2][0] = s1 * s2 + m[2][1] =-c1 * s2 + m[2][2] = c2 + return } matrix3_from_euler_angles_xzy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2 * c3; - m[0][1] = s1 * s3 + c1 * c3 * s2; - m[0][2] = c3 * s1 * s2 - c1 * s3; - m[1][0] =-s2; - m[1][1] = c1 * c2; - m[1][2] = c2 * s1; - m[2][0] = c2 * s3; - m[2][1] = c1 * s2 * s3 - c3 * s1; - m[2][2] = c1 * c3 + s1 * s2 *s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 * c3 + m[0][1] = s1 * s3 + c1 * c3 * s2 + m[0][2] = c3 * s1 * s2 - c1 * s3 + m[1][0] =-s2 + m[1][1] = c1 * c2 + m[1][2] = c2 * s1 + m[2][0] = c2 * s3 + m[2][1] = c1 * s2 * s3 - c3 * s1 + m[2][2] = c1 * c3 + s1 * s2 *s3 + return } matrix3_from_euler_angles_yzx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2; - m[0][1] = s2; - m[0][2] =-c2 * s1; - m[1][0] = s1 * s3 - c1 * c3 * s2; - m[1][1] = c2 * c3; - m[1][2] = c1 * s3 + c3 * s1 * s2; - m[2][0] = c3 * s1 + c1 * s2 * s3; - m[2][1] =-c2 * s3; - m[2][2] = c1 * c3 - s1 * s2 * s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 + m[0][1] = s2 + m[0][2] =-c2 * s1 + m[1][0] = s1 * s3 - c1 * c3 * s2 + m[1][1] = c2 * c3 + m[1][2] = c1 * s3 + c3 * s1 * s2 + m[2][0] = c3 * s1 + c1 * s2 * s3 + m[2][1] =-c2 * s3 + m[2][2] = c1 * c3 - s1 * s2 * s3 + return } matrix3_from_euler_angles_zyx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2; - m[0][1] = c2 * s1; - m[0][2] =-s2; - m[1][0] = c1 * s2 * s3 - c3 * s1; - m[1][1] = c1 * c3 + s1 * s2 * s3; - m[1][2] = c2 * s3; - m[2][0] = s1 * s3 + c1 * c3 * s2; - m[2][1] = c3 * s1 * s2 - c1 * s3; - m[2][2] = c2 * c3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 + m[0][1] = c2 * s1 + m[0][2] =-s2 + m[1][0] = c1 * s2 * s3 - c3 * s1 + m[1][1] = c1 * c3 + s1 * s2 * s3 + m[1][2] = c2 * s3 + m[2][0] = s1 * s3 + c1 * c3 * s2 + m[2][1] = c3 * s1 * s2 - c1 * s3 + m[2][2] = c2 * c3 + return } matrix3_from_euler_angles_zxy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - s1 * s2 * s3; - m[0][1] = c3 * s1 + c1 * s2 * s3; - m[0][2] =-c2 * s3; - m[1][0] =-c2 * s1; - m[1][1] = c1 * c2; - m[1][2] = s2; - m[2][0] = c1 * s3 + c3 * s1 * s2; - m[2][1] = s1 * s3 - c1 * c3 * s2; - m[2][2] = c2 * c3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - s1 * s2 * s3 + m[0][1] = c3 * s1 + c1 * s2 * s3 + m[0][2] =-c2 * s3 + m[1][0] =-c2 * s1 + m[1][1] = c1 * c2 + m[1][2] = s2 + m[2][0] = c1 * s3 + c3 * s1 * s2 + m[2][1] = s1 * s3 - c1 * c3 * s2 + m[2][2] = c2 * c3 + return } matrix3_from_yaw_pitch_roll_f64 :: proc(yaw, pitch, roll: f64) -> (m: Matrix3f64) { - ch := math.cos(yaw); - sh := math.sin(yaw); - cp := math.cos(pitch); - sp := math.sin(pitch); - cb := math.cos(roll); - sb := math.sin(roll); - - m[0][0] = ch * cb + sh * sp * sb; - m[0][1] = sb * cp; - m[0][2] = -sh * cb + ch * sp * sb; - m[1][0] = -ch * sb + sh * sp * cb; - m[1][1] = cb * cp; - m[1][2] = sb * sh + ch * sp * cb; - m[2][0] = sh * cp; - m[2][1] = -sp; - m[2][2] = ch * cp; - return m; + ch := math.cos(yaw) + sh := math.sin(yaw) + cp := math.cos(pitch) + sp := math.sin(pitch) + cb := math.cos(roll) + sb := math.sin(roll) + + m[0][0] = ch * cb + sh * sp * sb + m[0][1] = sb * cp + m[0][2] = -sh * cb + ch * sp * sb + m[1][0] = -ch * sb + sh * sp * cb + m[1][1] = cb * cp + m[1][2] = sb * sh + ch * sp * cb + m[2][0] = sh * cp + m[2][1] = -sp + m[2][2] = ch * cp + return m } euler_angles_xyz_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[2][1], m[2][2]); - C2 := math.sqrt(m[0][0]*m[0][0] + m[1][0]*m[1][0]); - T2 := math.atan2(-m[2][0], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[0][2] - C1*m[0][1], C1*m[1][1] - S1*m[1][2]); - t1 = -T1; - t2 = -T2; - t3 = -T3; - return; + T1 := math.atan2(m[2][1], m[2][2]) + C2 := math.sqrt(m[0][0]*m[0][0] + m[1][0]*m[1][0]) + T2 := math.atan2(-m[2][0], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[0][2] - C1*m[0][1], C1*m[1][1] - S1*m[1][2]) + t1 = -T1 + t2 = -T2 + t3 = -T3 + return } euler_angles_yxz_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[2][0], m[2][2]); - C2 := math.sqrt(m[0][1]*m[0][1] + m[1][1]*m[1][1]); - T2 := math.atan2(-m[2][1], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[1][2] - C1*m[1][0], C1*m[0][0] - S1*m[0][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][0], m[2][2]) + C2 := math.sqrt(m[0][1]*m[0][1] + m[1][1]*m[1][1]) + T2 := math.atan2(-m[2][1], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[1][2] - C1*m[1][0], C1*m[0][0] - S1*m[0][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xzx_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[0][2], m[0][1]); - S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]); - T2 := math.atan2(S2, m[0][0]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[1][2] - S1*m[1][1], C1*m[2][2] - S1*m[2][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][2], m[0][1]) + S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]) + T2 := math.atan2(S2, m[0][0]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[1][2] - S1*m[1][1], C1*m[2][2] - S1*m[2][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xyx_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[0][1], -m[0][2]); - S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]); - T2 := math.atan2(S2, m[0][0]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-C1*m[2][1] - S1*m[2][2], C1*m[1][1] + S1*m[1][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][1], -m[0][2]) + S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]) + T2 := math.atan2(S2, m[0][0]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-C1*m[2][1] - S1*m[2][2], C1*m[1][1] + S1*m[1][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yxy_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[1][0], m[1][2]); - S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]); - T2 := math.atan2(S2, m[1][1]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[2][0] - S1*m[2][2], C1*m[0][0] - S1*m[0][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][0], m[1][2]) + S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]) + T2 := math.atan2(S2, m[1][1]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[2][0] - S1*m[2][2], C1*m[0][0] - S1*m[0][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yzy_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[1][2], -m[1][0]); - S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]); - T2 := math.atan2(S2, m[1][1]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-S1*m[0][0] - C1*m[0][2], S1*m[2][0] + C1*m[2][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][2], -m[1][0]) + S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]) + T2 := math.atan2(S2, m[1][1]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-S1*m[0][0] - C1*m[0][2], S1*m[2][0] + C1*m[2][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zyz_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[2][1], m[2][0]); - S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]); - T2 := math.atan2(S2, m[2][2]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[0][1] - S1*m[0][0], C1*m[1][1] - S1*m[1][0]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][1], m[2][0]) + S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]) + T2 := math.atan2(S2, m[2][2]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[0][1] - S1*m[0][0], C1*m[1][1] - S1*m[1][0]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zxz_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[2][0], -m[2][1]); - S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]); - T2 := math.atan2(S2, m[2][2]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-C1*m[1][0] - S1*m[1][1], C1*m[0][0] + S1*m[0][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][0], -m[2][1]) + S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]) + T2 := math.atan2(S2, m[2][2]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-C1*m[1][0] - S1*m[1][1], C1*m[0][0] + S1*m[0][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xzy_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[1][2], m[1][1]); - C2 := math.sqrt(m[0][0]*m[0][0] + m[2][0]*m[2][0]); - T2 := math.atan2(-m[1][0], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[0][1] - C1*m[0][2], C1*m[2][2] - S1*m[2][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][2], m[1][1]) + C2 := math.sqrt(m[0][0]*m[0][0] + m[2][0]*m[2][0]) + T2 := math.atan2(-m[1][0], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[0][1] - C1*m[0][2], C1*m[2][2] - S1*m[2][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yzx_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(-m[0][2], m[0][0]); - C2 := math.sqrt(m[1][1]*m[1][1] + m[2][1]*m[2][1]); - T2 := math.atan2(m[0][1], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[1][0] + C1*m[1][2], S1*m[2][0] + C1*m[2][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(-m[0][2], m[0][0]) + C2 := math.sqrt(m[1][1]*m[1][1] + m[2][1]*m[2][1]) + T2 := math.atan2(m[0][1], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[1][0] + C1*m[1][2], S1*m[2][0] + C1*m[2][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zyx_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[0][1], m[0][0]); - C2 := math.sqrt(m[1][2]*m[1][2] + m[2][2]*m[2][2]); - T2 := math.atan2(-m[0][2], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[2][0] - C1*m[2][1], C1*m[1][1] - S1*m[1][0]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][1], m[0][0]) + C2 := math.sqrt(m[1][2]*m[1][2] + m[2][2]*m[2][2]) + T2 := math.atan2(-m[0][2], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[2][0] - C1*m[2][1], C1*m[1][1] - S1*m[1][0]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zxy_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(-m[1][0], m[1][1]); - C2 := math.sqrt(m[0][2]*m[0][2] + m[2][2]*m[2][2]); - T2 := math.atan2(m[1][2], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[2][0] + S1*m[2][1], C1*m[0][0] + S1*m[0][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(-m[1][0], m[1][1]) + C2 := math.sqrt(m[0][2]*m[0][2] + m[2][2]*m[2][2]) + T2 := math.atan2(m[1][2], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[2][0] + S1*m[2][1], C1*m[0][0] + S1*m[0][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } @@ -736,621 +736,621 @@ euler_angles_zxy_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { matrix4_from_euler_angle_x_f64 :: proc(angle_x: f64) -> (m: Matrix4f64) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - m[0][0] = 1; - m[1][1] = +cos_x; - m[2][1] = +sin_x; - m[1][2] = -sin_x; - m[2][2] = +cos_x; - m[3][3] = 1; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + m[0][0] = 1 + m[1][1] = +cos_x + m[2][1] = +sin_x + m[1][2] = -sin_x + m[2][2] = +cos_x + m[3][3] = 1 + return } matrix4_from_euler_angle_y_f64 :: proc(angle_y: f64) -> (m: Matrix4f64) { - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = +cos_y; - m[2][0] = -sin_y; - m[1][1] = 1; - m[0][2] = +sin_y; - m[2][2] = +cos_y; - m[3][3] = 1; - return; + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = +cos_y + m[2][0] = -sin_y + m[1][1] = 1 + m[0][2] = +sin_y + m[2][2] = +cos_y + m[3][3] = 1 + return } matrix4_from_euler_angle_z_f64 :: proc(angle_z: f64) -> (m: Matrix4f64) { - cos_z, sin_z := math.cos(angle_z), math.sin(angle_z); - m[0][0] = +cos_z; - m[1][0] = +sin_z; - m[1][1] = +cos_z; - m[0][1] = -sin_z; - m[2][2] = 1; - m[3][3] = 1; - return; + cos_z, sin_z := math.cos(angle_z), math.sin(angle_z) + m[0][0] = +cos_z + m[1][0] = +sin_z + m[1][1] = +cos_z + m[0][1] = -sin_z + m[2][2] = 1 + m[3][3] = 1 + return } matrix4_from_derived_euler_angle_x_f64 :: proc(angle_x: f64, angular_velocity_x: f64) -> (m: Matrix4f64) { - cos_x := math.cos(angle_x) * angular_velocity_x; - sin_x := math.sin(angle_x) * angular_velocity_x; - m[0][0] = 1; - m[1][1] = +cos_x; - m[2][1] = +sin_x; - m[1][2] = -sin_x; - m[2][2] = +cos_x; - m[3][3] = 1; - return; + cos_x := math.cos(angle_x) * angular_velocity_x + sin_x := math.sin(angle_x) * angular_velocity_x + m[0][0] = 1 + m[1][1] = +cos_x + m[2][1] = +sin_x + m[1][2] = -sin_x + m[2][2] = +cos_x + m[3][3] = 1 + return } matrix4_from_derived_euler_angle_y_f64 :: proc(angle_y: f64, angular_velocity_y: f64) -> (m: Matrix4f64) { - cos_y := math.cos(angle_y) * angular_velocity_y; - sin_y := math.sin(angle_y) * angular_velocity_y; - m[0][0] = +cos_y; - m[2][0] = -sin_y; - m[1][1] = 1; - m[0][2] = +sin_y; - m[2][2] = +cos_y; - m[3][3] = 1; - return; + cos_y := math.cos(angle_y) * angular_velocity_y + sin_y := math.sin(angle_y) * angular_velocity_y + m[0][0] = +cos_y + m[2][0] = -sin_y + m[1][1] = 1 + m[0][2] = +sin_y + m[2][2] = +cos_y + m[3][3] = 1 + return } matrix4_from_derived_euler_angle_z_f64 :: proc(angle_z: f64, angular_velocity_z: f64) -> (m: Matrix4f64) { - cos_z := math.cos(angle_z) * angular_velocity_z; - sin_z := math.sin(angle_z) * angular_velocity_z; - m[0][0] = +cos_z; - m[1][0] = +sin_z; - m[1][1] = +cos_z; - m[0][1] = -sin_z; - m[2][2] = 1; - m[3][3] = 1; - return; + cos_z := math.cos(angle_z) * angular_velocity_z + sin_z := math.sin(angle_z) * angular_velocity_z + m[0][0] = +cos_z + m[1][0] = +sin_z + m[1][1] = +cos_z + m[0][1] = -sin_z + m[2][2] = 1 + m[3][3] = 1 + return } matrix4_from_euler_angles_xy_f64 :: proc(angle_x, angle_y: f64) -> (m: Matrix4f64) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = cos_y; - m[1][0] = -sin_x * - sin_y; - m[2][0] = -cos_x * - sin_y; - m[1][1] = cos_x; - m[2][1] = sin_x; - m[0][2] = sin_y; - m[1][2] = -sin_x * cos_y; - m[2][2] = cos_x * cos_y; - m[3][3] = 1; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = cos_y + m[1][0] = -sin_x * - sin_y + m[2][0] = -cos_x * - sin_y + m[1][1] = cos_x + m[2][1] = sin_x + m[0][2] = sin_y + m[1][2] = -sin_x * cos_y + m[2][2] = cos_x * cos_y + m[3][3] = 1 + return } matrix4_from_euler_angles_yx_f64 :: proc(angle_y, angle_x: f64) -> (m: Matrix4f64) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = cos_y; - m[2][0] = -sin_y; - m[0][1] = sin_y*sin_x; - m[1][1] = cos_x; - m[2][1] = cos_y*sin_x; - m[0][2] = sin_y*cos_x; - m[1][2] = -sin_x; - m[2][2] = cos_y*cos_x; - m[3][3] = 1; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = cos_y + m[2][0] = -sin_y + m[0][1] = sin_y*sin_x + m[1][1] = cos_x + m[2][1] = cos_y*sin_x + m[0][2] = sin_y*cos_x + m[1][2] = -sin_x + m[2][2] = cos_y*cos_x + m[3][3] = 1 + return } matrix4_from_euler_angles_xz_f64 :: proc(angle_x, angle_z: f64) -> (m: Matrix4f64) { - return mul(matrix4_from_euler_angle_x(angle_x), matrix4_from_euler_angle_z(angle_z)); + return mul(matrix4_from_euler_angle_x(angle_x), matrix4_from_euler_angle_z(angle_z)) } matrix4_from_euler_angles_zx_f64 :: proc(angle_z, angle_x: f64) -> (m: Matrix4f64) { - return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_x(angle_x)); + return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_x(angle_x)) } matrix4_from_euler_angles_yz_f64 :: proc(angle_y, angle_z: f64) -> (m: Matrix4f64) { - return mul(matrix4_from_euler_angle_y(angle_y), matrix4_from_euler_angle_z(angle_z)); + return mul(matrix4_from_euler_angle_y(angle_y), matrix4_from_euler_angle_z(angle_z)) } matrix4_from_euler_angles_zy_f64 :: proc(angle_z, angle_y: f64) -> (m: Matrix4f64) { - return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_y(angle_y)); + return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_y(angle_y)) } matrix4_from_euler_angles_xyz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { - c1 := math.cos(-t1); - c2 := math.cos(-t2); - c3 := math.cos(-t3); - s1 := math.sin(-t1); - s2 := math.sin(-t2); - s3 := math.sin(-t3); - - m[0][0] = c2 * c3; - m[0][1] =-c1 * s3 + s1 * s2 * c3; - m[0][2] = s1 * s3 + c1 * s2 * c3; - m[0][3] = 0; - m[1][0] = c2 * s3; - m[1][1] = c1 * c3 + s1 * s2 * s3; - m[1][2] =-s1 * c3 + c1 * s2 * s3; - m[1][3] = 0; - m[2][0] =-s2; - m[2][1] = s1 * c2; - m[2][2] = c1 * c2; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(-t1) + c2 := math.cos(-t2) + c3 := math.cos(-t3) + s1 := math.sin(-t1) + s2 := math.sin(-t2) + s3 := math.sin(-t3) + + m[0][0] = c2 * c3 + m[0][1] =-c1 * s3 + s1 * s2 * c3 + m[0][2] = s1 * s3 + c1 * s2 * c3 + m[0][3] = 0 + m[1][0] = c2 * s3 + m[1][1] = c1 * c3 + s1 * s2 * s3 + m[1][2] =-s1 * c3 + c1 * s2 * s3 + m[1][3] = 0 + m[2][0] =-s2 + m[2][1] = s1 * c2 + m[2][2] = c1 * c2 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_yxz_f64 :: proc(yaw, pitch, roll: f64) -> (m: Matrix4f64) { - ch := math.cos(yaw); - sh := math.sin(yaw); - cp := math.cos(pitch); - sp := math.sin(pitch); - cb := math.cos(roll); - sb := math.sin(roll); - - m[0][0] = ch * cb + sh * sp * sb; - m[0][1] = sb * cp; - m[0][2] = -sh * cb + ch * sp * sb; - m[0][3] = 0; - m[1][0] = -ch * sb + sh * sp * cb; - m[1][1] = cb * cp; - m[1][2] = sb * sh + ch * sp * cb; - m[1][3] = 0; - m[2][0] = sh * cp; - m[2][1] = -sp; - m[2][2] = ch * cp; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + ch := math.cos(yaw) + sh := math.sin(yaw) + cp := math.cos(pitch) + sp := math.sin(pitch) + cb := math.cos(roll) + sb := math.sin(roll) + + m[0][0] = ch * cb + sh * sp * sb + m[0][1] = sb * cp + m[0][2] = -sh * cb + ch * sp * sb + m[0][3] = 0 + m[1][0] = -ch * sb + sh * sp * cb + m[1][1] = cb * cp + m[1][2] = sb * sh + ch * sp * cb + m[1][3] = 0 + m[2][0] = sh * cp + m[2][1] = -sp + m[2][2] = ch * cp + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_xzx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2; - m[0][1] = c1 * s2; - m[0][2] = s1 * s2; - m[0][3] = 0; - m[1][0] =-c3 * s2; - m[1][1] = c1 * c2 * c3 - s1 * s3; - m[1][2] = c1 * s3 + c2 * c3 * s1; - m[1][3] = 0; - m[2][0] = s2 * s3; - m[2][1] =-c3 * s1 - c1 * c2 * s3; - m[2][2] = c1 * c3 - c2 * s1 * s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 + m[0][1] = c1 * s2 + m[0][2] = s1 * s2 + m[0][3] = 0 + m[1][0] =-c3 * s2 + m[1][1] = c1 * c2 * c3 - s1 * s3 + m[1][2] = c1 * s3 + c2 * c3 * s1 + m[1][3] = 0 + m[2][0] = s2 * s3 + m[2][1] =-c3 * s1 - c1 * c2 * s3 + m[2][2] = c1 * c3 - c2 * s1 * s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_xyx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2; - m[0][1] = s1 * s2; - m[0][2] =-c1 * s2; - m[0][3] = 0; - m[1][0] = s2 * s3; - m[1][1] = c1 * c3 - c2 * s1 * s3; - m[1][2] = c3 * s1 + c1 * c2 * s3; - m[1][3] = 0; - m[2][0] = c3 * s2; - m[2][1] =-c1 * s3 - c2 * c3 * s1; - m[2][2] = c1 * c2 * c3 - s1 * s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 + m[0][1] = s1 * s2 + m[0][2] =-c1 * s2 + m[0][3] = 0 + m[1][0] = s2 * s3 + m[1][1] = c1 * c3 - c2 * s1 * s3 + m[1][2] = c3 * s1 + c1 * c2 * s3 + m[1][3] = 0 + m[2][0] = c3 * s2 + m[2][1] =-c1 * s3 - c2 * c3 * s1 + m[2][2] = c1 * c2 * c3 - s1 * s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_yxy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - c2 * s1 * s3; - m[0][1] = s2* s3; - m[0][2] =-c3 * s1 - c1 * c2 * s3; - m[0][3] = 0; - m[1][0] = s1 * s2; - m[1][1] = c2; - m[1][2] = c1 * s2; - m[1][3] = 0; - m[2][0] = c1 * s3 + c2 * c3 * s1; - m[2][1] =-c3 * s2; - m[2][2] = c1 * c2 * c3 - s1 * s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - c2 * s1 * s3 + m[0][1] = s2* s3 + m[0][2] =-c3 * s1 - c1 * c2 * s3 + m[0][3] = 0 + m[1][0] = s1 * s2 + m[1][1] = c2 + m[1][2] = c1 * s2 + m[1][3] = 0 + m[2][0] = c1 * s3 + c2 * c3 * s1 + m[2][1] =-c3 * s2 + m[2][2] = c1 * c2 * c3 - s1 * s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_yzy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2 * c3 - s1 * s3; - m[0][1] = c3 * s2; - m[0][2] =-c1 * s3 - c2 * c3 * s1; - m[0][3] = 0; - m[1][0] =-c1 * s2; - m[1][1] = c2; - m[1][2] = s1 * s2; - m[1][3] = 0; - m[2][0] = c3 * s1 + c1 * c2 * s3; - m[2][1] = s2 * s3; - m[2][2] = c1 * c3 - c2 * s1 * s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 * c3 - s1 * s3 + m[0][1] = c3 * s2 + m[0][2] =-c1 * s3 - c2 * c3 * s1 + m[0][3] = 0 + m[1][0] =-c1 * s2 + m[1][1] = c2 + m[1][2] = s1 * s2 + m[1][3] = 0 + m[2][0] = c3 * s1 + c1 * c2 * s3 + m[2][1] = s2 * s3 + m[2][2] = c1 * c3 - c2 * s1 * s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_zyz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2 * c3 - s1 * s3; - m[0][1] = c1 * s3 + c2 * c3 * s1; - m[0][2] =-c3 * s2; - m[0][3] = 0; - m[1][0] =-c3 * s1 - c1 * c2 * s3; - m[1][1] = c1 * c3 - c2 * s1 * s3; - m[1][2] = s2 * s3; - m[1][3] = 0; - m[2][0] = c1 * s2; - m[2][1] = s1 * s2; - m[2][2] = c2; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 * c3 - s1 * s3 + m[0][1] = c1 * s3 + c2 * c3 * s1 + m[0][2] =-c3 * s2 + m[0][3] = 0 + m[1][0] =-c3 * s1 - c1 * c2 * s3 + m[1][1] = c1 * c3 - c2 * s1 * s3 + m[1][2] = s2 * s3 + m[1][3] = 0 + m[2][0] = c1 * s2 + m[2][1] = s1 * s2 + m[2][2] = c2 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_zxz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - c2 * s1 * s3; - m[0][1] = c3 * s1 + c1 * c2 * s3; - m[0][2] = s2 *s3; - m[0][3] = 0; - m[1][0] =-c1 * s3 - c2 * c3 * s1; - m[1][1] = c1 * c2 * c3 - s1 * s3; - m[1][2] = c3 * s2; - m[1][3] = 0; - m[2][0] = s1 * s2; - m[2][1] =-c1 * s2; - m[2][2] = c2; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - c2 * s1 * s3 + m[0][1] = c3 * s1 + c1 * c2 * s3 + m[0][2] = s2 *s3 + m[0][3] = 0 + m[1][0] =-c1 * s3 - c2 * c3 * s1 + m[1][1] = c1 * c2 * c3 - s1 * s3 + m[1][2] = c3 * s2 + m[1][3] = 0 + m[2][0] = s1 * s2 + m[2][1] =-c1 * s2 + m[2][2] = c2 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_xzy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2 * c3; - m[0][1] = s1 * s3 + c1 * c3 * s2; - m[0][2] = c3 * s1 * s2 - c1 * s3; - m[0][3] = 0; - m[1][0] =-s2; - m[1][1] = c1 * c2; - m[1][2] = c2 * s1; - m[1][3] = 0; - m[2][0] = c2 * s3; - m[2][1] = c1 * s2 * s3 - c3 * s1; - m[2][2] = c1 * c3 + s1 * s2 *s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 * c3 + m[0][1] = s1 * s3 + c1 * c3 * s2 + m[0][2] = c3 * s1 * s2 - c1 * s3 + m[0][3] = 0 + m[1][0] =-s2 + m[1][1] = c1 * c2 + m[1][2] = c2 * s1 + m[1][3] = 0 + m[2][0] = c2 * s3 + m[2][1] = c1 * s2 * s3 - c3 * s1 + m[2][2] = c1 * c3 + s1 * s2 *s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_yzx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2; - m[0][1] = s2; - m[0][2] =-c2 * s1; - m[0][3] = 0; - m[1][0] = s1 * s3 - c1 * c3 * s2; - m[1][1] = c2 * c3; - m[1][2] = c1 * s3 + c3 * s1 * s2; - m[1][3] = 0; - m[2][0] = c3 * s1 + c1 * s2 * s3; - m[2][1] =-c2 * s3; - m[2][2] = c1 * c3 - s1 * s2 * s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 + m[0][1] = s2 + m[0][2] =-c2 * s1 + m[0][3] = 0 + m[1][0] = s1 * s3 - c1 * c3 * s2 + m[1][1] = c2 * c3 + m[1][2] = c1 * s3 + c3 * s1 * s2 + m[1][3] = 0 + m[2][0] = c3 * s1 + c1 * s2 * s3 + m[2][1] =-c2 * s3 + m[2][2] = c1 * c3 - s1 * s2 * s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_zyx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2; - m[0][1] = c2 * s1; - m[0][2] =-s2; - m[0][3] = 0; - m[1][0] = c1 * s2 * s3 - c3 * s1; - m[1][1] = c1 * c3 + s1 * s2 * s3; - m[1][2] = c2 * s3; - m[1][3] = 0; - m[2][0] = s1 * s3 + c1 * c3 * s2; - m[2][1] = c3 * s1 * s2 - c1 * s3; - m[2][2] = c2 * c3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 + m[0][1] = c2 * s1 + m[0][2] =-s2 + m[0][3] = 0 + m[1][0] = c1 * s2 * s3 - c3 * s1 + m[1][1] = c1 * c3 + s1 * s2 * s3 + m[1][2] = c2 * s3 + m[1][3] = 0 + m[2][0] = s1 * s3 + c1 * c3 * s2 + m[2][1] = c3 * s1 * s2 - c1 * s3 + m[2][2] = c2 * c3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_zxy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - s1 * s2 * s3; - m[0][1] = c3 * s1 + c1 * s2 * s3; - m[0][2] =-c2 * s3; - m[0][3] = 0; - m[1][0] =-c2 * s1; - m[1][1] = c1 * c2; - m[1][2] = s2; - m[1][3] = 0; - m[2][0] = c1 * s3 + c3 * s1 * s2; - m[2][1] = s1 * s3 - c1 * c3 * s2; - m[2][2] = c2 * c3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - s1 * s2 * s3 + m[0][1] = c3 * s1 + c1 * s2 * s3 + m[0][2] =-c2 * s3 + m[0][3] = 0 + m[1][0] =-c2 * s1 + m[1][1] = c1 * c2 + m[1][2] = s2 + m[1][3] = 0 + m[2][0] = c1 * s3 + c3 * s1 * s2 + m[2][1] = s1 * s3 - c1 * c3 * s2 + m[2][2] = c2 * c3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_yaw_pitch_roll_f64 :: proc(yaw, pitch, roll: f64) -> (m: Matrix4f64) { - ch := math.cos(yaw); - sh := math.sin(yaw); - cp := math.cos(pitch); - sp := math.sin(pitch); - cb := math.cos(roll); - sb := math.sin(roll); - - m[0][0] = ch * cb + sh * sp * sb; - m[0][1] = sb * cp; - m[0][2] = -sh * cb + ch * sp * sb; - m[0][3] = 0; - m[1][0] = -ch * sb + sh * sp * cb; - m[1][1] = cb * cp; - m[1][2] = sb * sh + ch * sp * cb; - m[1][3] = 0; - m[2][0] = sh * cp; - m[2][1] = -sp; - m[2][2] = ch * cp; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return m; + ch := math.cos(yaw) + sh := math.sin(yaw) + cp := math.cos(pitch) + sp := math.sin(pitch) + cb := math.cos(roll) + sb := math.sin(roll) + + m[0][0] = ch * cb + sh * sp * sb + m[0][1] = sb * cp + m[0][2] = -sh * cb + ch * sp * sb + m[0][3] = 0 + m[1][0] = -ch * sb + sh * sp * cb + m[1][1] = cb * cp + m[1][2] = sb * sh + ch * sp * cb + m[1][3] = 0 + m[2][0] = sh * cp + m[2][1] = -sp + m[2][2] = ch * cp + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return m } euler_angles_xyz_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[2][1], m[2][2]); - C2 := math.sqrt(m[0][0]*m[0][0] + m[1][0]*m[1][0]); - T2 := math.atan2(-m[2][0], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[0][2] - C1*m[0][1], C1*m[1][1] - S1*m[1][2]); - t1 = -T1; - t2 = -T2; - t3 = -T3; - return; + T1 := math.atan2(m[2][1], m[2][2]) + C2 := math.sqrt(m[0][0]*m[0][0] + m[1][0]*m[1][0]) + T2 := math.atan2(-m[2][0], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[0][2] - C1*m[0][1], C1*m[1][1] - S1*m[1][2]) + t1 = -T1 + t2 = -T2 + t3 = -T3 + return } euler_angles_yxz_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[2][0], m[2][2]); - C2 := math.sqrt(m[0][1]*m[0][1] + m[1][1]*m[1][1]); - T2 := math.atan2(-m[2][1], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[1][2] - C1*m[1][0], C1*m[0][0] - S1*m[0][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][0], m[2][2]) + C2 := math.sqrt(m[0][1]*m[0][1] + m[1][1]*m[1][1]) + T2 := math.atan2(-m[2][1], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[1][2] - C1*m[1][0], C1*m[0][0] - S1*m[0][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xzx_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[0][2], m[0][1]); - S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]); - T2 := math.atan2(S2, m[0][0]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[1][2] - S1*m[1][1], C1*m[2][2] - S1*m[2][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][2], m[0][1]) + S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]) + T2 := math.atan2(S2, m[0][0]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[1][2] - S1*m[1][1], C1*m[2][2] - S1*m[2][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xyx_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[0][1], -m[0][2]); - S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]); - T2 := math.atan2(S2, m[0][0]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-C1*m[2][1] - S1*m[2][2], C1*m[1][1] + S1*m[1][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][1], -m[0][2]) + S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]) + T2 := math.atan2(S2, m[0][0]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-C1*m[2][1] - S1*m[2][2], C1*m[1][1] + S1*m[1][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yxy_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[1][0], m[1][2]); - S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]); - T2 := math.atan2(S2, m[1][1]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[2][0] - S1*m[2][2], C1*m[0][0] - S1*m[0][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][0], m[1][2]) + S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]) + T2 := math.atan2(S2, m[1][1]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[2][0] - S1*m[2][2], C1*m[0][0] - S1*m[0][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yzy_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[1][2], -m[1][0]); - S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]); - T2 := math.atan2(S2, m[1][1]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-S1*m[0][0] - C1*m[0][2], S1*m[2][0] + C1*m[2][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][2], -m[1][0]) + S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]) + T2 := math.atan2(S2, m[1][1]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-S1*m[0][0] - C1*m[0][2], S1*m[2][0] + C1*m[2][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zyz_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[2][1], m[2][0]); - S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]); - T2 := math.atan2(S2, m[2][2]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[0][1] - S1*m[0][0], C1*m[1][1] - S1*m[1][0]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][1], m[2][0]) + S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]) + T2 := math.atan2(S2, m[2][2]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[0][1] - S1*m[0][0], C1*m[1][1] - S1*m[1][0]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zxz_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[2][0], -m[2][1]); - S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]); - T2 := math.atan2(S2, m[2][2]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-C1*m[1][0] - S1*m[1][1], C1*m[0][0] + S1*m[0][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][0], -m[2][1]) + S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]) + T2 := math.atan2(S2, m[2][2]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-C1*m[1][0] - S1*m[1][1], C1*m[0][0] + S1*m[0][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xzy_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[1][2], m[1][1]); - C2 := math.sqrt(m[0][0]*m[0][0] + m[2][0]*m[2][0]); - T2 := math.atan2(-m[1][0], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[0][1] - C1*m[0][2], C1*m[2][2] - S1*m[2][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][2], m[1][1]) + C2 := math.sqrt(m[0][0]*m[0][0] + m[2][0]*m[2][0]) + T2 := math.atan2(-m[1][0], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[0][1] - C1*m[0][2], C1*m[2][2] - S1*m[2][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yzx_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(-m[0][2], m[0][0]); - C2 := math.sqrt(m[1][1]*m[1][1] + m[2][1]*m[2][1]); - T2 := math.atan2(m[0][1], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[1][0] + C1*m[1][2], S1*m[2][0] + C1*m[2][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(-m[0][2], m[0][0]) + C2 := math.sqrt(m[1][1]*m[1][1] + m[2][1]*m[2][1]) + T2 := math.atan2(m[0][1], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[1][0] + C1*m[1][2], S1*m[2][0] + C1*m[2][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zyx_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[0][1], m[0][0]); - C2 := math.sqrt(m[1][2]*m[1][2] + m[2][2]*m[2][2]); - T2 := math.atan2(-m[0][2], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[2][0] - C1*m[2][1], C1*m[1][1] - S1*m[1][0]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][1], m[0][0]) + C2 := math.sqrt(m[1][2]*m[1][2] + m[2][2]*m[2][2]) + T2 := math.atan2(-m[0][2], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[2][0] - C1*m[2][1], C1*m[1][1] - S1*m[1][0]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zxy_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(-m[1][0], m[1][1]); - C2 := math.sqrt(m[0][2]*m[0][2] + m[2][2]*m[2][2]); - T2 := math.atan2(m[1][2], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[2][0] + S1*m[2][1], C1*m[0][0] + S1*m[0][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(-m[1][0], m[1][1]) + C2 := math.sqrt(m[0][2]*m[0][2] + m[2][2]*m[2][2]) + T2 := math.atan2(m[1][2], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[2][0] + S1*m[2][1], C1*m[0][0] + S1*m[0][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } diff --git a/core/math/linalg/swizzle.odin b/core/math/linalg/swizzle.odin index 335d22b9b..f035a5276 100644 --- a/core/math/linalg/swizzle.odin +++ b/core/math/linalg/swizzle.odin @@ -33,110 +33,110 @@ Vector4_Components :: enum u8 { } scalar_f32_swizzle1 :: proc(f: f32, c0: Scalar_Components) -> f32 { - return f; + return f } scalar_f32_swizzle2 :: proc(f: f32, c0, c1: Scalar_Components) -> Vector2f32 { - return {f, f}; + return {f, f} } scalar_f32_swizzle3 :: proc(f: f32, c0, c1, c2: Scalar_Components) -> Vector3f32 { - return {f, f, f}; + return {f, f, f} } scalar_f32_swizzle4 :: proc(f: f32, c0, c1, c2, c3: Scalar_Components) -> Vector4f32 { - return {f, f, f, f}; + return {f, f, f, f} } vector2f32_swizzle1 :: proc(v: Vector2f32, c0: Vector2_Components) -> f32 { - return v[c0]; + return v[c0] } vector2f32_swizzle2 :: proc(v: Vector2f32, c0, c1: Vector2_Components) -> Vector2f32 { - return {v[c0], v[c1]}; + return {v[c0], v[c1]} } vector2f32_swizzle3 :: proc(v: Vector2f32, c0, c1, c2: Vector2_Components) -> Vector3f32 { - return {v[c0], v[c1], v[c2]}; + return {v[c0], v[c1], v[c2]} } vector2f32_swizzle4 :: proc(v: Vector2f32, c0, c1, c2, c3: Vector2_Components) -> Vector4f32 { - return {v[c0], v[c1], v[c2], v[c3]}; + return {v[c0], v[c1], v[c2], v[c3]} } vector3f32_swizzle1 :: proc(v: Vector3f32, c0: Vector3_Components) -> f32 { - return v[c0]; + return v[c0] } vector3f32_swizzle2 :: proc(v: Vector3f32, c0, c1: Vector3_Components) -> Vector2f32 { - return {v[c0], v[c1]}; + return {v[c0], v[c1]} } vector3f32_swizzle3 :: proc(v: Vector3f32, c0, c1, c2: Vector3_Components) -> Vector3f32 { - return {v[c0], v[c1], v[c2]}; + return {v[c0], v[c1], v[c2]} } vector3f32_swizzle4 :: proc(v: Vector3f32, c0, c1, c2, c3: Vector3_Components) -> Vector4f32 { - return {v[c0], v[c1], v[c2], v[c3]}; + return {v[c0], v[c1], v[c2], v[c3]} } vector4f32_swizzle1 :: proc(v: Vector4f32, c0: Vector4_Components) -> f32 { - return v[c0]; + return v[c0] } vector4f32_swizzle2 :: proc(v: Vector4f32, c0, c1: Vector4_Components) -> Vector2f32 { - return {v[c0], v[c1]}; + return {v[c0], v[c1]} } vector4f32_swizzle3 :: proc(v: Vector4f32, c0, c1, c2: Vector4_Components) -> Vector3f32 { - return {v[c0], v[c1], v[c2]}; + return {v[c0], v[c1], v[c2]} } vector4f32_swizzle4 :: proc(v: Vector4f32, c0, c1, c2, c3: Vector4_Components) -> Vector4f32 { - return {v[c0], v[c1], v[c2], v[c3]}; + return {v[c0], v[c1], v[c2], v[c3]} } scalar_f64_swizzle1 :: proc(f: f64, c0: Scalar_Components) -> f64 { - return f; + return f } scalar_f64_swizzle2 :: proc(f: f64, c0, c1: Scalar_Components) -> Vector2f64 { - return {f, f}; + return {f, f} } scalar_f64_swizzle3 :: proc(f: f64, c0, c1, c2: Scalar_Components) -> Vector3f64 { - return {f, f, f}; + return {f, f, f} } scalar_f64_swizzle4 :: proc(f: f64, c0, c1, c2, c3: Scalar_Components) -> Vector4f64 { - return {f, f, f, f}; + return {f, f, f, f} } vector2f64_swizzle1 :: proc(v: Vector2f64, c0: Vector2_Components) -> f64 { - return v[c0]; + return v[c0] } vector2f64_swizzle2 :: proc(v: Vector2f64, c0, c1: Vector2_Components) -> Vector2f64 { - return {v[c0], v[c1]}; + return {v[c0], v[c1]} } vector2f64_swizzle3 :: proc(v: Vector2f64, c0, c1, c2: Vector2_Components) -> Vector3f64 { - return {v[c0], v[c1], v[c2]}; + return {v[c0], v[c1], v[c2]} } vector2f64_swizzle4 :: proc(v: Vector2f64, c0, c1, c2, c3: Vector2_Components) -> Vector4f64 { - return {v[c0], v[c1], v[c2], v[c3]}; + return {v[c0], v[c1], v[c2], v[c3]} } vector3f64_swizzle1 :: proc(v: Vector3f64, c0: Vector3_Components) -> f64 { - return v[c0]; + return v[c0] } vector3f64_swizzle2 :: proc(v: Vector3f64, c0, c1: Vector3_Components) -> Vector2f64 { - return {v[c0], v[c1]}; + return {v[c0], v[c1]} } vector3f64_swizzle3 :: proc(v: Vector3f64, c0, c1, c2: Vector3_Components) -> Vector3f64 { - return {v[c0], v[c1], v[c2]}; + return {v[c0], v[c1], v[c2]} } vector3f64_swizzle4 :: proc(v: Vector3f64, c0, c1, c2, c3: Vector3_Components) -> Vector4f64 { - return {v[c0], v[c1], v[c2], v[c3]}; + return {v[c0], v[c1], v[c2], v[c3]} } vector4f64_swizzle1 :: proc(v: Vector4f64, c0: Vector4_Components) -> f64 { - return v[c0]; + return v[c0] } vector4f64_swizzle2 :: proc(v: Vector4f64, c0, c1: Vector4_Components) -> Vector2f64 { - return {v[c0], v[c1]}; + return {v[c0], v[c1]} } vector4f64_swizzle3 :: proc(v: Vector4f64, c0, c1, c2: Vector4_Components) -> Vector3f64 { - return {v[c0], v[c1], v[c2]}; + return {v[c0], v[c1], v[c2]} } vector4f64_swizzle4 :: proc(v: Vector4f64, c0, c1, c2, c3: Vector4_Components) -> Vector4f64 { - return {v[c0], v[c1], v[c2], v[c3]}; + return {v[c0], v[c1], v[c2], v[c3]} } @@ -151,7 +151,7 @@ scalar_swizzle :: proc{ scalar_f64_swizzle2, scalar_f64_swizzle3, scalar_f64_swizzle4, -}; +} vector2_swizzle :: proc{ vector2f32_swizzle1, @@ -162,7 +162,7 @@ vector2_swizzle :: proc{ vector2f64_swizzle2, vector2f64_swizzle3, vector2f64_swizzle4, -}; +} vector3_swizzle :: proc{ vector3f32_swizzle1, @@ -173,7 +173,7 @@ vector3_swizzle :: proc{ vector3f64_swizzle2, vector3f64_swizzle3, vector3f64_swizzle4, -}; +} vector4_swizzle :: proc{ vector4f32_swizzle1, @@ -184,7 +184,7 @@ vector4_swizzle :: proc{ vector4f64_swizzle2, vector4f64_swizzle3, vector4f64_swizzle4, -}; +} swizzle :: proc{ scalar_f32_swizzle1, @@ -219,4 +219,4 @@ swizzle :: proc{ vector4f64_swizzle2, vector4f64_swizzle3, vector4f64_swizzle4, -}; +} diff --git a/core/math/math.odin b/core/math/math.odin index 28b0c42fc..6a094cfd4 100644 --- a/core/math/math.odin +++ b/core/math/math.odin @@ -1,7 +1,7 @@ package math import "core:intrinsics" -_ :: intrinsics; +_ :: intrinsics Float_Class :: enum { Normal, // an ordinary nonzero floating point value @@ -11,89 +11,89 @@ Float_Class :: enum { NaN, // Not-A-Number (NaN) Inf, // positive infinity Neg_Inf, // negative infinity -}; +} -TAU :: 6.28318530717958647692528676655900576; -PI :: 3.14159265358979323846264338327950288; +TAU :: 6.28318530717958647692528676655900576 +PI :: 3.14159265358979323846264338327950288 -E :: 2.71828182845904523536; +E :: 2.71828182845904523536 -τ :: TAU; -π :: PI; -e :: E; +τ :: TAU +π :: PI +e :: E -SQRT_TWO :: 1.41421356237309504880168872420969808; -SQRT_THREE :: 1.73205080756887729352744634150587236; -SQRT_FIVE :: 2.23606797749978969640917366873127623; +SQRT_TWO :: 1.41421356237309504880168872420969808 +SQRT_THREE :: 1.73205080756887729352744634150587236 +SQRT_FIVE :: 2.23606797749978969640917366873127623 -LN2 :: 0.693147180559945309417232121458176568; -LN10 :: 2.30258509299404568401799145468436421; +LN2 :: 0.693147180559945309417232121458176568 +LN10 :: 2.30258509299404568401799145468436421 -MAX_F64_PRECISION :: 16; // Maximum number of meaningful digits after the decimal point for 'f64' -MAX_F32_PRECISION :: 8; // Maximum number of meaningful digits after the decimal point for 'f32' -MAX_F16_PRECISION :: 4; // Maximum number of meaningful digits after the decimal point for 'f16' +MAX_F64_PRECISION :: 16 // Maximum number of meaningful digits after the decimal point for 'f64' +MAX_F32_PRECISION :: 8 // Maximum number of meaningful digits after the decimal point for 'f32' +MAX_F16_PRECISION :: 4 // Maximum number of meaningful digits after the decimal point for 'f16' -RAD_PER_DEG :: TAU/360.0; -DEG_PER_RAD :: 360.0/TAU; +RAD_PER_DEG :: TAU/360.0 +DEG_PER_RAD :: 360.0/TAU @(default_calling_convention="none") foreign _ { @(link_name="llvm.sqrt.f16") - sqrt_f16 :: proc(x: f16) -> f16 ---; + sqrt_f16 :: proc(x: f16) -> f16 --- @(link_name="llvm.sqrt.f32") - sqrt_f32 :: proc(x: f32) -> f32 ---; + sqrt_f32 :: proc(x: f32) -> f32 --- @(link_name="llvm.sqrt.f64") - sqrt_f64 :: proc(x: f64) -> f64 ---; + sqrt_f64 :: proc(x: f64) -> f64 --- @(link_name="llvm.sin.f16") - sin_f16 :: proc(θ: f16) -> f16 ---; + sin_f16 :: proc(θ: f16) -> f16 --- @(link_name="llvm.sin.f32") - sin_f32 :: proc(θ: f32) -> f32 ---; + sin_f32 :: proc(θ: f32) -> f32 --- @(link_name="llvm.sin.f64") - sin_f64 :: proc(θ: f64) -> f64 ---; + sin_f64 :: proc(θ: f64) -> f64 --- @(link_name="llvm.cos.f16") - cos_f16 :: proc(θ: f16) -> f16 ---; + cos_f16 :: proc(θ: f16) -> f16 --- @(link_name="llvm.cos.f32") - cos_f32 :: proc(θ: f32) -> f32 ---; + cos_f32 :: proc(θ: f32) -> f32 --- @(link_name="llvm.cos.f64") - cos_f64 :: proc(θ: f64) -> f64 ---; + cos_f64 :: proc(θ: f64) -> f64 --- @(link_name="llvm.pow.f16") - pow_f16 :: proc(x, power: f16) -> f16 ---; + pow_f16 :: proc(x, power: f16) -> f16 --- @(link_name="llvm.pow.f32") - pow_f32 :: proc(x, power: f32) -> f32 ---; + pow_f32 :: proc(x, power: f32) -> f32 --- @(link_name="llvm.pow.f64") - pow_f64 :: proc(x, power: f64) -> f64 ---; + pow_f64 :: proc(x, power: f64) -> f64 --- @(link_name="llvm.fmuladd.f16") - fmuladd_f16 :: proc(a, b, c: f16) -> f16 ---; + fmuladd_f16 :: proc(a, b, c: f16) -> f16 --- @(link_name="llvm.fmuladd.f32") - fmuladd_f32 :: proc(a, b, c: f32) -> f32 ---; + fmuladd_f32 :: proc(a, b, c: f32) -> f32 --- @(link_name="llvm.fmuladd.f64") - fmuladd_f64 :: proc(a, b, c: f64) -> f64 ---; + fmuladd_f64 :: proc(a, b, c: f64) -> f64 --- @(link_name="llvm.log.f16") - ln_f16 :: proc(x: f16) -> f16 ---; + ln_f16 :: proc(x: f16) -> f16 --- @(link_name="llvm.log.f32") - ln_f32 :: proc(x: f32) -> f32 ---; + ln_f32 :: proc(x: f32) -> f32 --- @(link_name="llvm.log.f64") - ln_f64 :: proc(x: f64) -> f64 ---; + ln_f64 :: proc(x: f64) -> f64 --- @(link_name="llvm.exp.f16") - exp_f16 :: proc(x: f16) -> f16 ---; + exp_f16 :: proc(x: f16) -> f16 --- @(link_name="llvm.exp.f32") - exp_f32 :: proc(x: f32) -> f32 ---; + exp_f32 :: proc(x: f32) -> f32 --- @(link_name="llvm.exp.f64") - exp_f64 :: proc(x: f64) -> f64 ---; + exp_f64 :: proc(x: f64) -> f64 --- @(link_name="llvm.ldexp.f16") - ldexp_f16 :: proc(val: f16, exp: i32) -> f16 ---; + ldexp_f16 :: proc(val: f16, exp: i32) -> f16 --- @(link_name="llvm.ldexp.f32") - ldexp_f32 :: proc(val: f32, exp: i32) -> f32 ---; + ldexp_f32 :: proc(val: f32, exp: i32) -> f32 --- @(link_name="llvm.ldexp.f64") - ldexp_f64 :: proc(val: f64, exp: i32) -> f64 ---; + ldexp_f64 :: proc(val: f64, exp: i32) -> f64 --- } sqrt_f16le :: proc(x: f16le) -> f16le { return #force_inline f16le(sqrt_f16(f16(x))); } @@ -106,7 +106,7 @@ sqrt :: proc{ sqrt_f16, sqrt_f16le, sqrt_f16be, sqrt_f32, sqrt_f32le, sqrt_f32be, sqrt_f64, sqrt_f64le, sqrt_f64be, -}; +} sin_f16le :: proc(θ: f16le) -> f16le { return #force_inline f16le(sin_f16(f16(θ))); } sin_f16be :: proc(θ: f16be) -> f16be { return #force_inline f16be(sin_f16(f16(θ))); } @@ -118,7 +118,7 @@ sin :: proc{ sin_f16, sin_f16le, sin_f16be, sin_f32, sin_f32le, sin_f32be, sin_f64, sin_f64le, sin_f64be, -}; +} cos_f16le :: proc(θ: f16le) -> f16le { return #force_inline f16le(cos_f16(f16(θ))); } cos_f16be :: proc(θ: f16be) -> f16be { return #force_inline f16be(cos_f16(f16(θ))); } @@ -130,7 +130,7 @@ cos :: proc{ cos_f16, cos_f16le, cos_f16be, cos_f32, cos_f32le, cos_f32be, cos_f64, cos_f64le, cos_f64be, -}; +} pow_f16le :: proc(x, power: f16le) -> f16le { return #force_inline f16le(pow_f16(f16(x), f16(power))); } pow_f16be :: proc(x, power: f16be) -> f16be { return #force_inline f16be(pow_f16(f16(x), f16(power))); } @@ -142,7 +142,7 @@ pow :: proc{ pow_f16, pow_f16le, pow_f16be, pow_f32, pow_f32le, pow_f32be, pow_f64, pow_f64le, pow_f64be, -}; +} fmuladd_f16le :: proc(a, b, c: f16le) -> f16le { return #force_inline f16le(fmuladd_f16(f16(a), f16(b), f16(c))); } fmuladd_f16be :: proc(a, b, c: f16be) -> f16be { return #force_inline f16be(fmuladd_f16(f16(a), f16(b), f16(c))); } @@ -154,7 +154,7 @@ fmuladd :: proc{ fmuladd_f16, fmuladd_f16le, fmuladd_f16be, fmuladd_f32, fmuladd_f32le, fmuladd_f32be, fmuladd_f64, fmuladd_f64le, fmuladd_f64be, -}; +} ln_f16le :: proc(x: f16le) -> f16le { return #force_inline f16le(ln_f16(f16(x))); } ln_f16be :: proc(x: f16be) -> f16be { return #force_inline f16be(ln_f16(f16(x))); } @@ -166,7 +166,7 @@ ln :: proc{ ln_f16, ln_f16le, ln_f16be, ln_f32, ln_f32le, ln_f32be, ln_f64, ln_f64le, ln_f64be, -}; +} exp_f16le :: proc(x: f16le) -> f16le { return #force_inline f16le(exp_f16(f16(x))); } exp_f16be :: proc(x: f16be) -> f16be { return #force_inline f16be(exp_f16(f16(x))); } @@ -178,7 +178,7 @@ exp :: proc{ exp_f16, exp_f16le, exp_f16be, exp_f32, exp_f32le, exp_f32be, exp_f64, exp_f64le, exp_f64be, -}; +} ldexp_f16le :: proc(val: f16le, exp: i32) -> f16le { return #force_inline f16le(ldexp_f16(f16(val), exp)); } ldexp_f16be :: proc(val: f16be, exp: i32) -> f16be { return #force_inline f16be(ldexp_f16(f16(val), exp)); } @@ -190,7 +190,7 @@ ldexp :: proc{ ldexp_f16, ldexp_f16le, ldexp_f16be, ldexp_f32, ldexp_f32le, ldexp_f32be, ldexp_f64, ldexp_f64le, ldexp_f64be, -}; +} log_f16 :: proc(x, base: f16) -> f16 { return ln(x) / ln(base); } @@ -208,7 +208,7 @@ log :: proc{ log_f16, log_f16le, log_f16be, log_f32, log_f32le, log_f32be, log_f64, log_f64le, log_f64be, -}; +} log2_f16 :: proc(x: f16) -> f16 { return ln(x)/LN2; } log2_f16le :: proc(x: f16le) -> f16le { return f16le(log2_f16(f16(x))); } @@ -225,7 +225,7 @@ log2 :: proc{ log2_f16, log2_f16le, log2_f16be, log2_f32, log2_f32le, log2_f32be, log2_f64, log2_f64le, log2_f64be, -}; +} log10_f16 :: proc(x: f16) -> f16 { return ln(x)/LN10; } log10_f16le :: proc(x: f16le) -> f16le { return f16le(log10_f16(f16(x))); } @@ -242,7 +242,7 @@ log10 :: proc{ log10_f16, log10_f16le, log10_f16be, log10_f32, log10_f32le, log10_f32be, log10_f64, log10_f64le, log10_f64be, -}; +} tan_f16 :: proc(θ: f16) -> f16 { return sin(θ)/cos(θ); } tan_f16le :: proc(θ: f16le) -> f16le { return f16le(tan_f16(f16(θ))); } @@ -259,55 +259,55 @@ tan :: proc{ tan_f16, tan_f16le, tan_f16be, tan_f32, tan_f32le, tan_f32be, tan_f64, tan_f64le, tan_f64be, -}; +} lerp :: proc(a, b: $T, t: $E) -> (x: T) { return a*(1-t) + b*t; } -saturate :: proc(a: $T) -> (x: T) { return clamp(a, 0, 1); }; +saturate :: proc(a: $T) -> (x: T) { return clamp(a, 0, 1); } unlerp :: proc(a, b, x: $T) -> (t: T) where intrinsics.type_is_float(T), !intrinsics.type_is_array(T) { - return (x-a)/(b-a); + return (x-a)/(b-a) } remap :: proc(old_value, old_min, old_max, new_min, new_max: $T) -> (x: T) where intrinsics.type_is_numeric(T), !intrinsics.type_is_array(T) { - old_range := old_max - old_min; - new_range := new_max - new_min; + old_range := old_max - old_min + new_range := new_max - new_min if old_range == 0 { - return new_range / 2; + return new_range / 2 } - return ((old_value - old_min) / old_range) * new_range + new_min; + return ((old_value - old_min) / old_range) * new_range + new_min } wrap :: proc(x, y: $T) -> T where intrinsics.type_is_numeric(T), !intrinsics.type_is_array(T) { - tmp := mod(x, y); - return y + tmp if tmp < 0 else tmp; + tmp := mod(x, y) + return y + tmp if tmp < 0 else tmp } angle_diff :: proc(a, b: $T) -> T where intrinsics.type_is_numeric(T), !intrinsics.type_is_array(T) { - dist := wrap(b - a, TAU); - return wrap(dist*2, TAU) - dist; + dist := wrap(b - a, TAU) + return wrap(dist*2, TAU) - dist } angle_lerp :: proc(a, b, t: $T) -> T where intrinsics.type_is_numeric(T), !intrinsics.type_is_array(T) { - return a + angle_diff(a, b) * t; + return a + angle_diff(a, b) * t } step :: proc(edge, x: $T) -> T where intrinsics.type_is_numeric(T), !intrinsics.type_is_array(T) { - return 0 if x < edge else 1; + return 0 if x < edge else 1 } smoothstep :: proc(edge0, edge1, x: $T) -> T where intrinsics.type_is_numeric(T), !intrinsics.type_is_array(T) { - t := clamp((x - edge0) / (edge1 - edge0), 0, 1); - return t * t * (3 - 2*t); + t := clamp((x - edge0) / (edge1 - edge0), 0, 1) + return t * t * (3 - 2*t) } bias :: proc(t, b: $T) -> T where intrinsics.type_is_numeric(T) { - return t / (((1/b) - 2) * (1 - t) + 1); + return t / (((1/b) - 2) * (1 - t) + 1) } gain :: proc(t, g: $T) -> T where intrinsics.type_is_numeric(T) { if t < 0.5 { - return bias(t*2, g)*0.5; + return bias(t*2, g)*0.5 } - return bias(t*2 - 1, 1 - g)*0.5 + 0.5; + return bias(t*2 - 1, 1 - g)*0.5 + 0.5 } @@ -324,20 +324,20 @@ sign :: proc{ sign_f16, sign_f16le, sign_f16be, sign_f32, sign_f32le, sign_f32be, sign_f64, sign_f64le, sign_f64be, -}; +} sign_bit_f16 :: proc(x: f16) -> bool { - return (transmute(u16)x) & (1<<15) != 0; + return (transmute(u16)x) & (1<<15) != 0 } sign_bit_f16le :: proc(x: f16le) -> bool { return #force_inline sign_bit_f16(f16(x)); } sign_bit_f16be :: proc(x: f16be) -> bool { return #force_inline sign_bit_f16(f16(x)); } sign_bit_f32 :: proc(x: f32) -> bool { - return (transmute(u32)x) & (1<<31) != 0; + return (transmute(u32)x) & (1<<31) != 0 } sign_bit_f32le :: proc(x: f32le) -> bool { return #force_inline sign_bit_f32(f32(x)); } sign_bit_f32be :: proc(x: f32be) -> bool { return #force_inline sign_bit_f32(f32(x)); } sign_bit_f64 :: proc(x: f64) -> bool { - return (transmute(u64)x) & (1<<63) != 0; + return (transmute(u64)x) & (1<<63) != 0 } sign_bit_f64le :: proc(x: f64le) -> bool { return #force_inline sign_bit_f64(f64(x)); } sign_bit_f64be :: proc(x: f64be) -> bool { return #force_inline sign_bit_f64(f64(x)); } @@ -345,32 +345,32 @@ sign_bit :: proc{ sign_bit_f16, sign_bit_f16le, sign_bit_f16be, sign_bit_f32, sign_bit_f32le, sign_bit_f32be, sign_bit_f64, sign_bit_f64le, sign_bit_f64be, -}; +} copy_sign_f16 :: proc(x, y: f16) -> f16 { - ix := transmute(u16)x; - iy := transmute(u16)y; - ix &= 0x7fff; - ix |= iy & 0x8000; - return transmute(f16)ix; + ix := transmute(u16)x + iy := transmute(u16)y + ix &= 0x7fff + ix |= iy & 0x8000 + return transmute(f16)ix } copy_sign_f16le :: proc(x, y: f16le) -> f16le { return #force_inline f16le(copy_sign_f16(f16(x), f16(y))); } copy_sign_f16be :: proc(x, y: f16be) -> f16be { return #force_inline f16be(copy_sign_f16(f16(x), f16(y))); } copy_sign_f32 :: proc(x, y: f32) -> f32 { - ix := transmute(u32)x; - iy := transmute(u32)y; - ix &= 0x7fff_ffff; - ix |= iy & 0x8000_0000; - return transmute(f32)ix; + ix := transmute(u32)x + iy := transmute(u32)y + ix &= 0x7fff_ffff + ix |= iy & 0x8000_0000 + return transmute(f32)ix } copy_sign_f32le :: proc(x, y: f32le) -> f32le { return #force_inline f32le(copy_sign_f32(f32(x), f32(y))); } copy_sign_f32be :: proc(x, y: f32be) -> f32be { return #force_inline f32be(copy_sign_f32(f32(x), f32(y))); } copy_sign_f64 :: proc(x, y: f64) -> f64 { - ix := transmute(u64)x; - iy := transmute(u64)y; - ix &= 0x7fff_ffff_ffff_ffff; - ix |= iy & 0x8000_0000_0000_0000; - return transmute(f64)ix; + ix := transmute(u64)x + iy := transmute(u64)y + ix &= 0x7fff_ffff_ffff_ffff + ix |= iy & 0x8000_0000_0000_0000 + return transmute(f64)ix } copy_sign_f64le :: proc(x, y: f64le) -> f64le { return #force_inline f64le(copy_sign_f64(f64(x), f64(y))); } copy_sign_f64be :: proc(x, y: f64be) -> f64be { return #force_inline f64be(copy_sign_f64(f64(x), f64(y))); } @@ -378,7 +378,7 @@ copy_sign :: proc{ copy_sign_f16, copy_sign_f16le, copy_sign_f16be, copy_sign_f32, copy_sign_f32le, copy_sign_f32be, copy_sign_f64, copy_sign_f64le, copy_sign_f64be, -}; +} to_radians_f16 :: proc(degrees: f16) -> f16 { return degrees * RAD_PER_DEG; } to_radians_f16le :: proc(degrees: f16le) -> f16le { return degrees * RAD_PER_DEG; } @@ -402,105 +402,105 @@ to_radians :: proc{ to_radians_f16, to_radians_f16le, to_radians_f16be, to_radians_f32, to_radians_f32le, to_radians_f32be, to_radians_f64, to_radians_f64le, to_radians_f64be, -}; +} to_degrees :: proc{ to_degrees_f16, to_degrees_f16le, to_degrees_f16be, to_degrees_f32, to_degrees_f32le, to_degrees_f32be, to_degrees_f64, to_degrees_f64le, to_degrees_f64be, -}; +} trunc_f16 :: proc(x: f16) -> f16 { trunc_internal :: proc(f: f16) -> f16 { - mask :: 0x1f; - shift :: 16 - 6; - bias :: 0xf; + mask :: 0x1f + shift :: 16 - 6 + bias :: 0xf if f < 1 { switch { - case f < 0: return -trunc_internal(-f); - case f == 0: return f; - case: return 0; + case f < 0: return -trunc_internal(-f) + case f == 0: return f + case: return 0 } } - x := transmute(u16)f; - e := (x >> shift) & mask - bias; + x := transmute(u16)f + e := (x >> shift) & mask - bias if e < shift { - x &= ~(1 << (shift-e)) - 1; + x &= ~(1 << (shift-e)) - 1 } - return transmute(f16)x; + return transmute(f16)x } switch classify(x) { case .Zero, .Neg_Zero, .NaN, .Inf, .Neg_Inf: - return x; + return x case .Normal, .Subnormal: // carry on } - return trunc_internal(x); + return trunc_internal(x) } trunc_f16le :: proc(x: f16le) -> f16le { return #force_inline f16le(trunc_f16(f16(x))); } trunc_f16be :: proc(x: f16be) -> f16be { return #force_inline f16be(trunc_f16(f16(x))); } trunc_f32 :: proc(x: f32) -> f32 { trunc_internal :: proc(f: f32) -> f32 { - mask :: 0xff; - shift :: 32 - 9; - bias :: 0x7f; + mask :: 0xff + shift :: 32 - 9 + bias :: 0x7f if f < 1 { switch { - case f < 0: return -trunc_internal(-f); - case f == 0: return f; - case: return 0; + case f < 0: return -trunc_internal(-f) + case f == 0: return f + case: return 0 } } - x := transmute(u32)f; - e := (x >> shift) & mask - bias; + x := transmute(u32)f + e := (x >> shift) & mask - bias if e < shift { - x &= ~(1 << (shift-e)) - 1; + x &= ~(1 << (shift-e)) - 1 } - return transmute(f32)x; + return transmute(f32)x } switch classify(x) { case .Zero, .Neg_Zero, .NaN, .Inf, .Neg_Inf: - return x; + return x case .Normal, .Subnormal: // carry on } - return trunc_internal(x); + return trunc_internal(x) } trunc_f32le :: proc(x: f32le) -> f32le { return #force_inline f32le(trunc_f32(f32(x))); } trunc_f32be :: proc(x: f32be) -> f32be { return #force_inline f32be(trunc_f32(f32(x))); } trunc_f64 :: proc(x: f64) -> f64 { trunc_internal :: proc(f: f64) -> f64 { - mask :: 0x7ff; - shift :: 64 - 12; - bias :: 0x3ff; + mask :: 0x7ff + shift :: 64 - 12 + bias :: 0x3ff if f < 1 { switch { - case f < 0: return -trunc_internal(-f); - case f == 0: return f; - case: return 0; + case f < 0: return -trunc_internal(-f) + case f == 0: return f + case: return 0 } } - x := transmute(u64)f; - e := (x >> shift) & mask - bias; + x := transmute(u64)f + e := (x >> shift) & mask - bias if e < shift { - x &= ~(1 << (shift-e)) - 1; + x &= ~(1 << (shift-e)) - 1 } - return transmute(f64)x; + return transmute(f64)x } switch classify(x) { case .Zero, .Neg_Zero, .NaN, .Inf, .Neg_Inf: - return x; + return x case .Normal, .Subnormal: // carry on } - return trunc_internal(x); + return trunc_internal(x) } trunc_f64le :: proc(x: f64le) -> f64le { return #force_inline f64le(trunc_f64(f64(x))); } trunc_f64be :: proc(x: f64be) -> f64be { return #force_inline f64be(trunc_f64(f64(x))); } @@ -508,41 +508,41 @@ trunc :: proc{ trunc_f16, trunc_f16le, trunc_f16be, trunc_f32, trunc_f32le, trunc_f32be, trunc_f64, trunc_f64le, trunc_f64be, -}; +} round_f16 :: proc(x: f16) -> f16 { - return ceil(x - 0.5) if x < 0 else floor(x + 0.5); + return ceil(x - 0.5) if x < 0 else floor(x + 0.5) } round_f16le :: proc(x: f16le) -> f16le { - return ceil(x - 0.5) if x < 0 else floor(x + 0.5); + return ceil(x - 0.5) if x < 0 else floor(x + 0.5) } round_f16be :: proc(x: f16be) -> f16be { - return ceil(x - 0.5) if x < 0 else floor(x + 0.5); + return ceil(x - 0.5) if x < 0 else floor(x + 0.5) } round_f32 :: proc(x: f32) -> f32 { - return ceil(x - 0.5) if x < 0 else floor(x + 0.5); + return ceil(x - 0.5) if x < 0 else floor(x + 0.5) } round_f32le :: proc(x: f32le) -> f32le { - return ceil(x - 0.5) if x < 0 else floor(x + 0.5); + return ceil(x - 0.5) if x < 0 else floor(x + 0.5) } round_f32be :: proc(x: f32be) -> f32be { - return ceil(x - 0.5) if x < 0 else floor(x + 0.5); + return ceil(x - 0.5) if x < 0 else floor(x + 0.5) } round_f64 :: proc(x: f64) -> f64 { - return ceil(x - 0.5) if x < 0 else floor(x + 0.5); + return ceil(x - 0.5) if x < 0 else floor(x + 0.5) } round_f64le :: proc(x: f64le) -> f64le { - return ceil(x - 0.5) if x < 0 else floor(x + 0.5); + return ceil(x - 0.5) if x < 0 else floor(x + 0.5) } round_f64be :: proc(x: f64be) -> f64be { - return ceil(x - 0.5) if x < 0 else floor(x + 0.5); + return ceil(x - 0.5) if x < 0 else floor(x + 0.5) } round :: proc{ round_f16, round_f16le, round_f16be, round_f32, round_f32le, round_f32be, round_f64, round_f64le, round_f64be, -}; +} ceil_f16 :: proc(x: f16) -> f16 { return -floor(-x); } @@ -561,53 +561,53 @@ ceil :: proc{ ceil_f16, ceil_f16le, ceil_f16be, ceil_f32, ceil_f32le, ceil_f32be, ceil_f64, ceil_f64le, ceil_f64be, -}; +} floor_f16 :: proc(x: f16) -> f16 { if x == 0 || is_nan(x) || is_inf(x) { - return x; + return x } if x < 0 { - d, fract := modf(-x); + d, fract := modf(-x) if fract != 0.0 { - d = d + 1; + d = d + 1 } - return -d; + return -d } - d, _ := modf(x); - return d; + d, _ := modf(x) + return d } floor_f16le :: proc(x: f16le) -> f16le { return #force_inline f16le(floor_f16(f16(x))); } floor_f16be :: proc(x: f16be) -> f16be { return #force_inline f16be(floor_f16(f16(x))); } floor_f32 :: proc(x: f32) -> f32 { if x == 0 || is_nan(x) || is_inf(x) { - return x; + return x } if x < 0 { - d, fract := modf(-x); + d, fract := modf(-x) if fract != 0.0 { - d = d + 1; + d = d + 1 } - return -d; + return -d } - d, _ := modf(x); - return d; + d, _ := modf(x) + return d } floor_f32le :: proc(x: f32le) -> f32le { return #force_inline f32le(floor_f32(f32(x))); } floor_f32be :: proc(x: f32be) -> f32be { return #force_inline f32be(floor_f32(f32(x))); } floor_f64 :: proc(x: f64) -> f64 { if x == 0 || is_nan(x) || is_inf(x) { - return x; + return x } if x < 0 { - d, fract := modf(-x); + d, fract := modf(-x) if fract != 0.0 { - d = d + 1; + d = d + 1 } - return -d; + return -d } - d, _ := modf(x); - return d; + d, _ := modf(x) + return d } floor_f64le :: proc(x: f64le) -> f64le { return #force_inline f64le(floor_f64(f64(x))); } floor_f64be :: proc(x: f64be) -> f64be { return #force_inline f64be(floor_f64(f64(x))); } @@ -615,164 +615,164 @@ floor :: proc{ floor_f16, floor_f16le, floor_f16be, floor_f32, floor_f32le, floor_f32be, floor_f64, floor_f64le, floor_f64be, -}; +} floor_div :: proc(x, y: $T) -> T where intrinsics.type_is_integer(T) { - a := x / y; - r := x % y; + a := x / y + r := x % y if (r > 0 && y < 0) || (r < 0 && y > 0) { - a -= 1; + a -= 1 } - return a; + return a } floor_mod :: proc(x, y: $T) -> T where intrinsics.type_is_integer(T) { - r := x % y; + r := x % y if (r > 0 && y < 0) || (r < 0 && y > 0) { - r += y; + r += y } - return r; + return r } modf_f16 :: proc(x: f16) -> (int: f16, frac: f16) { - shift :: 16 - 5 - 1; - mask :: 0x1f; - bias :: 15; + shift :: 16 - 5 - 1 + mask :: 0x1f + bias :: 15 if x < 1 { switch { case x < 0: - int, frac = modf(-x); - return -int, -frac; + int, frac = modf(-x) + return -int, -frac case x == 0: - return x, x; + return x, x } - return 0, x; + return 0, x } - i := transmute(u16)x; - e := uint(i>>shift)&mask - bias; + i := transmute(u16)x + e := uint(i>>shift)&mask - bias if e < shift { - i &~= 1<<(shift-e) - 1; + i &~= 1<<(shift-e) - 1 } - int = transmute(f16)i; - frac = x - int; - return; + int = transmute(f16)i + frac = x - int + return } modf_f16le :: proc(x: f16le) -> (int: f16le, frac: f16le) { - i, f := #force_inline modf_f16(f16(x)); - return f16le(i), f16le(f); + i, f := #force_inline modf_f16(f16(x)) + return f16le(i), f16le(f) } modf_f16be :: proc(x: f16be) -> (int: f16be, frac: f16be) { - i, f := #force_inline modf_f16(f16(x)); - return f16be(i), f16be(f); + i, f := #force_inline modf_f16(f16(x)) + return f16be(i), f16be(f) } modf_f32 :: proc(x: f32) -> (int: f32, frac: f32) { - shift :: 32 - 8 - 1; - mask :: 0xff; - bias :: 127; + shift :: 32 - 8 - 1 + mask :: 0xff + bias :: 127 if x < 1 { switch { case x < 0: - int, frac = modf(-x); - return -int, -frac; + int, frac = modf(-x) + return -int, -frac case x == 0: - return x, x; + return x, x } - return 0, x; + return 0, x } - i := transmute(u32)x; - e := uint(i>>shift)&mask - bias; + i := transmute(u32)x + e := uint(i>>shift)&mask - bias if e < shift { - i &~= 1<<(shift-e) - 1; + i &~= 1<<(shift-e) - 1 } - int = transmute(f32)i; - frac = x - int; - return; + int = transmute(f32)i + frac = x - int + return } modf_f32le :: proc(x: f32le) -> (int: f32le, frac: f32le) { - i, f := #force_inline modf_f32(f32(x)); - return f32le(i), f32le(f); + i, f := #force_inline modf_f32(f32(x)) + return f32le(i), f32le(f) } modf_f32be :: proc(x: f32be) -> (int: f32be, frac: f32be) { - i, f := #force_inline modf_f32(f32(x)); - return f32be(i), f32be(f); + i, f := #force_inline modf_f32(f32(x)) + return f32be(i), f32be(f) } modf_f64 :: proc(x: f64) -> (int: f64, frac: f64) { - shift :: 64 - 11 - 1; - mask :: 0x7ff; - bias :: 1023; + shift :: 64 - 11 - 1 + mask :: 0x7ff + bias :: 1023 if x < 1 { switch { case x < 0: - int, frac = modf(-x); - return -int, -frac; + int, frac = modf(-x) + return -int, -frac case x == 0: - return x, x; + return x, x } - return 0, x; + return 0, x } - i := transmute(u64)x; - e := uint(i>>shift)&mask - bias; + i := transmute(u64)x + e := uint(i>>shift)&mask - bias if e < shift { - i &~= 1<<(shift-e) - 1; + i &~= 1<<(shift-e) - 1 } - int = transmute(f64)i; - frac = x - int; - return; + int = transmute(f64)i + frac = x - int + return } modf_f64le :: proc(x: f64le) -> (int: f64le, frac: f64le) { - i, f := #force_inline modf_f64(f64(x)); - return f64le(i), f64le(f); + i, f := #force_inline modf_f64(f64(x)) + return f64le(i), f64le(f) } modf_f64be :: proc(x: f64be) -> (int: f64be, frac: f64be) { - i, f := #force_inline modf_f64(f64(x)); - return f64be(i), f64be(f); + i, f := #force_inline modf_f64(f64(x)) + return f64be(i), f64be(f) } modf :: proc{ modf_f16, modf_f16le, modf_f16be, modf_f32, modf_f32le, modf_f32be, modf_f64, modf_f64le, modf_f64be, -}; -split_decimal :: modf; +} +split_decimal :: modf mod_f16 :: proc(x, y: f16) -> (n: f16) { - z := abs(y); - n = remainder(abs(x), z); + z := abs(y) + n = remainder(abs(x), z) if sign(n) < 0 { - n += z; + n += z } - return copy_sign(n, x); + return copy_sign(n, x) } mod_f16le :: proc(x, y: f16le) -> (n: f16le) { return #force_inline f16le(mod_f16(f16(x), f16(y))); } mod_f16be :: proc(x, y: f16be) -> (n: f16be) { return #force_inline f16be(mod_f16(f16(x), f16(y))); } mod_f32 :: proc(x, y: f32) -> (n: f32) { - z := abs(y); - n = remainder(abs(x), z); + z := abs(y) + n = remainder(abs(x), z) if sign(n) < 0 { - n += z; + n += z } - return copy_sign(n, x); + return copy_sign(n, x) } mod_f32le :: proc(x, y: f32le) -> (n: f32le) { return #force_inline f32le(mod_f32(f32(x), f32(y))); } mod_f32be :: proc(x, y: f32be) -> (n: f32be) { return #force_inline f32be(mod_f32(f32(x), f32(y))); } mod_f64 :: proc(x, y: f64) -> (n: f64) { - z := abs(y); - n = remainder(abs(x), z); + z := abs(y) + n = remainder(abs(x), z) if sign(n) < 0 { - n += z; + n += z } - return copy_sign(n, x); + return copy_sign(n, x) } mod_f64le :: proc(x, y: f64le) -> (n: f64le) { return #force_inline f64le(mod_f64(f64(x), f64(y))); } mod_f64be :: proc(x, y: f64be) -> (n: f64be) { return #force_inline f64be(mod_f64(f64(x), f64(y))); } @@ -780,7 +780,7 @@ mod :: proc{ mod_f16, mod_f16le, mod_f16be, mod_f32, mod_f32le, mod_f32be, mod_f64, mod_f64le, mod_f64be, -}; +} remainder_f16 :: proc(x, y: f16 ) -> f16 { return x - round(x/y) * y; } remainder_f16le :: proc(x, y: f16le) -> f16le { return x - round(x/y) * y; } @@ -795,95 +795,95 @@ remainder :: proc{ remainder_f16, remainder_f16le, remainder_f16be, remainder_f32, remainder_f32le, remainder_f32be, remainder_f64, remainder_f64le, remainder_f64be, -}; +} gcd :: proc(x, y: $T) -> T where intrinsics.type_is_ordered_numeric(T) { - x, y := x, y; + x, y := x, y for y != 0 { - x %= y; - x, y = y, x; + x %= y + x, y = y, x } - return abs(x); + return abs(x) } lcm :: proc(x, y: $T) -> T where intrinsics.type_is_ordered_numeric(T) { - return x / gcd(x, y) * y; + return x / gcd(x, y) * y } frexp_f16 :: proc(x: f16) -> (significand: f16, exponent: int) { - f, e := frexp_f64(f64(x)); - return f16(f), e; + f, e := frexp_f64(f64(x)) + return f16(f), e } frexp_f16le :: proc(x: f16le) -> (significand: f16le, exponent: int) { - f, e := frexp_f64(f64(x)); - return f16le(f), e; + f, e := frexp_f64(f64(x)) + return f16le(f), e } frexp_f16be :: proc(x: f16be) -> (significand: f16be, exponent: int) { - f, e := frexp_f64(f64(x)); - return f16be(f), e; + f, e := frexp_f64(f64(x)) + return f16be(f), e } frexp_f32 :: proc(x: f32) -> (significand: f32, exponent: int) { - f, e := frexp_f64(f64(x)); - return f32(f), e; + f, e := frexp_f64(f64(x)) + return f32(f), e } frexp_f32le :: proc(x: f32le) -> (significand: f32le, exponent: int) { - f, e := frexp_f64(f64(x)); - return f32le(f), e; + f, e := frexp_f64(f64(x)) + return f32le(f), e } frexp_f32be :: proc(x: f32be) -> (significand: f32be, exponent: int) { - f, e := frexp_f64(f64(x)); - return f32be(f), e; + f, e := frexp_f64(f64(x)) + return f32be(f), e } frexp_f64 :: proc(x: f64) -> (significand: f64, exponent: int) { switch { case x == 0: - return 0, 0; + return 0, 0 case x < 0: - significand, exponent = frexp(-x); - return -significand, exponent; + significand, exponent = frexp(-x) + return -significand, exponent } - ex := trunc(log2(x)); - exponent = int(ex); - significand = x / pow(2.0, ex); + ex := trunc(log2(x)) + exponent = int(ex) + significand = x / pow(2.0, ex) if abs(significand) >= 1 { - exponent += 1; - significand /= 2; + exponent += 1 + significand /= 2 } if exponent == 1024 && significand == 0 { - significand = 0.99999999999999988898; + significand = 0.99999999999999988898 } - return; + return } frexp_f64le :: proc(x: f64le) -> (significand: f64le, exponent: int) { - f, e := frexp_f64(f64(x)); - return f64le(f), e; + f, e := frexp_f64(f64(x)) + return f64le(f), e } frexp_f64be :: proc(x: f64be) -> (significand: f64be, exponent: int) { - f, e := frexp_f64(f64(x)); - return f64be(f), e; + f, e := frexp_f64(f64(x)) + return f64be(f), e } frexp :: proc{ frexp_f16, frexp_f16le, frexp_f16be, frexp_f32, frexp_f32le, frexp_f32be, frexp_f64, frexp_f64le, frexp_f64be, -}; +} binomial :: proc(n, k: int) -> int { switch { - case k <= 0: return 1; - case 2*k > n: return binomial(n, n-k); + case k <= 0: return 1 + case 2*k > n: return binomial(n, n-k) } - b := n; + b := n for i in 2..<k { - b = (b * (n+1-i))/i; + b = (b * (n+1-i))/i } - return b; + return b } factorial :: proc(n: int) -> int { @@ -910,7 +910,7 @@ factorial :: proc(n: int) -> int { 6_402_373_705_728_000, 121_645_100_408_832_000, 2_432_902_008_176_640_000, - }; + } } else { @static table := [13]int{ 1, @@ -926,88 +926,88 @@ factorial :: proc(n: int) -> int { 3_628_800, 39_916_800, 479_001_600, - }; + } } - assert(n >= 0, "parameter must not be negative"); - assert(n < len(table), "parameter is too large to lookup in the table"); - return table[n]; + assert(n >= 0, "parameter must not be negative") + assert(n < len(table), "parameter is too large to lookup in the table") + return table[n] } classify_f16 :: proc(x: f16) -> Float_Class { switch { case x == 0: - i := transmute(i16)x; + i := transmute(i16)x if i < 0 { - return .Neg_Zero; + return .Neg_Zero } - return .Zero; + return .Zero case x*0.5 == x: if x < 0 { - return .Neg_Inf; + return .Neg_Inf } - return .Inf; + return .Inf case !(x == x): - return .NaN; + return .NaN } - u := transmute(u16)x; - exp := int(u>>10) & (1<<5 - 1); + u := transmute(u16)x + exp := int(u>>10) & (1<<5 - 1) if exp == 0 { - return .Subnormal; + return .Subnormal } - return .Normal; + return .Normal } classify_f16le :: proc(x: f16le) -> Float_Class { return #force_inline classify_f16(f16(x)); } classify_f16be :: proc(x: f16be) -> Float_Class { return #force_inline classify_f16(f16(x)); } classify_f32 :: proc(x: f32) -> Float_Class { switch { case x == 0: - i := transmute(i32)x; + i := transmute(i32)x if i < 0 { - return .Neg_Zero; + return .Neg_Zero } - return .Zero; + return .Zero case x*0.5 == x: if x < 0 { - return .Neg_Inf; + return .Neg_Inf } - return .Inf; + return .Inf case !(x == x): - return .NaN; + return .NaN } - u := transmute(u32)x; - exp := int(u>>23) & (1<<8 - 1); + u := transmute(u32)x + exp := int(u>>23) & (1<<8 - 1) if exp == 0 { - return .Subnormal; + return .Subnormal } - return .Normal; + return .Normal } classify_f32le :: proc(x: f32le) -> Float_Class { return #force_inline classify_f32(f32(x)); } classify_f32be :: proc(x: f32be) -> Float_Class { return #force_inline classify_f32(f32(x)); } classify_f64 :: proc(x: f64) -> Float_Class { switch { case x == 0: - i := transmute(i64)x; + i := transmute(i64)x if i < 0 { - return .Neg_Zero; + return .Neg_Zero } - return .Zero; + return .Zero case x*0.5 == x: if x < 0 { - return .Neg_Inf; + return .Neg_Inf } - return .Inf; + return .Inf case !(x == x): - return .NaN; + return .NaN } - u := transmute(u64)x; - exp := int(u>>52) & (1<<11 - 1); + u := transmute(u64)x + exp := int(u>>52) & (1<<11 - 1) if exp == 0 { - return .Subnormal; + return .Subnormal } - return .Normal; + return .Normal } classify_f64le :: proc(x: f64le) -> Float_Class { return #force_inline classify_f64(f64(x)); } classify_f64be :: proc(x: f64be) -> Float_Class { return #force_inline classify_f64(f64(x)); } @@ -1015,7 +1015,7 @@ classify :: proc{ classify_f16, classify_f16le, classify_f16be, classify_f32, classify_f32le, classify_f32be, classify_f64, classify_f64le, classify_f64be, -}; +} is_nan_f16 :: proc(x: f16) -> bool { return classify(x) == .NaN; } is_nan_f16le :: proc(x: f16le) -> bool { return classify(x) == .NaN; } @@ -1030,209 +1030,209 @@ is_nan :: proc{ is_nan_f16, is_nan_f16le, is_nan_f16be, is_nan_f32, is_nan_f32le, is_nan_f32be, is_nan_f64, is_nan_f64le, is_nan_f64be, -}; +} // is_inf reports whether f is an infinity, according to sign. // If sign > 0, is_inf reports whether f is positive infinity. // If sign < 0, is_inf reports whether f is negative infinity. // If sign == 0, is_inf reports whether f is either infinity. is_inf_f16 :: proc(x: f16, sign: int = 0) -> bool { - class := classify(abs(x)); + class := classify(abs(x)) switch { case sign > 0: - return class == .Inf; + return class == .Inf case sign < 0: - return class == .Neg_Inf; + return class == .Neg_Inf } - return class == .Inf || class == .Neg_Inf; + return class == .Inf || class == .Neg_Inf } is_inf_f16le :: proc(x: f16le, sign: int = 0) -> bool { - return #force_inline is_inf_f16(f16(x), sign); + return #force_inline is_inf_f16(f16(x), sign) } is_inf_f16be :: proc(x: f16be, sign: int = 0) -> bool { - return #force_inline is_inf_f16(f16(x), sign); + return #force_inline is_inf_f16(f16(x), sign) } is_inf_f32 :: proc(x: f32, sign: int = 0) -> bool { - class := classify(abs(x)); + class := classify(abs(x)) switch { case sign > 0: - return class == .Inf; + return class == .Inf case sign < 0: - return class == .Neg_Inf; + return class == .Neg_Inf } - return class == .Inf || class == .Neg_Inf; + return class == .Inf || class == .Neg_Inf } is_inf_f32le :: proc(x: f32le, sign: int = 0) -> bool { - return #force_inline is_inf_f32(f32(x), sign); + return #force_inline is_inf_f32(f32(x), sign) } is_inf_f32be :: proc(x: f32be, sign: int = 0) -> bool { - return #force_inline is_inf_f32(f32(x), sign); + return #force_inline is_inf_f32(f32(x), sign) } is_inf_f64 :: proc(x: f64, sign: int = 0) -> bool { - class := classify(abs(x)); + class := classify(abs(x)) switch { case sign > 0: - return class == .Inf; + return class == .Inf case sign < 0: - return class == .Neg_Inf; + return class == .Neg_Inf } - return class == .Inf || class == .Neg_Inf; + return class == .Inf || class == .Neg_Inf } is_inf_f64le :: proc(x: f64le, sign: int = 0) -> bool { - return #force_inline is_inf_f64(f64(x), sign); + return #force_inline is_inf_f64(f64(x), sign) } is_inf_f64be :: proc(x: f64be, sign: int = 0) -> bool { - return #force_inline is_inf_f64(f64(x), sign); + return #force_inline is_inf_f64(f64(x), sign) } is_inf :: proc{ is_inf_f16, is_inf_f16le, is_inf_f16be, is_inf_f32, is_inf_f32le, is_inf_f32be, is_inf_f64, is_inf_f64le, is_inf_f64be, -}; +} inf_f16 :: proc(sign: int) -> f16 { - return f16(inf_f64(sign)); + return f16(inf_f64(sign)) } inf_f16le :: proc(sign: int) -> f16le { - return f16le(inf_f64(sign)); + return f16le(inf_f64(sign)) } inf_f16be :: proc(sign: int) -> f16be { - return f16be(inf_f64(sign)); + return f16be(inf_f64(sign)) } inf_f32 :: proc(sign: int) -> f32 { - return f32(inf_f64(sign)); + return f32(inf_f64(sign)) } inf_f32le :: proc(sign: int) -> f32le { - return f32le(inf_f64(sign)); + return f32le(inf_f64(sign)) } inf_f32be :: proc(sign: int) -> f32be { - return f32be(inf_f64(sign)); + return f32be(inf_f64(sign)) } inf_f64 :: proc(sign: int) -> f64 { - v: u64; + v: u64 if sign >= 0 { - v = 0x7ff00000_00000000; + v = 0x7ff00000_00000000 } else { - v = 0xfff00000_00000000; + v = 0xfff00000_00000000 } - return transmute(f64)v; + return transmute(f64)v } inf_f64le :: proc(sign: int) -> f64le { - return f64le(inf_f64(sign)); + return f64le(inf_f64(sign)) } inf_f64be :: proc(sign: int) -> f64be { - return f64be(inf_f64(sign)); + return f64be(inf_f64(sign)) } nan_f16 :: proc() -> f16 { - return f16(nan_f64()); + return f16(nan_f64()) } nan_f16le :: proc() -> f16le { - return f16le(nan_f64()); + return f16le(nan_f64()) } nan_f16be :: proc() -> f16be { - return f16be(nan_f64()); + return f16be(nan_f64()) } nan_f32 :: proc() -> f32 { - return f32(nan_f64()); + return f32(nan_f64()) } nan_f32le :: proc() -> f32le { - return f32le(nan_f64()); + return f32le(nan_f64()) } nan_f32be :: proc() -> f32be { - return f32be(nan_f64()); + return f32be(nan_f64()) } nan_f64 :: proc() -> f64 { - v: u64 = 0x7ff80000_00000001; - return transmute(f64)v; + v: u64 = 0x7ff80000_00000001 + return transmute(f64)v } nan_f64le :: proc() -> f64le { - return f64le(nan_f64()); + return f64le(nan_f64()) } nan_f64be :: proc() -> f64be { - return f64be(nan_f64()); + return f64be(nan_f64()) } is_power_of_two :: proc(x: int) -> bool { - return x > 0 && (x & (x-1)) == 0; + return x > 0 && (x & (x-1)) == 0 } next_power_of_two :: proc(x: int) -> int { - k := x -1; + k := x -1 when size_of(int) == 8 { - k = k | (k >> 32); + k = k | (k >> 32) } - k = k | (k >> 16); - k = k | (k >> 8); - k = k | (k >> 4); - k = k | (k >> 2); - k = k | (k >> 1); - k += 1 + int(x <= 0); - return k; + k = k | (k >> 16) + k = k | (k >> 8) + k = k | (k >> 4) + k = k | (k >> 2) + k = k | (k >> 1) + k += 1 + int(x <= 0) + return k } sum :: proc(x: $T/[]$E) -> (res: E) where intrinsics.type_is_numeric(E) { for i in x { - res += i; + res += i } - return; + return } prod :: proc(x: $T/[]$E) -> (res: E) where intrinsics.type_is_numeric(E) { for i in x { - res *= i; + res *= i } - return; + return } cumsum_inplace :: proc(x: $T/[]$E) -> T where intrinsics.type_is_numeric(E) { for i in 1..<len(x) { - x[i] = x[i-1] + x[i]; + x[i] = x[i-1] + x[i] } } cumsum :: proc(dst, src: $T/[]$E) -> T where intrinsics.type_is_numeric(E) { - N := min(len(dst), len(src)); + N := min(len(dst), len(src)) if N > 0 { - dst[0] = src[0]; + dst[0] = src[0] for i in 1..<N { - dst[i] = dst[i-1] + src[i]; + dst[i] = dst[i-1] + src[i] } } - return dst[:N]; + return dst[:N] } atan2_f16 :: proc(y, x: f16) -> f16 { // TODO(bill): Better atan2_f16 - return f16(atan2_f64(f64(y), f64(x))); + return f16(atan2_f64(f64(y), f64(x))) } atan2_f16le :: proc(y, x: f16le) -> f16le { // TODO(bill): Better atan2_f16 - return f16le(atan2_f64(f64(y), f64(x))); + return f16le(atan2_f64(f64(y), f64(x))) } atan2_f16be :: proc(y, x: f16be) -> f16be { // TODO(bill): Better atan2_f16 - return f16be(atan2_f64(f64(y), f64(x))); + return f16be(atan2_f64(f64(y), f64(x))) } atan2_f32 :: proc(y, x: f32) -> f32 { // TODO(bill): Better atan2_f32 - return f32(atan2_f64(f64(y), f64(x))); + return f32(atan2_f64(f64(y), f64(x))) } atan2_f32le :: proc(y, x: f32le) -> f32le { // TODO(bill): Better atan2_f32 - return f32le(atan2_f64(f64(y), f64(x))); + return f32le(atan2_f64(f64(y), f64(x))) } atan2_f32be :: proc(y, x: f32be) -> f32be { // TODO(bill): Better atan2_f32 - return f32be(atan2_f64(f64(y), f64(x))); + return f32be(atan2_f64(f64(y), f64(x))) } atan2_f64 :: proc(y, x: f64) -> f64 { @@ -1242,161 +1242,161 @@ atan2_f64 :: proc(y, x: f64) -> f64 { // Stephen L. Moshier // moshier@na-net.ornl.gov - NAN :: 0h7fff_ffff_ffff_ffff; - INF :: 0h7FF0_0000_0000_0000; - PI :: 0h4009_21fb_5444_2d18; + NAN :: 0h7fff_ffff_ffff_ffff + INF :: 0h7FF0_0000_0000_0000 + PI :: 0h4009_21fb_5444_2d18 atan :: proc(x: f64) -> f64 { if x == 0 { - return x; + return x } if x > 0 { - return s_atan(x); + return s_atan(x) } - return -s_atan(-x); + return -s_atan(-x) } // s_atan reduces its argument (known to be positive) to the range [0, 0.66] and calls x_atan. s_atan :: proc(x: f64) -> f64 { - MORE_BITS :: 6.123233995736765886130e-17; // pi/2 = PIO2 + MORE_BITS - TAN3PI08 :: 2.41421356237309504880; // tan(3*pi/8) + MORE_BITS :: 6.123233995736765886130e-17 // pi/2 = PIO2 + MORE_BITS + TAN3PI08 :: 2.41421356237309504880 // tan(3*pi/8) if x <= 0.66 { - return x_atan(x); + return x_atan(x) } if x > TAN3PI08 { - return PI/2 - x_atan(1/x) + MORE_BITS; + return PI/2 - x_atan(1/x) + MORE_BITS } - return PI/4 + x_atan((x-1)/(x+1)) + 0.5*MORE_BITS; + return PI/4 + x_atan((x-1)/(x+1)) + 0.5*MORE_BITS } // x_atan evaluates a series valid in the range [0, 0.66]. x_atan :: proc(x: f64) -> f64 { - P0 :: -8.750608600031904122785e-01; - P1 :: -1.615753718733365076637e+01; - P2 :: -7.500855792314704667340e+01; - P3 :: -1.228866684490136173410e+02; - P4 :: -6.485021904942025371773e+01; - Q0 :: +2.485846490142306297962e+01; - Q1 :: +1.650270098316988542046e+02; - Q2 :: +4.328810604912902668951e+02; - Q3 :: +4.853903996359136964868e+02; - Q4 :: +1.945506571482613964425e+02; - - z := x * x; - z = z * ((((P0*z+P1)*z+P2)*z+P3)*z + P4) / (((((z+Q0)*z+Q1)*z+Q2)*z+Q3)*z + Q4); - z = x*z + x; - return z; + P0 :: -8.750608600031904122785e-01 + P1 :: -1.615753718733365076637e+01 + P2 :: -7.500855792314704667340e+01 + P3 :: -1.228866684490136173410e+02 + P4 :: -6.485021904942025371773e+01 + Q0 :: +2.485846490142306297962e+01 + Q1 :: +1.650270098316988542046e+02 + Q2 :: +4.328810604912902668951e+02 + Q3 :: +4.853903996359136964868e+02 + Q4 :: +1.945506571482613964425e+02 + + z := x * x + z = z * ((((P0*z+P1)*z+P2)*z+P3)*z + P4) / (((((z+Q0)*z+Q1)*z+Q2)*z+Q3)*z + Q4) + z = x*z + x + return z } switch { case is_nan(y) || is_nan(x): - return NAN; + return NAN case y == 0: if x >= 0 && !sign_bit(x) { - return copy_sign(0.0, y); + return copy_sign(0.0, y) } - return copy_sign(PI, y); + return copy_sign(PI, y) case x == 0: - return copy_sign(PI*0.5, y); + return copy_sign(PI*0.5, y) case is_inf(x, 0): if is_inf(x, 1) { if is_inf(y, 0) { - return copy_sign(PI*0.25, y); + return copy_sign(PI*0.25, y) } - return copy_sign(0, y); + return copy_sign(0, y) } if is_inf(y, 0) { - return copy_sign(PI*0.75, y); + return copy_sign(PI*0.75, y) } - return copy_sign(PI, y); + return copy_sign(PI, y) case is_inf(y, 0): - return copy_sign(PI*0.5, y); + return copy_sign(PI*0.5, y) } - q := atan(y / x); + q := atan(y / x) if x < 0 { if q <= 0 { - return q + PI; + return q + PI } - return q - PI; + return q - PI } - return q; + return q } atan2_f64le :: proc(y, x: f64le) -> f64le { // TODO(bill): Better atan2_f32 - return f64le(atan2_f64(f64(y), f64(x))); + return f64le(atan2_f64(f64(y), f64(x))) } atan2_f64be :: proc(y, x: f64be) -> f64be { // TODO(bill): Better atan2_f32 - return f64be(atan2_f64(f64(y), f64(x))); + return f64be(atan2_f64(f64(y), f64(x))) } atan2 :: proc{ atan2_f16, atan2_f16le, atan2_f16be, atan2_f32, atan2_f32le, atan2_f32be, atan2_f64, atan2_f64le, atan2_f64be, -}; +} atan :: proc(x: $T) -> T where intrinsics.type_is_float(T) { - return atan2(x, 1); + return atan2(x, 1) } asin :: proc(x: $T) -> T where intrinsics.type_is_float(T) { - return atan2(x, 1 + sqrt(1 - x*x)); + return atan2(x, 1 + sqrt(1 - x*x)) } acos :: proc(x: $T) -> T where intrinsics.type_is_float(T) { - return 2 * atan2(sqrt(1 - x), sqrt(1 + x)); + return 2 * atan2(sqrt(1 - x), sqrt(1 + x)) } sinh :: proc(x: $T) -> T where intrinsics.type_is_float(T) { - return (exp(x) - exp(-x))*0.5; + return (exp(x) - exp(-x))*0.5 } cosh :: proc(x: $T) -> T where intrinsics.type_is_float(T) { - return (exp(x) + exp(-x))*0.5; + return (exp(x) + exp(-x))*0.5 } tanh :: proc(x: $T) -> T where intrinsics.type_is_float(T) { - t := exp(2*x); - return (t - 1) / (t + 1); -} - -F16_DIG :: 3; -F16_EPSILON :: 0.00097656; -F16_GUARD :: 0; -F16_MANT_DIG :: 11; -F16_MAX :: 65504.0; -F16_MAX_10_EXP :: 4; -F16_MAX_EXP :: 15; -F16_MIN :: 6.10351562e-5; -F16_MIN_10_EXP :: -4; -F16_MIN_EXP :: -14; -F16_NORMALIZE :: 0; -F16_RADIX :: 2; -F16_ROUNDS :: 1; - - -F32_DIG :: 6; -F32_EPSILON :: 1.192092896e-07; -F32_GUARD :: 0; -F32_MANT_DIG :: 24; -F32_MAX :: 3.402823466e+38; -F32_MAX_10_EXP :: 38; -F32_MAX_EXP :: 128; -F32_MIN :: 1.175494351e-38; -F32_MIN_10_EXP :: -37; -F32_MIN_EXP :: -125; -F32_NORMALIZE :: 0; -F32_RADIX :: 2; -F32_ROUNDS :: 1; - -F64_DIG :: 15; // # of decimal digits of precision -F64_EPSILON :: 2.2204460492503131e-016; // smallest such that 1.0+F64_EPSILON != 1.0 -F64_MANT_DIG :: 53; // # of bits in mantissa -F64_MAX :: 1.7976931348623158e+308; // max value -F64_MAX_10_EXP :: 308; // max decimal exponent -F64_MAX_EXP :: 1024; // max binary exponent -F64_MIN :: 2.2250738585072014e-308; // min positive value -F64_MIN_10_EXP :: -307; // min decimal exponent -F64_MIN_EXP :: -1021; // min binary exponent -F64_RADIX :: 2; // exponent radix -F64_ROUNDS :: 1; // addition rounding: near + t := exp(2*x) + return (t - 1) / (t + 1) +} + +F16_DIG :: 3 +F16_EPSILON :: 0.00097656 +F16_GUARD :: 0 +F16_MANT_DIG :: 11 +F16_MAX :: 65504.0 +F16_MAX_10_EXP :: 4 +F16_MAX_EXP :: 15 +F16_MIN :: 6.10351562e-5 +F16_MIN_10_EXP :: -4 +F16_MIN_EXP :: -14 +F16_NORMALIZE :: 0 +F16_RADIX :: 2 +F16_ROUNDS :: 1 + + +F32_DIG :: 6 +F32_EPSILON :: 1.192092896e-07 +F32_GUARD :: 0 +F32_MANT_DIG :: 24 +F32_MAX :: 3.402823466e+38 +F32_MAX_10_EXP :: 38 +F32_MAX_EXP :: 128 +F32_MIN :: 1.175494351e-38 +F32_MIN_10_EXP :: -37 +F32_MIN_EXP :: -125 +F32_NORMALIZE :: 0 +F32_RADIX :: 2 +F32_ROUNDS :: 1 + +F64_DIG :: 15 // # of decimal digits of precision +F64_EPSILON :: 2.2204460492503131e-016 // smallest such that 1.0+F64_EPSILON != 1.0 +F64_MANT_DIG :: 53 // # of bits in mantissa +F64_MAX :: 1.7976931348623158e+308 // max value +F64_MAX_10_EXP :: 308 // max decimal exponent +F64_MAX_EXP :: 1024 // max binary exponent +F64_MIN :: 2.2250738585072014e-308 // min positive value +F64_MIN_10_EXP :: -307 // min decimal exponent +F64_MIN_EXP :: -1021 // min binary exponent +F64_RADIX :: 2 // exponent radix +F64_ROUNDS :: 1 // addition rounding: near diff --git a/core/math/rand/normal.odin b/core/math/rand/normal.odin index 653ca6c3b..4a77543ba 100644 --- a/core/math/rand/normal.odin +++ b/core/math/rand/normal.odin @@ -18,7 +18,7 @@ import "core:math" // sample = norm_float64() * std_dev + mean // norm_float64 :: proc(r: ^Rand = nil) -> f64 { - rn :: 3.442619855899; + rn :: 3.442619855899 @(static) kn := [128]u32{ @@ -48,7 +48,7 @@ norm_float64 :: proc(r: ^Rand = nil) -> f64 { 0x7e3b737a, 0x7e268c2f, 0x7e0e3ff5, 0x7df1aa5d, 0x7dcf8c72, 0x7da61a1e, 0x7d72a0fb, 0x7d30e097, 0x7cd9b4ab, 0x7c600f1a, 0x7ba90bdc, 0x7a722176, 0x77d664e5, - }; + } @(static) wn := [128]f32{ @@ -84,7 +84,7 @@ norm_float64 :: proc(r: ^Rand = nil) -> f64 { 1.1781276e-09, 1.1962995e-09, 1.2158287e-09, 1.2369856e-09, 1.2601323e-09, 1.2857697e-09, 1.3146202e-09, 1.347784e-09, 1.3870636e-09, 1.4357403e-09, 1.5008659e-09, 1.6030948e-09, - }; + } @(static) fn := [128]f32{ @@ -114,39 +114,39 @@ norm_float64 :: proc(r: ^Rand = nil) -> f64 { 0.044660863, 0.040742867, 0.03688439, 0.033087887, 0.029356318, 0.025693292, 0.022103304, 0.018592102, 0.015167298, 0.011839478, 0.008624485, 0.005548995, 0.0026696292, - }; + } - r := r; + r := r if r == nil { // NOTE(bill, 2020-09-07): Do this so that people can // enforce the global random state if necessary with `nil` - r = &global_rand; + r = &global_rand } for { - j := i32(uint32(r)); - i := j & 0x7f; - x := f64(j) * f64(wn[i]); + j := i32(uint32(r)) + i := j & 0x7f + x := f64(j) * f64(wn[i]) if u32(abs(j)) < kn[i] { // 99% of the time this will be hit - return x; + return x } if i == 0 { for { - x = -math.ln(float64(r)) * (1.0/ rn); - y := -math.ln(float64(r)); + x = -math.ln(float64(r)) * (1.0/ rn) + y := -math.ln(float64(r)) if y+y >= x*x { - break; + break } } - return j > 0 ? rn + x : -rn - x; + return j > 0 ? rn + x : -rn - x } if fn[i]+f32(float64(r))*(fn[i-1]-fn[i]) < f32(math.exp(-0.5*x*x)) { - return x; + return x } } - return 0; // NOTE(bill): Will never be hit but this is here for sanity's sake + return 0 // NOTE(bill): Will never be hit but this is here for sanity's sake } diff --git a/core/math/rand/rand.odin b/core/math/rand/rand.odin index 812cdc53d..1a833d3ca 100644 --- a/core/math/rand/rand.odin +++ b/core/math/rand/rand.odin @@ -7,56 +7,56 @@ Rand :: struct { @(private) -_GLOBAL_SEED_DATA := 1234567890; +_GLOBAL_SEED_DATA := 1234567890 @(private) -global_rand := create(u64(uintptr(&_GLOBAL_SEED_DATA))); +global_rand := create(u64(uintptr(&_GLOBAL_SEED_DATA))) set_global_seed :: proc(seed: u64) { - init(&global_rand, seed); + init(&global_rand, seed) } create :: proc(seed: u64) -> Rand { - r: Rand; - init(&r, seed); - return r; + r: Rand + init(&r, seed) + return r } init :: proc(r: ^Rand, seed: u64) { - r.state = 0; - r.inc = (seed << 1) | 1; - _random(r); - r.state += seed; - _random(r); + r.state = 0 + r.inc = (seed << 1) | 1 + _random(r) + r.state += seed + _random(r) } _random :: proc(r: ^Rand) -> u32 { - r := r; + r := r if r == nil { // NOTE(bill, 2020-09-07): Do this so that people can // enforce the global random state if necessary with `nil` - r = &global_rand; + r = &global_rand } - old_state := r.state; - r.state = old_state * 6364136223846793005 + (r.inc|1); - xor_shifted := u32(((old_state>>18) ~ old_state) >> 27); - rot := u32(old_state >> 59); - return (xor_shifted >> rot) | (xor_shifted << ((-rot) & 31)); + old_state := r.state + r.state = old_state * 6364136223846793005 + (r.inc|1) + xor_shifted := u32(((old_state>>18) ~ old_state) >> 27) + rot := u32(old_state >> 59) + return (xor_shifted >> rot) | (xor_shifted << ((-rot) & 31)) } uint32 :: proc(r: ^Rand = nil) -> u32 { return _random(r); } uint64 :: proc(r: ^Rand = nil) -> u64 { - a := u64(_random(r)); - b := u64(_random(r)); - return (a<<32) | b; + a := u64(_random(r)) + b := u64(_random(r)) + return (a<<32) | b } uint128 :: proc(r: ^Rand = nil) -> u128 { - a := u128(_random(r)); - b := u128(_random(r)); - c := u128(_random(r)); - d := u128(_random(r)); - return (a<<96) | (b<<64) | (c<<32) | d; + a := u128(_random(r)) + b := u128(_random(r)) + c := u128(_random(r)) + d := u128(_random(r)) + return (a<<96) | (b<<64) | (c<<32) | d } int31 :: proc(r: ^Rand = nil) -> i32 { return i32(uint32(r) << 1 >> 1); } @@ -65,57 +65,57 @@ int127 :: proc(r: ^Rand = nil) -> i128 { return i128(uint128(r) << 1 >> 1); } int31_max :: proc(n: i32, r: ^Rand = nil) -> i32 { if n <= 0 { - panic("Invalid argument to int31_max"); + panic("Invalid argument to int31_max") } if n&(n-1) == 0 { - return int31(r) & (n-1); + return int31(r) & (n-1) } - max := i32((1<<31) - 1 - (1<<31)&u32(n)); - v := int31(r); + max := i32((1<<31) - 1 - (1<<31)&u32(n)) + v := int31(r) for v > max { - v = int31(r); + v = int31(r) } - return v % n; + return v % n } int63_max :: proc(n: i64, r: ^Rand = nil) -> i64 { if n <= 0 { - panic("Invalid argument to int63_max"); + panic("Invalid argument to int63_max") } if n&(n-1) == 0 { - return int63(r) & (n-1); + return int63(r) & (n-1) } - max := i64((1<<63) - 1 - (1<<63)&u64(n)); - v := int63(r); + max := i64((1<<63) - 1 - (1<<63)&u64(n)) + v := int63(r) for v > max { - v = int63(r); + v = int63(r) } - return v % n; + return v % n } int127_max :: proc(n: i128, r: ^Rand = nil) -> i128 { if n <= 0 { - panic("Invalid argument to int127_max"); + panic("Invalid argument to int127_max") } if n&(n-1) == 0 { - return int127(r) & (n-1); + return int127(r) & (n-1) } - max := i128((1<<63) - 1 - (1<<63)&u128(n)); - v := int127(r); + max := i128((1<<63) - 1 - (1<<63)&u128(n)) + v := int127(r) for v > max { - v = int127(r); + v = int127(r) } - return v % n; + return v % n } int_max :: proc(n: int, r: ^Rand = nil) -> int { if n <= 0 { - panic("Invalid argument to int_max"); + panic("Invalid argument to int_max") } when size_of(int) == 4 { - return int(int31_max(i32(n), r)); + return int(int31_max(i32(n), r)) } else { - return int(int63_max(i64(n), r)); + return int(int63_max(i64(n), r)) } } @@ -127,40 +127,40 @@ float32_range :: proc(lo, hi: f32, r: ^Rand = nil) -> f32 { return (hi-lo)*float read :: proc(p: []byte, r: ^Rand = nil) -> (n: int) { - pos := i8(0); - val := i64(0); + pos := i8(0) + val := i64(0) for n = 0; n < len(p); n += 1 { if pos == 0 { - val = int63(r); - pos = 7; + val = int63(r) + pos = 7 } - p[n] = byte(val); - val >>= 8; - pos -= 1; + p[n] = byte(val) + val >>= 8 + pos -= 1 } - return; + return } // perm returns a slice of n ints in a pseudo-random permutation of integers in the range [0, n) perm :: proc(n: int, r: ^Rand = nil) -> []int { - m := make([]int, n); + m := make([]int, n) for i := 0; i < n; i += 1 { - j := int_max(i+1, r); - m[i] = m[j]; - m[j] = i; + j := int_max(i+1, r) + m[i] = m[j] + m[j] = i } - return m; + return m } shuffle :: proc(array: $T/[]$E, r: ^Rand = nil) { - n := i64(len(array)); + n := i64(len(array)) if n < 2 { - return; + return } for i := i64(0); i < n; i += 1 { - j := int63_max(n, r); - array[i], array[j] = array[j], array[i]; + j := int63_max(n, r) + array[i], array[j] = array[j], array[i] } } diff --git a/core/mem/alloc.odin b/core/mem/alloc.odin index 4000ab92f..796d5c20a 100644 --- a/core/mem/alloc.odin +++ b/core/mem/alloc.odin @@ -3,7 +3,7 @@ package mem import "core:runtime" // NOTE(bill, 2019-12-31): These are defined in `package runtime` as they are used in the `context`. This is to prevent an import definition cycle. -Allocator_Mode :: runtime.Allocator_Mode; +Allocator_Mode :: runtime.Allocator_Mode /* Allocator_Mode :: enum byte { Alloc, @@ -14,12 +14,12 @@ Allocator_Mode :: enum byte { } */ -Allocator_Mode_Set :: runtime.Allocator_Mode_Set; +Allocator_Mode_Set :: runtime.Allocator_Mode_Set /* Allocator_Mode_Set :: distinct bit_set[Allocator_Mode]; */ -Allocator_Query_Info :: runtime.Allocator_Query_Info; +Allocator_Query_Info :: runtime.Allocator_Query_Info /* Allocator_Query_Info :: struct { pointer: rawptr, @@ -28,7 +28,7 @@ Allocator_Query_Info :: struct { } */ -Allocator_Error :: runtime.Allocator_Error; +Allocator_Error :: runtime.Allocator_Error /* Allocator_Error :: enum byte { None = 0, @@ -38,14 +38,14 @@ Allocator_Error :: enum byte { Mode_Not_Implemented = 4, } */ -Allocator_Proc :: runtime.Allocator_Proc; +Allocator_Proc :: runtime.Allocator_Proc /* Allocator_Proc :: #type proc(allocator_data: rawptr, mode: Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, location: Source_Code_Location = #caller_location) -> ([]byte, Allocator_Error); */ -Allocator :: runtime.Allocator; +Allocator :: runtime.Allocator /* Allocator :: struct { procedure: Allocator_Proc, @@ -53,148 +53,148 @@ Allocator :: struct { } */ -DEFAULT_ALIGNMENT :: 2*align_of(rawptr); +DEFAULT_ALIGNMENT :: 2*align_of(rawptr) alloc :: proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> rawptr { if size == 0 { - return nil; + return nil } if allocator.procedure == nil { - return nil; + return nil } - data, err := allocator.procedure(allocator.data, Allocator_Mode.Alloc, size, alignment, nil, 0, loc); - _ = err; - return raw_data(data); + data, err := allocator.procedure(allocator.data, Allocator_Mode.Alloc, size, alignment, nil, 0, loc) + _ = err + return raw_data(data) } alloc_bytes :: proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) { if size == 0 { - return nil, nil; + return nil, nil } if allocator.procedure == nil { - return nil, nil; + return nil, nil } - return allocator.procedure(allocator.data, Allocator_Mode.Alloc, size, alignment, nil, 0, loc); + return allocator.procedure(allocator.data, Allocator_Mode.Alloc, size, alignment, nil, 0, loc) } free :: proc(ptr: rawptr, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { if ptr == nil { - return nil; + return nil } if allocator.procedure == nil { - return nil; + return nil } - _, err := allocator.procedure(allocator.data, Allocator_Mode.Free, 0, 0, ptr, 0, loc); - return err; + _, err := allocator.procedure(allocator.data, Allocator_Mode.Free, 0, 0, ptr, 0, loc) + return err } free_bytes :: proc(bytes: []byte, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { if bytes == nil { - return nil; + return nil } if allocator.procedure == nil { - return nil; + return nil } - _, err := allocator.procedure(allocator.data, Allocator_Mode.Free, 0, 0, raw_data(bytes), len(bytes), loc); - return err; + _, err := allocator.procedure(allocator.data, Allocator_Mode.Free, 0, 0, raw_data(bytes), len(bytes), loc) + return err } free_all :: proc(allocator := context.allocator, loc := #caller_location) -> Allocator_Error { if allocator.procedure != nil { - _, err := allocator.procedure(allocator.data, Allocator_Mode.Free_All, 0, 0, nil, 0, loc); - return err; + _, err := allocator.procedure(allocator.data, Allocator_Mode.Free_All, 0, 0, nil, 0, loc) + return err } - return nil; + return nil } resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> rawptr { if allocator.procedure == nil { - return nil; + return nil } if new_size == 0 { if ptr != nil { - allocator.procedure(allocator.data, Allocator_Mode.Free, 0, 0, ptr, old_size, loc); + allocator.procedure(allocator.data, Allocator_Mode.Free, 0, 0, ptr, old_size, loc) } - return nil; + return nil } else if ptr == nil { - _, err := allocator.procedure(allocator.data, Allocator_Mode.Alloc, new_size, alignment, nil, 0, loc); - _ = err; - return nil; + _, err := allocator.procedure(allocator.data, Allocator_Mode.Alloc, new_size, alignment, nil, 0, loc) + _ = err + return nil } - data, err := allocator.procedure(allocator.data, Allocator_Mode.Resize, new_size, alignment, ptr, old_size, loc); + data, err := allocator.procedure(allocator.data, Allocator_Mode.Resize, new_size, alignment, ptr, old_size, loc) if err == .Mode_Not_Implemented { - data, err = allocator.procedure(allocator.data, Allocator_Mode.Alloc, new_size, alignment, nil, 0, loc); + data, err = allocator.procedure(allocator.data, Allocator_Mode.Alloc, new_size, alignment, nil, 0, loc) if err != nil { - return nil; + return nil } - runtime.copy(data, byte_slice(ptr, old_size)); - _, err = allocator.procedure(allocator.data, Allocator_Mode.Free, 0, 0, ptr, old_size, loc); - return raw_data(data); + runtime.copy(data, byte_slice(ptr, old_size)) + _, err = allocator.procedure(allocator.data, Allocator_Mode.Free, 0, 0, ptr, old_size, loc) + return raw_data(data) } - return raw_data(data); + return raw_data(data) } resize_bytes :: proc(old_data: []byte, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) { if allocator.procedure == nil { - return nil, nil; + return nil, nil } - ptr := raw_data(old_data); - old_size := len(old_data); + ptr := raw_data(old_data) + old_size := len(old_data) if new_size == 0 { if ptr != nil { - _, err := allocator.procedure(allocator.data, Allocator_Mode.Free, 0, 0, ptr, old_size, loc); - return nil, err; + _, err := allocator.procedure(allocator.data, Allocator_Mode.Free, 0, 0, ptr, old_size, loc) + return nil, err } - return nil, nil; + return nil, nil } else if ptr == nil { - return allocator.procedure(allocator.data, Allocator_Mode.Alloc, new_size, alignment, nil, 0, loc); + return allocator.procedure(allocator.data, Allocator_Mode.Alloc, new_size, alignment, nil, 0, loc) } - data, err := allocator.procedure(allocator.data, Allocator_Mode.Resize, new_size, alignment, ptr, old_size, loc); + data, err := allocator.procedure(allocator.data, Allocator_Mode.Resize, new_size, alignment, ptr, old_size, loc) if err == .Mode_Not_Implemented { - data, err = allocator.procedure(allocator.data, Allocator_Mode.Alloc, new_size, alignment, nil, 0, loc); + data, err = allocator.procedure(allocator.data, Allocator_Mode.Alloc, new_size, alignment, nil, 0, loc) if err != nil { - return data, err; + return data, err } - runtime.copy(data, old_data); - _, err = allocator.procedure(allocator.data, Allocator_Mode.Free, 0, 0, ptr, old_size, loc); + runtime.copy(data, old_data) + _, err = allocator.procedure(allocator.data, Allocator_Mode.Free, 0, 0, ptr, old_size, loc) } - return data, err; + return data, err } query_features :: proc(allocator: Allocator, loc := #caller_location) -> (set: Allocator_Mode_Set) { if allocator.procedure != nil { - allocator.procedure(allocator.data, Allocator_Mode.Query_Features, 0, 0, &set, 0, loc); - return set; + allocator.procedure(allocator.data, Allocator_Mode.Query_Features, 0, 0, &set, 0, loc) + return set } - return nil; + return nil } query_info :: proc(pointer: rawptr, allocator: Allocator, loc := #caller_location) -> (props: Allocator_Query_Info) { - props.pointer = pointer; + props.pointer = pointer if allocator.procedure != nil { - allocator.procedure(allocator.data, Allocator_Mode.Query_Info, 0, 0, &props, 0, loc); + allocator.procedure(allocator.data, Allocator_Mode.Query_Info, 0, 0, &props, 0, loc) } - return; + return } delete_string :: proc(str: string, allocator := context.allocator, loc := #caller_location) { - free(raw_data(str), allocator, loc); + free(raw_data(str), allocator, loc) } delete_cstring :: proc(str: cstring, allocator := context.allocator, loc := #caller_location) { - free((^byte)(str), allocator, loc); + free((^byte)(str), allocator, loc) } delete_dynamic_array :: proc(array: $T/[dynamic]$E, loc := #caller_location) { - free(raw_data(array), array.allocator, loc); + free(raw_data(array), array.allocator, loc) } delete_slice :: proc(array: $T/[]$E, allocator := context.allocator, loc := #caller_location) { - free(raw_data(array), allocator, loc); + free(raw_data(array), allocator, loc) } delete_map :: proc(m: $T/map[$K]$V, loc := #caller_location) { - raw := transmute(Raw_Map)m; - delete_slice(raw.hashes, raw.entries.allocator, loc); - free(raw.entries.data, raw.entries.allocator, loc); + raw := transmute(Raw_Map)m + delete_slice(raw.hashes, raw.entries.allocator, loc) + free(raw.entries.data, raw.entries.allocator, loc) } @@ -204,72 +204,72 @@ delete :: proc{ delete_dynamic_array, delete_slice, delete_map, -}; +} new :: proc($T: typeid, allocator := context.allocator, loc := #caller_location) -> (^T, Allocator_Error) { - return new_aligned(T, align_of(T), allocator, loc); + return new_aligned(T, align_of(T), allocator, loc) } new_aligned :: proc($T: typeid, alignment: int, allocator := context.allocator, loc := #caller_location) -> (t: ^T, err: Allocator_Error) { - data := alloc_bytes(size_of(T), alignment, allocator, loc) or_return; - t = (^T)(raw_data(data)); - return; + data := alloc_bytes(size_of(T), alignment, allocator, loc) or_return + t = (^T)(raw_data(data)) + return } new_clone :: proc(data: $T, allocator := context.allocator, loc := #caller_location) -> ^T { - data := alloc_bytes(size_of(T), alignment, allocator, loc) or_return; - t = (^T)(raw_data(data)); + data := alloc_bytes(size_of(T), alignment, allocator, loc) or_return + t = (^T)(raw_data(data)) if t != nil { - t^ = data; + t^ = data } - return; + return } -DEFAULT_RESERVE_CAPACITY :: 16; +DEFAULT_RESERVE_CAPACITY :: 16 make_aligned :: proc($T: typeid/[]$E, #any_int len: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> (slice: T, err: Allocator_Error) { - runtime.make_slice_error_loc(loc, len); - data := alloc_bytes(size_of(E)*len, alignment, allocator, loc) or_return; + runtime.make_slice_error_loc(loc, len) + data := alloc_bytes(size_of(E)*len, alignment, allocator, loc) or_return if data == nil && size_of(E) != 0 { - return; + return } - slice = transmute(T)Raw_Slice{raw_data(data), len}; - return; + slice = transmute(T)Raw_Slice{raw_data(data), len} + return } make_slice :: proc($T: typeid/[]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) { - return make_aligned(T, len, align_of(E), allocator, loc); + return make_aligned(T, len, align_of(E), allocator, loc) } make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) { - return make_dynamic_array_len_cap(T, 0, DEFAULT_RESERVE_CAPACITY, allocator, loc); + return make_dynamic_array_len_cap(T, 0, DEFAULT_RESERVE_CAPACITY, allocator, loc) } make_dynamic_array_len :: proc($T: typeid/[dynamic]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) { - return make_dynamic_array_len_cap(T, len, len, allocator, loc); + return make_dynamic_array_len_cap(T, len, len, allocator, loc) } make_dynamic_array_len_cap :: proc($T: typeid/[dynamic]$E, #any_int len: int, #any_int cap: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) { - runtime.make_dynamic_array_error_loc(loc, len, cap); - data := alloc_bytes(size_of(E)*cap, align_of(E), allocator, loc) or_return; - s := Raw_Dynamic_Array{raw_data(data), len, cap, allocator}; + runtime.make_dynamic_array_error_loc(loc, len, cap) + data := alloc_bytes(size_of(E)*cap, align_of(E), allocator, loc) or_return + s := Raw_Dynamic_Array{raw_data(data), len, cap, allocator} if data == nil && size_of(E) != 0 { - s.len, s.cap = 0, 0; + s.len, s.cap = 0, 0 } - array = transmute(T)s; - return; + array = transmute(T)s + return } make_map :: proc($T: typeid/map[$K]$E, #any_int cap: int = DEFAULT_RESERVE_CAPACITY, allocator := context.allocator, loc := #caller_location) -> T { - runtime.make_map_expr_error_loc(loc, cap); - context.allocator = allocator; + runtime.make_map_expr_error_loc(loc, cap) + context.allocator = allocator - m: T; - reserve_map(&m, cap); - return m; + m: T + reserve_map(&m, cap) + return m } make_multi_pointer :: proc($T: typeid/[^]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (mp: T, err: Allocator_Error) { - runtime.make_slice_error_loc(loc, len); - data := alloc_bytes(size_of(E)*len, align_of(E), allocator, loc) or_return; + runtime.make_slice_error_loc(loc, len) + data := alloc_bytes(size_of(E)*len, align_of(E), allocator, loc) or_return if data == nil && size_of(E) != 0 { - return; + return } - mp = cast(T)raw_data(data); - return; + mp = cast(T)raw_data(data) + return } make :: proc{ @@ -279,55 +279,55 @@ make :: proc{ make_dynamic_array_len_cap, make_map, make_multi_pointer, -}; +} default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment: int, allocator := context.allocator, loc := #caller_location) -> rawptr { if old_memory == nil { - return alloc(new_size, alignment, allocator, loc); + return alloc(new_size, alignment, allocator, loc) } if new_size == 0 { - free(old_memory, allocator, loc); - return nil; + free(old_memory, allocator, loc) + return nil } if new_size == old_size { - return old_memory; + return old_memory } - new_memory := alloc(new_size, alignment, allocator, loc); + new_memory := alloc(new_size, alignment, allocator, loc) if new_memory == nil { - return nil; + return nil } - copy(new_memory, old_memory, min(old_size, new_size)); - free(old_memory, allocator, loc); - return new_memory; + copy(new_memory, old_memory, min(old_size, new_size)) + free(old_memory, allocator, loc) + return new_memory } default_resize_bytes_align :: proc(old_data: []byte, new_size, alignment: int, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) { - old_memory := raw_data(old_data); - old_size := len(old_data); + old_memory := raw_data(old_data) + old_size := len(old_data) if old_memory == nil { - return alloc_bytes(new_size, alignment, allocator, loc); + return alloc_bytes(new_size, alignment, allocator, loc) } if new_size == 0 { - err := free_bytes(old_data, allocator, loc); - return nil, err; + err := free_bytes(old_data, allocator, loc) + return nil, err } if new_size == old_size { - return old_data, .None; + return old_data, .None } - new_memory, err := alloc_bytes(new_size, alignment, allocator, loc); + new_memory, err := alloc_bytes(new_size, alignment, allocator, loc) if new_memory == nil || err != nil { - return nil, err; + return nil, err } - runtime.copy(new_memory, old_data); - free_bytes(old_data, allocator, loc); - return new_memory, err; + runtime.copy(new_memory, old_data) + free_bytes(old_data, allocator, loc) + return new_memory, err } diff --git a/core/mem/allocators.odin b/core/mem/allocators.odin index d497017ad..b8bd9a065 100644 --- a/core/mem/allocators.odin +++ b/core/mem/allocators.odin @@ -6,14 +6,14 @@ import "core:runtime" nil_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, loc := #caller_location) -> ([]byte, Allocator_Error) { - return nil, nil; + return nil, nil } nil_allocator :: proc() -> Allocator { return Allocator{ procedure = nil_allocator_proc, data = nil, - }; + } } // Custom allocators @@ -32,76 +32,76 @@ Arena_Temp_Memory :: struct { init_arena :: proc(a: ^Arena, data: []byte) { - a.data = data; - a.offset = 0; - a.peak_used = 0; - a.temp_count = 0; + a.data = data + a.offset = 0 + a.peak_used = 0 + a.temp_count = 0 } arena_allocator :: proc(arena: ^Arena) -> Allocator { return Allocator{ procedure = arena_allocator_proc, data = arena, - }; + } } arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, location := #caller_location) -> ([]byte, Allocator_Error) { - arena := cast(^Arena)allocator_data; + arena := cast(^Arena)allocator_data switch mode { case .Alloc: - total_size := size + alignment; + total_size := size + alignment if arena.offset + total_size > len(arena.data) { - return nil, .Out_Of_Memory; + return nil, .Out_Of_Memory } - #no_bounds_check end := &arena.data[arena.offset]; + #no_bounds_check end := &arena.data[arena.offset] - ptr := align_forward(end, uintptr(alignment)); - arena.offset += total_size; - arena.peak_used = max(arena.peak_used, arena.offset); - zero(ptr, size); - return byte_slice(ptr, size), nil; + ptr := align_forward(end, uintptr(alignment)) + arena.offset += total_size + arena.peak_used = max(arena.peak_used, arena.offset) + zero(ptr, size) + return byte_slice(ptr, size), nil case .Free: - return nil, .Mode_Not_Implemented; + return nil, .Mode_Not_Implemented case .Free_All: - arena.offset = 0; + arena.offset = 0 case .Resize: - return default_resize_bytes_align(byte_slice(old_memory, old_size), size, alignment, arena_allocator(arena)); + return default_resize_bytes_align(byte_slice(old_memory, old_size), size, alignment, arena_allocator(arena)) case .Query_Features: - set := (^Allocator_Mode_Set)(old_memory); + set := (^Allocator_Mode_Set)(old_memory) if set != nil { - set^ = {.Alloc, .Free_All, .Resize, .Query_Features}; + set^ = {.Alloc, .Free_All, .Resize, .Query_Features} } - return nil, nil; + return nil, nil case .Query_Info: - return nil, .Mode_Not_Implemented; + return nil, .Mode_Not_Implemented } - return nil, nil; + return nil, nil } begin_arena_temp_memory :: proc(a: ^Arena) -> Arena_Temp_Memory { - tmp: Arena_Temp_Memory; - tmp.arena = a; - tmp.prev_offset = a.offset; - a.temp_count += 1; - return tmp; + tmp: Arena_Temp_Memory + tmp.arena = a + tmp.prev_offset = a.offset + a.temp_count += 1 + return tmp } end_arena_temp_memory :: proc(using tmp: Arena_Temp_Memory) { - assert(arena.offset >= prev_offset); - assert(arena.temp_count > 0); - arena.offset = prev_offset; - arena.temp_count -= 1; + assert(arena.offset >= prev_offset) + assert(arena.temp_count > 0) + arena.offset = prev_offset + arena.temp_count -= 1 } @@ -115,164 +115,164 @@ Scratch_Allocator :: struct { } scratch_allocator_init :: proc(s: ^Scratch_Allocator, size: int, backup_allocator := context.allocator) -> Allocator_Error { - s.data = make_aligned([]byte, size, 2*align_of(rawptr), backup_allocator) or_return; - s.curr_offset = 0; - s.prev_allocation = nil; - s.backup_allocator = backup_allocator; - s.leaked_allocations.allocator = backup_allocator; - return nil; + s.data = make_aligned([]byte, size, 2*align_of(rawptr), backup_allocator) or_return + s.curr_offset = 0 + s.prev_allocation = nil + s.backup_allocator = backup_allocator + s.leaked_allocations.allocator = backup_allocator + return nil } scratch_allocator_destroy :: proc(s: ^Scratch_Allocator) { if s == nil { - return; + return } for ptr in s.leaked_allocations { - free_bytes(ptr, s.backup_allocator); + free_bytes(ptr, s.backup_allocator) } - delete(s.leaked_allocations); - delete(s.data, s.backup_allocator); - s^ = {}; + delete(s.leaked_allocations) + delete(s.data, s.backup_allocator) + s^ = {} } scratch_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, loc := #caller_location) -> ([]byte, Allocator_Error) { - s := (^Scratch_Allocator)(allocator_data); + s := (^Scratch_Allocator)(allocator_data) if s.data == nil { - DEFAULT_BACKING_SIZE :: 1<<22; + DEFAULT_BACKING_SIZE :: 1<<22 if !(context.allocator.procedure != scratch_allocator_proc && context.allocator.data != allocator_data) { - panic("cyclic initialization of the scratch allocator with itself"); + panic("cyclic initialization of the scratch allocator with itself") } - scratch_allocator_init(s, DEFAULT_BACKING_SIZE); + scratch_allocator_init(s, DEFAULT_BACKING_SIZE) } - size := size; + size := size switch mode { case .Alloc: - size = align_forward_int(size, alignment); + size = align_forward_int(size, alignment) switch { case s.curr_offset+size <= len(s.data): - start := uintptr(raw_data(s.data)); - ptr := start + uintptr(s.curr_offset); - ptr = align_forward_uintptr(ptr, uintptr(alignment)); - zero(rawptr(ptr), size); + start := uintptr(raw_data(s.data)) + ptr := start + uintptr(s.curr_offset) + ptr = align_forward_uintptr(ptr, uintptr(alignment)) + zero(rawptr(ptr), size) - s.prev_allocation = rawptr(ptr); - offset := int(ptr - start); - s.curr_offset = offset + size; - return byte_slice(rawptr(ptr), size), nil; + s.prev_allocation = rawptr(ptr) + offset := int(ptr - start) + s.curr_offset = offset + size + return byte_slice(rawptr(ptr), size), nil case size <= len(s.data): - start := uintptr(raw_data(s.data)); - ptr := align_forward_uintptr(start, uintptr(alignment)); - zero(rawptr(ptr), size); + start := uintptr(raw_data(s.data)) + ptr := align_forward_uintptr(start, uintptr(alignment)) + zero(rawptr(ptr), size) - s.prev_allocation = rawptr(ptr); - offset := int(ptr - start); - s.curr_offset = offset + size; - return byte_slice(rawptr(ptr), size), nil; + s.prev_allocation = rawptr(ptr) + offset := int(ptr - start) + s.curr_offset = offset + size + return byte_slice(rawptr(ptr), size), nil } - a := s.backup_allocator; + a := s.backup_allocator if a.procedure == nil { - a = context.allocator; - s.backup_allocator = a; + a = context.allocator + s.backup_allocator = a } - ptr, err := alloc_bytes(size, alignment, a, loc); + ptr, err := alloc_bytes(size, alignment, a, loc) if err != nil { - return ptr, err; + return ptr, err } if s.leaked_allocations == nil { - s.leaked_allocations, err = make([dynamic][]byte, a); + s.leaked_allocations, err = make([dynamic][]byte, a) } - append(&s.leaked_allocations, ptr); + append(&s.leaked_allocations, ptr) if logger := context.logger; logger.lowest_level <= .Warning { if logger.procedure != nil { - logger.procedure(logger.data, .Warning, "mem.Scratch_Allocator resorted to backup_allocator" , logger.options, loc); + logger.procedure(logger.data, .Warning, "mem.Scratch_Allocator resorted to backup_allocator" , logger.options, loc) } } - return ptr, err; + return ptr, err case .Free: - start := uintptr(raw_data(s.data)); - end := start + uintptr(len(s.data)); - old_ptr := uintptr(old_memory); + start := uintptr(raw_data(s.data)) + end := start + uintptr(len(s.data)) + old_ptr := uintptr(old_memory) if s.prev_allocation == old_memory { - s.curr_offset = int(uintptr(s.prev_allocation) - start); - s.prev_allocation = nil; - return nil, nil; + s.curr_offset = int(uintptr(s.prev_allocation) - start) + s.prev_allocation = nil + return nil, nil } if start <= old_ptr && old_ptr < end { // NOTE(bill): Cannot free this pointer but it is valid - return nil, nil; + return nil, nil } if len(s.leaked_allocations) != 0 { for data, i in s.leaked_allocations { - ptr := raw_data(data); + ptr := raw_data(data) if ptr == old_memory { - free_bytes(data, s.backup_allocator); - ordered_remove(&s.leaked_allocations, i); - return nil, nil; + free_bytes(data, s.backup_allocator) + ordered_remove(&s.leaked_allocations, i) + return nil, nil } } } - return nil, .Invalid_Pointer; + return nil, .Invalid_Pointer // panic("invalid pointer passed to default_temp_allocator"); case .Free_All: - s.curr_offset = 0; - s.prev_allocation = nil; + s.curr_offset = 0 + s.prev_allocation = nil for ptr in s.leaked_allocations { - free_bytes(ptr, s.backup_allocator); + free_bytes(ptr, s.backup_allocator) } - clear(&s.leaked_allocations); + clear(&s.leaked_allocations) case .Resize: - begin := uintptr(raw_data(s.data)); - end := begin + uintptr(len(s.data)); - old_ptr := uintptr(old_memory); + begin := uintptr(raw_data(s.data)) + end := begin + uintptr(len(s.data)) + old_ptr := uintptr(old_memory) if begin <= old_ptr && old_ptr < end && old_ptr+uintptr(size) < end { - s.curr_offset = int(old_ptr-begin)+size; - return byte_slice(old_memory, size), nil; + s.curr_offset = int(old_ptr-begin)+size + return byte_slice(old_memory, size), nil } - data, err := scratch_allocator_proc(allocator_data, .Alloc, size, alignment, old_memory, old_size, loc); + data, err := scratch_allocator_proc(allocator_data, .Alloc, size, alignment, old_memory, old_size, loc) if err != nil { - return data, err; + return data, err } - runtime.copy(data, byte_slice(old_memory, old_size)); - _, err = scratch_allocator_proc(allocator_data, .Free, 0, alignment, old_memory, old_size, loc); - return data, err; + runtime.copy(data, byte_slice(old_memory, old_size)) + _, err = scratch_allocator_proc(allocator_data, .Free, 0, alignment, old_memory, old_size, loc) + return data, err case .Query_Features: - set := (^Allocator_Mode_Set)(old_memory); + set := (^Allocator_Mode_Set)(old_memory) if set != nil { - set^ = {.Alloc, .Free, .Free_All, .Resize, .Query_Features}; + set^ = {.Alloc, .Free, .Free_All, .Resize, .Query_Features} } - return nil, nil; + return nil, nil case .Query_Info: - return nil, .Mode_Not_Implemented; + return nil, .Mode_Not_Implemented } - return nil, nil; + return nil, nil } scratch_allocator :: proc(allocator: ^Scratch_Allocator) -> Allocator { return Allocator{ procedure = scratch_allocator_proc, data = allocator, - }; + } } @@ -293,143 +293,143 @@ Stack :: struct { } init_stack :: proc(s: ^Stack, data: []byte) { - s.data = data; - s.prev_offset = 0; - s.curr_offset = 0; - s.peak_used = 0; + s.data = data + s.prev_offset = 0 + s.curr_offset = 0 + s.peak_used = 0 } stack_allocator :: proc(stack: ^Stack) -> Allocator { return Allocator{ procedure = stack_allocator_proc, data = stack, - }; + } } stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, location := #caller_location) -> ([]byte, Allocator_Error) { - s := cast(^Stack)allocator_data; + s := cast(^Stack)allocator_data if s.data == nil { - return nil, .Invalid_Argument; + return nil, .Invalid_Argument } raw_alloc :: proc(s: ^Stack, size, alignment: int) -> ([]byte, Allocator_Error) { - curr_addr := uintptr(raw_data(s.data)) + uintptr(s.curr_offset); - padding := calc_padding_with_header(curr_addr, uintptr(alignment), size_of(Stack_Allocation_Header)); + curr_addr := uintptr(raw_data(s.data)) + uintptr(s.curr_offset) + padding := calc_padding_with_header(curr_addr, uintptr(alignment), size_of(Stack_Allocation_Header)) if s.curr_offset + padding + size > len(s.data) { - return nil, .Out_Of_Memory; + return nil, .Out_Of_Memory } - s.prev_offset = s.curr_offset; - s.curr_offset += padding; + s.prev_offset = s.curr_offset + s.curr_offset += padding - next_addr := curr_addr + uintptr(padding); - header := (^Stack_Allocation_Header)(next_addr - size_of(Stack_Allocation_Header)); - header.padding = padding; - header.prev_offset = s.prev_offset; + next_addr := curr_addr + uintptr(padding) + header := (^Stack_Allocation_Header)(next_addr - size_of(Stack_Allocation_Header)) + header.padding = padding + header.prev_offset = s.prev_offset - s.curr_offset += size; + s.curr_offset += size - s.peak_used = max(s.peak_used, s.curr_offset); + s.peak_used = max(s.peak_used, s.curr_offset) - zero(rawptr(next_addr), size); - return byte_slice(rawptr(next_addr), size), nil; + zero(rawptr(next_addr), size) + return byte_slice(rawptr(next_addr), size), nil } switch mode { case .Alloc: - return raw_alloc(s, size, alignment); + return raw_alloc(s, size, alignment) case .Free: if old_memory == nil { - return nil, nil; + return nil, nil } - start := uintptr(raw_data(s.data)); - end := start + uintptr(len(s.data)); - curr_addr := uintptr(old_memory); + start := uintptr(raw_data(s.data)) + end := start + uintptr(len(s.data)) + curr_addr := uintptr(old_memory) if !(start <= curr_addr && curr_addr < end) { - panic("Out of bounds memory address passed to stack allocator (free)"); + panic("Out of bounds memory address passed to stack allocator (free)") } if curr_addr >= start+uintptr(s.curr_offset) { // NOTE(bill): Allow double frees - return nil, nil; + return nil, nil } - header := (^Stack_Allocation_Header)(curr_addr - size_of(Stack_Allocation_Header)); - old_offset := int(curr_addr - uintptr(header.padding) - uintptr(raw_data(s.data))); + header := (^Stack_Allocation_Header)(curr_addr - size_of(Stack_Allocation_Header)) + old_offset := int(curr_addr - uintptr(header.padding) - uintptr(raw_data(s.data))) if old_offset != header.prev_offset { // panic("Out of order stack allocator free"); - return nil, .Invalid_Pointer; + return nil, .Invalid_Pointer } - s.curr_offset = old_offset; - s.prev_offset = header.prev_offset; + s.curr_offset = old_offset + s.prev_offset = header.prev_offset case .Free_All: - s.prev_offset = 0; - s.curr_offset = 0; + s.prev_offset = 0 + s.curr_offset = 0 case .Resize: if old_memory == nil { - return raw_alloc(s, size, alignment); + return raw_alloc(s, size, alignment) } if size == 0 { - return nil, nil; + return nil, nil } - start := uintptr(raw_data(s.data)); - end := start + uintptr(len(s.data)); - curr_addr := uintptr(old_memory); + start := uintptr(raw_data(s.data)) + end := start + uintptr(len(s.data)) + curr_addr := uintptr(old_memory) if !(start <= curr_addr && curr_addr < end) { - panic("Out of bounds memory address passed to stack allocator (resize)"); + panic("Out of bounds memory address passed to stack allocator (resize)") } if curr_addr >= start+uintptr(s.curr_offset) { // NOTE(bill): Allow double frees - return nil, nil; + return nil, nil } if old_size == size { - return byte_slice(old_memory, size), nil; + return byte_slice(old_memory, size), nil } - header := (^Stack_Allocation_Header)(curr_addr - size_of(Stack_Allocation_Header)); - old_offset := int(curr_addr - uintptr(header.padding) - uintptr(raw_data(s.data))); + header := (^Stack_Allocation_Header)(curr_addr - size_of(Stack_Allocation_Header)) + old_offset := int(curr_addr - uintptr(header.padding) - uintptr(raw_data(s.data))) if old_offset != header.prev_offset { - data, err := raw_alloc(s, size, alignment); + data, err := raw_alloc(s, size, alignment) if err == nil { - runtime.copy(data, byte_slice(old_memory, old_size)); + runtime.copy(data, byte_slice(old_memory, old_size)) } - return data, err; + return data, err } - old_memory_size := uintptr(s.curr_offset) - (curr_addr - start); - assert(old_memory_size == uintptr(old_size)); + old_memory_size := uintptr(s.curr_offset) - (curr_addr - start) + assert(old_memory_size == uintptr(old_size)) - diff := size - old_size; - s.curr_offset += diff; // works for smaller sizes too + diff := size - old_size + s.curr_offset += diff // works for smaller sizes too if diff > 0 { - zero(rawptr(curr_addr + uintptr(diff)), diff); + zero(rawptr(curr_addr + uintptr(diff)), diff) } - return byte_slice(old_memory, size), nil; + return byte_slice(old_memory, size), nil case .Query_Features: - set := (^Allocator_Mode_Set)(old_memory); + set := (^Allocator_Mode_Set)(old_memory) if set != nil { - set^ = {.Alloc, .Free, .Free_All, .Resize, .Query_Features}; + set^ = {.Alloc, .Free, .Free_All, .Resize, .Query_Features} } - return nil, nil; + return nil, nil case .Query_Info: - return nil, .Mode_Not_Implemented; + return nil, .Mode_Not_Implemented } - return nil, nil; + return nil, nil } @@ -450,121 +450,121 @@ Small_Stack :: struct { } init_small_stack :: proc(s: ^Small_Stack, data: []byte) { - s.data = data; - s.offset = 0; - s.peak_used = 0; + s.data = data + s.offset = 0 + s.peak_used = 0 } small_stack_allocator :: proc(stack: ^Small_Stack) -> Allocator { return Allocator{ procedure = small_stack_allocator_proc, data = stack, - }; + } } small_stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, ocation := #caller_location) -> ([]byte, Allocator_Error) { - s := cast(^Small_Stack)allocator_data; + s := cast(^Small_Stack)allocator_data if s.data == nil { - return nil, .Invalid_Argument; + return nil, .Invalid_Argument } - align := clamp(alignment, 1, 8*size_of(Stack_Allocation_Header{}.padding)/2); + align := clamp(alignment, 1, 8*size_of(Stack_Allocation_Header{}.padding)/2) raw_alloc :: proc(s: ^Small_Stack, size, alignment: int) -> ([]byte, Allocator_Error) { - curr_addr := uintptr(raw_data(s.data)) + uintptr(s.offset); - padding := calc_padding_with_header(curr_addr, uintptr(alignment), size_of(Small_Stack_Allocation_Header)); + curr_addr := uintptr(raw_data(s.data)) + uintptr(s.offset) + padding := calc_padding_with_header(curr_addr, uintptr(alignment), size_of(Small_Stack_Allocation_Header)) if s.offset + padding + size > len(s.data) { - return nil, .Out_Of_Memory; + return nil, .Out_Of_Memory } - s.offset += padding; + s.offset += padding - next_addr := curr_addr + uintptr(padding); - header := (^Small_Stack_Allocation_Header)(next_addr - size_of(Small_Stack_Allocation_Header)); - header.padding = auto_cast padding; + next_addr := curr_addr + uintptr(padding) + header := (^Small_Stack_Allocation_Header)(next_addr - size_of(Small_Stack_Allocation_Header)) + header.padding = auto_cast padding - s.offset += size; + s.offset += size - s.peak_used = max(s.peak_used, s.offset); + s.peak_used = max(s.peak_used, s.offset) - zero(rawptr(next_addr), size); - return byte_slice(rawptr(next_addr), size), nil; + zero(rawptr(next_addr), size) + return byte_slice(rawptr(next_addr), size), nil } switch mode { case .Alloc: - return raw_alloc(s, size, align); + return raw_alloc(s, size, align) case .Free: if old_memory == nil { - return nil, nil; + return nil, nil } - start := uintptr(raw_data(s.data)); - end := start + uintptr(len(s.data)); - curr_addr := uintptr(old_memory); + start := uintptr(raw_data(s.data)) + end := start + uintptr(len(s.data)) + curr_addr := uintptr(old_memory) if !(start <= curr_addr && curr_addr < end) { // panic("Out of bounds memory address passed to stack allocator (free)"); - return nil, .Invalid_Pointer; + return nil, .Invalid_Pointer } if curr_addr >= start+uintptr(s.offset) { // NOTE(bill): Allow double frees - return nil, nil; + return nil, nil } - header := (^Small_Stack_Allocation_Header)(curr_addr - size_of(Small_Stack_Allocation_Header)); - old_offset := int(curr_addr - uintptr(header.padding) - uintptr(raw_data(s.data))); + header := (^Small_Stack_Allocation_Header)(curr_addr - size_of(Small_Stack_Allocation_Header)) + old_offset := int(curr_addr - uintptr(header.padding) - uintptr(raw_data(s.data))) - s.offset = old_offset; + s.offset = old_offset case .Free_All: - s.offset = 0; + s.offset = 0 case .Resize: if old_memory == nil { - return raw_alloc(s, size, align); + return raw_alloc(s, size, align) } if size == 0 { - return nil, nil; + return nil, nil } - start := uintptr(raw_data(s.data)); - end := start + uintptr(len(s.data)); - curr_addr := uintptr(old_memory); + start := uintptr(raw_data(s.data)) + end := start + uintptr(len(s.data)) + curr_addr := uintptr(old_memory) if !(start <= curr_addr && curr_addr < end) { // panic("Out of bounds memory address passed to stack allocator (resize)"); - return nil, .Invalid_Pointer; + return nil, .Invalid_Pointer } if curr_addr >= start+uintptr(s.offset) { // NOTE(bill): Treat as a double free - return nil, nil; + return nil, nil } if old_size == size { - return byte_slice(old_memory, size), nil; + return byte_slice(old_memory, size), nil } - data, err := raw_alloc(s, size, align); + data, err := raw_alloc(s, size, align) if err == nil { - runtime.copy(data, byte_slice(old_memory, old_size)); + runtime.copy(data, byte_slice(old_memory, old_size)) } - return data, err; + return data, err case .Query_Features: - set := (^Allocator_Mode_Set)(old_memory); + set := (^Allocator_Mode_Set)(old_memory) if set != nil { - set^ = {.Alloc, .Free, .Free_All, .Resize, .Query_Features}; + set^ = {.Alloc, .Free, .Free_All, .Resize, .Query_Features} } - return nil, nil; + return nil, nil case .Query_Info: - return nil, .Mode_Not_Implemented; + return nil, .Mode_Not_Implemented } - return nil, nil; + return nil, nil } @@ -588,51 +588,51 @@ Dynamic_Pool :: struct { } -DYNAMIC_POOL_BLOCK_SIZE_DEFAULT :: 65536; -DYNAMIC_POOL_OUT_OF_BAND_SIZE_DEFAULT :: 6554; +DYNAMIC_POOL_BLOCK_SIZE_DEFAULT :: 65536 +DYNAMIC_POOL_OUT_OF_BAND_SIZE_DEFAULT :: 6554 dynamic_pool_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, loc := #caller_location) -> ([]byte, Allocator_Error) { - pool := (^Dynamic_Pool)(allocator_data); + pool := (^Dynamic_Pool)(allocator_data) switch mode { case .Alloc: - return dynamic_pool_alloc_bytes(pool, size); + return dynamic_pool_alloc_bytes(pool, size) case .Free: - return nil, .Mode_Not_Implemented; + return nil, .Mode_Not_Implemented case .Free_All: - dynamic_pool_free_all(pool); - return nil, nil; + dynamic_pool_free_all(pool) + return nil, nil case .Resize: if old_size >= size { - return byte_slice(old_memory, size), nil; + return byte_slice(old_memory, size), nil } - data, err := dynamic_pool_alloc_bytes(pool, size); + data, err := dynamic_pool_alloc_bytes(pool, size) if err == nil { - runtime.copy(data, byte_slice(old_memory, old_size)); + runtime.copy(data, byte_slice(old_memory, old_size)) } - return data, err; + return data, err case .Query_Features: - set := (^Allocator_Mode_Set)(old_memory); + set := (^Allocator_Mode_Set)(old_memory) if set != nil { - set^ = {.Alloc, .Free_All, .Resize, .Query_Features, .Query_Info}; + set^ = {.Alloc, .Free_All, .Resize, .Query_Features, .Query_Info} } - return nil, nil; + return nil, nil case .Query_Info: - info := (^Allocator_Query_Info)(old_memory); + info := (^Allocator_Query_Info)(old_memory) if info != nil && info.pointer != nil { - info.size = pool.block_size; - info.alignment = pool.alignment; - return byte_slice(info, size_of(info^)), nil; + info.size = pool.block_size + info.alignment = pool.alignment + return byte_slice(info, size_of(info^)), nil } - return nil, nil; + return nil, nil } - return nil, nil; + return nil, nil } @@ -640,7 +640,7 @@ dynamic_pool_allocator :: proc(pool: ^Dynamic_Pool) -> Allocator { return Allocator{ procedure = dynamic_pool_allocator_proc, data = pool, - }; + } } dynamic_pool_init :: proc(pool: ^Dynamic_Pool, @@ -649,112 +649,112 @@ dynamic_pool_init :: proc(pool: ^Dynamic_Pool, block_size := DYNAMIC_POOL_BLOCK_SIZE_DEFAULT, out_band_size := DYNAMIC_POOL_OUT_OF_BAND_SIZE_DEFAULT, alignment := 8) { - pool.block_size = block_size; - pool.out_band_size = out_band_size; - pool.alignment = alignment; - pool.block_allocator = block_allocator; - pool.out_band_allocations.allocator = array_allocator; - pool. unused_blocks.allocator = array_allocator; - pool. used_blocks.allocator = array_allocator; + pool.block_size = block_size + pool.out_band_size = out_band_size + pool.alignment = alignment + pool.block_allocator = block_allocator + pool.out_band_allocations.allocator = array_allocator + pool. unused_blocks.allocator = array_allocator + pool. used_blocks.allocator = array_allocator } dynamic_pool_destroy :: proc(using pool: ^Dynamic_Pool) { - dynamic_pool_free_all(pool); - delete(unused_blocks); - delete(used_blocks); + dynamic_pool_free_all(pool) + delete(unused_blocks) + delete(used_blocks) - zero(pool, size_of(pool^)); + zero(pool, size_of(pool^)) } dynamic_pool_alloc :: proc(pool: ^Dynamic_Pool, bytes: int) -> rawptr { - data, err := dynamic_pool_alloc_bytes(pool, bytes); - assert(err == nil); - return raw_data(data); + data, err := dynamic_pool_alloc_bytes(pool, bytes) + assert(err == nil) + return raw_data(data) } dynamic_pool_alloc_bytes :: proc(using pool: ^Dynamic_Pool, bytes: int) -> ([]byte, Allocator_Error) { cycle_new_block :: proc(using pool: ^Dynamic_Pool) -> (err: Allocator_Error) { if block_allocator.procedure == nil { - panic("You must call pool_init on a Pool before using it"); + panic("You must call pool_init on a Pool before using it") } if current_block != nil { - append(&used_blocks, current_block); + append(&used_blocks, current_block) } - new_block: rawptr; + new_block: rawptr if len(unused_blocks) > 0 { - new_block = pop(&unused_blocks); + new_block = pop(&unused_blocks) } else { - data: []byte; + data: []byte data, err = block_allocator.procedure(block_allocator.data, Allocator_Mode.Alloc, block_size, alignment, - nil, 0); - new_block = raw_data(data); + nil, 0) + new_block = raw_data(data) } - bytes_left = block_size; - current_pos = new_block; - current_block = new_block; - return; + bytes_left = block_size + current_pos = new_block + current_block = new_block + return } - n := bytes; - extra := alignment - (n % alignment); - n += extra; + n := bytes + extra := alignment - (n % alignment) + n += extra if n >= out_band_size { - assert(block_allocator.procedure != nil); + assert(block_allocator.procedure != nil) memory, err := block_allocator.procedure(block_allocator.data, Allocator_Mode.Alloc, block_size, alignment, - nil, 0); + nil, 0) if memory != nil { - append(&out_band_allocations, raw_data(memory)); + append(&out_band_allocations, raw_data(memory)) } - return memory, err; + return memory, err } if bytes_left < n { - err := cycle_new_block(pool); + err := cycle_new_block(pool) if err != nil { - return nil, err; + return nil, err } if current_block == nil { - return nil, .Out_Of_Memory; + return nil, .Out_Of_Memory } } - memory := current_pos; - current_pos = ptr_offset((^byte)(current_pos), n); - bytes_left -= n; - return byte_slice(memory, bytes), nil; + memory := current_pos + current_pos = ptr_offset((^byte)(current_pos), n) + bytes_left -= n + return byte_slice(memory, bytes), nil } dynamic_pool_reset :: proc(using pool: ^Dynamic_Pool) { if current_block != nil { - append(&unused_blocks, current_block); - current_block = nil; + append(&unused_blocks, current_block) + current_block = nil } for block in used_blocks { - append(&unused_blocks, block); + append(&unused_blocks, block) } - clear(&used_blocks); + clear(&used_blocks) for a in out_band_allocations { - free(a, block_allocator); + free(a, block_allocator) } - clear(&out_band_allocations); + clear(&out_band_allocations) } dynamic_pool_free_all :: proc(using pool: ^Dynamic_Pool) { - dynamic_pool_reset(pool); + dynamic_pool_reset(pool) for block in unused_blocks { - free(block, block_allocator); + free(block, block_allocator) } - clear(&unused_blocks); + clear(&unused_blocks) } @@ -765,38 +765,38 @@ panic_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, switch mode { case .Alloc: if size > 0 { - panic("mem: panic allocator, .Alloc called"); + panic("mem: panic allocator, .Alloc called") } case .Resize: if size > 0 { - panic("mem: panic allocator, .Resize called"); + panic("mem: panic allocator, .Resize called") } case .Free: if old_memory != nil { - panic("mem: panic allocator, .Free called"); + panic("mem: panic allocator, .Free called") } case .Free_All: - panic("mem: panic allocator, .Free_All called"); + panic("mem: panic allocator, .Free_All called") case .Query_Features: - set := (^Allocator_Mode_Set)(old_memory); + set := (^Allocator_Mode_Set)(old_memory) if set != nil { - set^ = {.Query_Features}; + set^ = {.Query_Features} } - return nil, nil; + return nil, nil case .Query_Info: - panic("mem: panic allocator, .Query_Info called"); + panic("mem: panic allocator, .Query_Info called") } - return nil, nil; + return nil, nil } panic_allocator :: proc() -> Allocator { return Allocator{ procedure = panic_allocator_proc, data = nil, - }; + } } @@ -819,57 +819,57 @@ Tracking_Allocator :: struct { } tracking_allocator_init :: proc(t: ^Tracking_Allocator, backing_allocator: Allocator, internals_allocator := context.allocator) { - t.backing = backing_allocator; - t.allocation_map.allocator = internals_allocator; - t.bad_free_array.allocator = internals_allocator; + t.backing = backing_allocator + t.allocation_map.allocator = internals_allocator + t.bad_free_array.allocator = internals_allocator } tracking_allocator_destroy :: proc(t: ^Tracking_Allocator) { - delete(t.allocation_map); - delete(t.bad_free_array); + delete(t.allocation_map) + delete(t.bad_free_array) } tracking_allocator :: proc(data: ^Tracking_Allocator) -> Allocator { return Allocator{ data = data, procedure = tracking_allocator_proc, - }; + } } tracking_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, loc := #caller_location) -> ([]byte, Allocator_Error) { - data := (^Tracking_Allocator)(allocator_data); + data := (^Tracking_Allocator)(allocator_data) if mode == .Query_Info { - info := (^Allocator_Query_Info)(old_memory); + info := (^Allocator_Query_Info)(old_memory) if info != nil && info.pointer != nil { if entry, ok := data.allocation_map[info.pointer]; ok { - info.size = entry.size; - info.alignment = entry.alignment; + info.size = entry.size + info.alignment = entry.alignment } - info.pointer = nil; + info.pointer = nil } - return nil, nil; + return nil, nil } - result: []byte; - err: Allocator_Error; + result: []byte + err: Allocator_Error if mode == .Free && old_memory not_in data.allocation_map { append(&data.bad_free_array, Tracking_Allocator_Bad_Free_Entry{ memory = old_memory, location = loc, - }); + }) } else { - result, err = data.backing.procedure(data.backing.data, mode, size, alignment, old_memory, old_size, loc); + result, err = data.backing.procedure(data.backing.data, mode, size, alignment, old_memory, old_size, loc) if err != nil { - return result, err; + return result, err } } - result_ptr := raw_data(result); + result_ptr := raw_data(result) if data.allocation_map.allocator.procedure == nil { - data.allocation_map.allocator = context.allocator; + data.allocation_map.allocator = context.allocator } switch mode { @@ -880,12 +880,12 @@ tracking_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, alignment = alignment, err = err, location = loc, - }; + } case .Free: - delete_key(&data.allocation_map, old_memory); + delete_key(&data.allocation_map, old_memory) case .Resize: if old_memory != result_ptr { - delete_key(&data.allocation_map, old_memory); + delete_key(&data.allocation_map, old_memory) } data.allocation_map[result_ptr] = Tracking_Allocator_Entry{ memory = result_ptr, @@ -893,24 +893,24 @@ tracking_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, alignment = alignment, err = err, location = loc, - }; + } case .Free_All: if data.clear_on_free_all { - clear_map(&data.allocation_map); + clear_map(&data.allocation_map) } case .Query_Features: - set := (^Allocator_Mode_Set)(old_memory); + set := (^Allocator_Mode_Set)(old_memory) if set != nil { - set^ = {.Alloc, .Free, .Free_All, .Resize, .Query_Features, .Query_Info}; + set^ = {.Alloc, .Free, .Free_All, .Resize, .Query_Features, .Query_Info} } - return nil, nil; + return nil, nil case .Query_Info: - unreachable(); + unreachable() } - return result, err; + return result, err } diff --git a/core/mem/mem.odin b/core/mem/mem.odin index 74e4d5d96..57ab943c2 100644 --- a/core/mem/mem.odin +++ b/core/mem/mem.odin @@ -4,66 +4,66 @@ import "core:runtime" import "core:intrinsics" set :: proc(data: rawptr, value: byte, len: int) -> rawptr { - return runtime.memset(data, i32(value), len); + return runtime.memset(data, i32(value), len) } zero :: proc(data: rawptr, len: int) -> rawptr { - return set(data, 0, len); + return set(data, 0, len) } zero_item :: proc(item: $P/^$T) { - set(item, 0, size_of(T)); + set(item, 0, size_of(T)) } zero_slice :: proc(data: $T/[]$E) { - zero(raw_data(data), size_of(E)*len(data)); + zero(raw_data(data), size_of(E)*len(data)) } copy :: proc(dst, src: rawptr, len: int) -> rawptr { - return runtime.mem_copy(dst, src, len); + return runtime.mem_copy(dst, src, len) } copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr { - return runtime.mem_copy_non_overlapping(dst, src, len); + return runtime.mem_copy_non_overlapping(dst, src, len) } compare :: proc(a, b: []byte) -> int { - res := compare_byte_ptrs(raw_data(a), raw_data(b), min(len(a), len(b))); + res := compare_byte_ptrs(raw_data(a), raw_data(b), min(len(a), len(b))) if res == 0 && len(a) != len(b) { - return len(a) <= len(b) ? -1 : +1; + return len(a) <= len(b) ? -1 : +1 } else if len(a) == 0 && len(b) == 0 { - return 0; + return 0 } - return res; + return res } compare_byte_ptrs :: proc(a, b: ^byte, n: int) -> int #no_bounds_check { switch { case a == b: - return 0; + return 0 case a == nil: - return -1; + return -1 case b == nil: - return -1; + return -1 case n == 0: - return 0; + return 0 } - x := slice_ptr(a, n); - y := slice_ptr(b, n); + x := slice_ptr(a, n) + y := slice_ptr(b, n) - SU :: size_of(uintptr); - fast := n/SU + 1; - offset := (fast-1)*SU; - curr_block := 0; + SU :: size_of(uintptr) + fast := n/SU + 1 + offset := (fast-1)*SU + curr_block := 0 if n < SU { - fast = 0; + fast = 0 } - la := slice_ptr((^uintptr)(a), fast); - lb := slice_ptr((^uintptr)(b), fast); + la := slice_ptr((^uintptr)(a), fast) + lb := slice_ptr((^uintptr)(b), fast) for /**/; curr_block < fast; curr_block += 1 { if la[curr_block] ~ lb[curr_block] != 0 { for pos := curr_block*SU; pos < n; pos += 1 { if x[pos] ~ y[pos] != 0 { - return (int(x[pos]) - int(y[pos])) < 0 ? -1 : +1; + return (int(x[pos]) - int(y[pos])) < 0 ? -1 : +1 } } } @@ -71,96 +71,96 @@ compare_byte_ptrs :: proc(a, b: ^byte, n: int) -> int #no_bounds_check { for /**/; offset < n; offset += 1 { if x[offset] ~ y[offset] != 0 { - return (int(x[offset]) - int(y[offset])) < 0 ? -1 : +1; + return (int(x[offset]) - int(y[offset])) < 0 ? -1 : +1 } } - return 0; + return 0 } check_zero :: proc(data: []byte) -> bool { - return check_zero_ptr(raw_data(data), len(data)); + return check_zero_ptr(raw_data(data), len(data)) } check_zero_ptr :: proc(ptr: rawptr, len: int) -> bool { switch { case len <= 0: - return true; + return true case ptr == nil: - return true; + return true } - start := uintptr(ptr); - start_aligned := align_forward_uintptr(start, align_of(uintptr)); - end := start + uintptr(len); - end_aligned := align_backward_uintptr(end, align_of(uintptr)); + start := uintptr(ptr) + start_aligned := align_forward_uintptr(start, align_of(uintptr)) + end := start + uintptr(len) + end_aligned := align_backward_uintptr(end, align_of(uintptr)) for b in start..<start_aligned { if (^byte)(b)^ != 0 { - return false; + return false } } for b := start_aligned; b < end_aligned; b += size_of(uintptr) { if (^uintptr)(b)^ != 0 { - return false; + return false } } for b in end_aligned..<end { if (^byte)(b)^ != 0 { - return false; + return false } } - return true; + return true } simple_equal :: proc(a, b: $T) -> bool where intrinsics.type_is_simple_compare(T) { - a, b := a, b; - return compare_byte_ptrs((^byte)(&a), (^byte)(&b), size_of(T)) == 0; + a, b := a, b + return compare_byte_ptrs((^byte)(&a), (^byte)(&b), size_of(T)) == 0 } compare_ptrs :: proc(a, b: rawptr, n: int) -> int { - return compare_byte_ptrs((^byte)(a), (^byte)(b), n); + return compare_byte_ptrs((^byte)(a), (^byte)(b), n) } ptr_offset :: proc(ptr: $P/^$T, n: int) -> P { - new := int(uintptr(ptr)) + size_of(T)*n; - return P(uintptr(new)); + new := int(uintptr(ptr)) + size_of(T)*n + return P(uintptr(new)) } ptr_sub :: proc(a, b: $P/^$T) -> int { - return (int(uintptr(a)) - int(uintptr(b)))/size_of(T); + return (int(uintptr(a)) - int(uintptr(b)))/size_of(T) } slice_ptr :: proc(ptr: ^$T, len: int) -> []T { - return ([^]T)(ptr)[:len]; + return ([^]T)(ptr)[:len] } byte_slice :: #force_inline proc "contextless" (data: rawptr, len: int) -> []byte { - return ([^]u8)(data)[:max(len, 0)]; + return ([^]u8)(data)[:max(len, 0)] } slice_to_bytes :: proc(slice: $E/[]$T) -> []byte { - s := transmute(Raw_Slice)slice; - s.len *= size_of(T); - return transmute([]byte)s; + s := transmute(Raw_Slice)slice + s.len *= size_of(T) + return transmute([]byte)s } slice_data_cast :: proc($T: typeid/[]$A, slice: $S/[]$B) -> T { when size_of(A) == 0 || size_of(B) == 0 { - return nil; + return nil } else { - s := transmute(Raw_Slice)slice; - s.len = (len(slice) * size_of(B)) / size_of(A); - return transmute(T)s; + s := transmute(Raw_Slice)slice + s.len = (len(slice) * size_of(B)) / size_of(A) + return transmute(T)s } } slice_to_components :: proc(slice: $E/[]$T) -> (data: ^T, len: int) { - s := transmute(Raw_Slice)slice; - return s.data, s.len; + s := transmute(Raw_Slice)slice + return s.data, s.len } buffer_from_slice :: proc(backing: $T/[]$E) -> [dynamic]E { @@ -169,18 +169,18 @@ buffer_from_slice :: proc(backing: $T/[]$E) -> [dynamic]E { len = 0, cap = len(backing), allocator = nil_allocator(), - }; + } } ptr_to_bytes :: proc(ptr: ^$T, len := 1) -> []byte { - assert(len >= 0); - return transmute([]byte)Raw_Slice{ptr, len*size_of(T)}; + assert(len >= 0) + return transmute([]byte)Raw_Slice{ptr, len*size_of(T)} } any_to_bytes :: proc(val: any) -> []byte { - ti := type_info_of(val.id); - size := ti != nil ? ti.size : 0; - return transmute([]byte)Raw_Slice{val.data, size}; + ti := type_info_of(val.id) + size := ti != nil ? ti.size : 0 + return transmute([]byte)Raw_Slice{val.data, size} } @@ -191,106 +191,106 @@ terabytes :: proc(x: int) -> int { return gigabytes(x) * 1024; } is_power_of_two :: proc(x: uintptr) -> bool { if x <= 0 { - return false; + return false } - return (x & (x-1)) == 0; + return (x & (x-1)) == 0 } align_forward :: proc(ptr: rawptr, align: uintptr) -> rawptr { - return rawptr(align_forward_uintptr(uintptr(ptr), align)); + return rawptr(align_forward_uintptr(uintptr(ptr), align)) } align_forward_uintptr :: proc(ptr, align: uintptr) -> uintptr { - assert(is_power_of_two(align)); + assert(is_power_of_two(align)) - p := ptr; - modulo := p & (align-1); + p := ptr + modulo := p & (align-1) if modulo != 0 { - p += align - modulo; + p += align - modulo } - return p; + return p } align_forward_int :: proc(ptr, align: int) -> int { - return int(align_forward_uintptr(uintptr(ptr), uintptr(align))); + return int(align_forward_uintptr(uintptr(ptr), uintptr(align))) } align_forward_uint :: proc(ptr, align: uint) -> uint { - return uint(align_forward_uintptr(uintptr(ptr), uintptr(align))); + return uint(align_forward_uintptr(uintptr(ptr), uintptr(align))) } align_backward :: proc(ptr: rawptr, align: uintptr) -> rawptr { - return rawptr(align_backward_uintptr(uintptr(ptr), align)); + return rawptr(align_backward_uintptr(uintptr(ptr), align)) } align_backward_uintptr :: proc(ptr, align: uintptr) -> uintptr { - assert(is_power_of_two(align)); - return align_forward_uintptr(ptr - align + 1, align); + assert(is_power_of_two(align)) + return align_forward_uintptr(ptr - align + 1, align) } align_backward_int :: proc(ptr, align: int) -> int { - return int(align_backward_uintptr(uintptr(ptr), uintptr(align))); + return int(align_backward_uintptr(uintptr(ptr), uintptr(align))) } align_backward_uint :: proc(ptr, align: uint) -> uint { - return uint(align_backward_uintptr(uintptr(ptr), uintptr(align))); + return uint(align_backward_uintptr(uintptr(ptr), uintptr(align))) } context_from_allocator :: proc(a: Allocator) -> type_of(context) { - context.allocator = a; - return context; + context.allocator = a + return context } reinterpret_copy :: proc($T: typeid, ptr: rawptr) -> (value: T) { - copy(&value, ptr, size_of(T)); - return; + copy(&value, ptr, size_of(T)) + return } -Fixed_Byte_Buffer :: distinct [dynamic]byte; +Fixed_Byte_Buffer :: distinct [dynamic]byte make_fixed_byte_buffer :: proc(backing: []byte) -> Fixed_Byte_Buffer { - s := transmute(Raw_Slice)backing; - d: Raw_Dynamic_Array; - d.data = s.data; - d.len = 0; - d.cap = s.len; - d.allocator = nil_allocator(); - return transmute(Fixed_Byte_Buffer)d; + s := transmute(Raw_Slice)backing + d: Raw_Dynamic_Array + d.data = s.data + d.len = 0 + d.cap = s.len + d.allocator = nil_allocator() + return transmute(Fixed_Byte_Buffer)d } align_formula :: proc(size, align: int) -> int { - result := size + align-1; - return result - result%align; + result := size + align-1 + return result - result%align } calc_padding_with_header :: proc(ptr: uintptr, align: uintptr, header_size: int) -> int { - p, a := ptr, align; - modulo := p & (a-1); + p, a := ptr, align + modulo := p & (a-1) - padding := uintptr(0); + padding := uintptr(0) if modulo != 0 { - padding = a - modulo; + padding = a - modulo } - needed_space := uintptr(header_size); + needed_space := uintptr(header_size) if padding < needed_space { - needed_space -= padding; + needed_space -= padding if needed_space & (a-1) > 0 { - padding += align * (1+(needed_space/align)); + padding += align * (1+(needed_space/align)) } else { - padding += align * (needed_space/align); + padding += align * (needed_space/align) } } - return int(padding); + return int(padding) } clone_slice :: proc(slice: $T/[]$E, allocator := context.allocator, loc := #caller_location) -> (new_slice: T) { - new_slice, _ = make(T, len(slice), allocator, loc); - runtime.copy(new_slice, slice); - return new_slice; + new_slice, _ = make(T, len(slice), allocator, loc) + runtime.copy(new_slice, slice) + return new_slice } diff --git a/core/mem/raw.odin b/core/mem/raw.odin index 99712e9e5..2c38f588c 100644 --- a/core/mem/raw.odin +++ b/core/mem/raw.odin @@ -31,31 +31,31 @@ Raw_Map :: struct { entries: Raw_Dynamic_Array, } -Raw_Complex64 :: struct {real, imag: f32}; -Raw_Complex128 :: struct {real, imag: f64}; -Raw_Quaternion128 :: struct {imag, jmag, kmag: f32, real: f32}; -Raw_Quaternion256 :: struct {imag, jmag, kmag: f64, real: f64}; -Raw_Quaternion128_Vector_Scalar :: struct {vector: [3]f32, scalar: f32}; -Raw_Quaternion256_Vector_Scalar :: struct {vector: [3]f64, scalar: f64}; +Raw_Complex64 :: struct {real, imag: f32} +Raw_Complex128 :: struct {real, imag: f64} +Raw_Quaternion128 :: struct {imag, jmag, kmag: f32, real: f32} +Raw_Quaternion256 :: struct {imag, jmag, kmag: f64, real: f64} +Raw_Quaternion128_Vector_Scalar :: struct {vector: [3]f32, scalar: f32} +Raw_Quaternion256_Vector_Scalar :: struct {vector: [3]f64, scalar: f64} make_any :: proc(data: rawptr, id: typeid) -> any { - return transmute(any)Raw_Any{data, id}; + return transmute(any)Raw_Any{data, id} } raw_array_data :: proc(a: $P/^($T/[$N]$E)) -> ^E { - return (^E)(a); + return (^E)(a) } raw_string_data :: proc(s: $T/string) -> ^byte { - return (transmute(Raw_String)s).data; + return (transmute(Raw_String)s).data } raw_slice_data :: proc(a: $T/[]$E) -> ^E { - return cast(^E)(transmute(Raw_Slice)a).data; + return cast(^E)(transmute(Raw_Slice)a).data } raw_dynamic_array_data :: proc(a: $T/[dynamic]$E) -> ^E { - return cast(^E)(transmute(Raw_Dynamic_Array)a).data; + return cast(^E)(transmute(Raw_Dynamic_Array)a).data } -raw_data :: proc{raw_array_data, raw_string_data, raw_slice_data, raw_dynamic_array_data}; +raw_data :: proc{raw_array_data, raw_string_data, raw_slice_data, raw_dynamic_array_data} Poly_Raw_Map_Entry :: struct($Key, $Value: typeid) { diff --git a/core/odin/ast/ast.odin b/core/odin/ast/ast.odin index 10bc538d3..2ed5c2b53 100644 --- a/core/odin/ast/ast.odin +++ b/core/odin/ast/ast.odin @@ -8,7 +8,7 @@ Proc_Tag :: enum { Optional_Ok, Optional_Second, } -Proc_Tags :: distinct bit_set[Proc_Tag; u32]; +Proc_Tags :: distinct bit_set[Proc_Tag; u32] Proc_Inlining :: enum u32 { None = 0, @@ -28,7 +28,7 @@ Node_State_Flag :: enum { Bounds_Check, No_Bounds_Check, } -Node_State_Flags :: distinct bit_set[Node_State_Flag]; +Node_State_Flags :: distinct bit_set[Node_State_Flag] Node :: struct { pos: tokenizer.Pos, @@ -526,18 +526,18 @@ Foreign_Import_Decl :: struct { // Other things unparen_expr :: proc(expr: ^Expr) -> (val: ^Expr) { - val = expr; + val = expr if expr == nil { - return; + return } for { - e, ok := val.derived.(Paren_Expr); + e, ok := val.derived.(Paren_Expr) if !ok || e.expr == nil { - break; + break } - val = e.expr; + val = e.expr } - return; + return } Field_Flag :: enum { @@ -554,16 +554,16 @@ Field_Flag :: enum { Typeid_Token, } -Field_Flags :: distinct bit_set[Field_Flag]; +Field_Flags :: distinct bit_set[Field_Flag] Field_Flags_Struct :: Field_Flags{ .Using, .Tags, -}; +} Field_Flags_Record_Poly_Params :: Field_Flags{ .Typeid_Token, .Default_Parameters, -}; +} Field_Flags_Signature :: Field_Flags{ .Ellipsis, .Using, @@ -571,10 +571,10 @@ Field_Flags_Signature :: Field_Flags{ .C_Vararg, .Auto_Cast, .Default_Parameters, -}; +} -Field_Flags_Signature_Params :: Field_Flags_Signature | {Field_Flag.Typeid_Token}; -Field_Flags_Signature_Results :: Field_Flags_Signature; +Field_Flags_Signature_Params :: Field_Flags_Signature | {Field_Flag.Typeid_Token} +Field_Flags_Signature_Results :: Field_Flags_Signature Proc_Group :: struct { diff --git a/core/odin/ast/clone.odin b/core/odin/ast/clone.odin index c6859c322..e42c5c39e 100644 --- a/core/odin/ast/clone.odin +++ b/core/odin/ast/clone.odin @@ -5,13 +5,13 @@ import "core:fmt" import "core:odin/tokenizer" new :: proc($T: typeid, pos, end: tokenizer.Pos) -> ^T { - n, _ := mem.new(T); - n.pos = pos; - n.end = end; - n.derived = n^; - base: ^Node = n; // dummy check - _ = base; // "Use" type to make -vet happy - return n; + n, _ := mem.new(T) + n.pos = pos + n.end = end + n.derived = n^ + base: ^Node = n // dummy check + _ = base // "Use" type to make -vet happy + return n } clone :: proc{ @@ -21,65 +21,65 @@ clone :: proc{ clone_decl, clone_array, clone_dynamic_array, -}; +} clone_array :: proc(array: $A/[]^$T) -> A { if len(array) == 0 { - return nil; + return nil } - res := make(A, len(array)); + res := make(A, len(array)) for elem, i in array { - res[i] = auto_cast clone(elem); + res[i] = auto_cast clone(elem) } - return res; + return res } clone_dynamic_array :: proc(array: $A/[dynamic]^$T) -> A { if len(array) == 0 { - return nil; + return nil } - res := make(A, len(array)); + res := make(A, len(array)) for elem, i in array { - res[i] = auto_cast clone(elem); + res[i] = auto_cast clone(elem) } - return res; + return res } clone_expr :: proc(node: ^Expr) -> ^Expr { - return cast(^Expr)clone_node(node); + return cast(^Expr)clone_node(node) } clone_stmt :: proc(node: ^Stmt) -> ^Stmt { - return cast(^Stmt)clone_node(node); + return cast(^Stmt)clone_node(node) } clone_decl :: proc(node: ^Decl) -> ^Decl { - return cast(^Decl)clone_node(node); + return cast(^Decl)clone_node(node) } clone_node :: proc(node: ^Node) -> ^Node { if node == nil { - return nil; + return nil } - size := size_of(Node); - align := align_of(Node); - ti := type_info_of(node.derived.id); + size := size_of(Node) + align := align_of(Node) + ti := type_info_of(node.derived.id) if ti != nil { - size = ti.size; - align = ti.align; + size = ti.size + align = ti.align } switch in node.derived { case Package, File: - panic("Cannot clone this node type"); + panic("Cannot clone this node type") } - res := cast(^Node)mem.alloc(size, align); - src: rawptr = node; + res := cast(^Node)mem.alloc(size, align) + src: rawptr = node if node.derived != nil { - src = node.derived.data; + src = node.derived.data } - mem.copy(res, src, size); - res.derived.data = rawptr(res); - res.derived.id = node.derived.id; + mem.copy(res, src, size) + res.derived.data = rawptr(res) + res.derived.id = node.derived.id switch r in &res.derived { case Bad_Expr: @@ -89,196 +89,196 @@ clone_node :: proc(node: ^Node) -> ^Node { case Basic_Lit: case Ellipsis: - r.expr = clone(r.expr); + r.expr = clone(r.expr) case Proc_Lit: - r.type = auto_cast clone(r.type); - r.body = clone(r.body); + r.type = auto_cast clone(r.type) + r.body = clone(r.body) case Comp_Lit: - r.type = clone(r.type); - r.elems = clone(r.elems); + r.type = clone(r.type) + r.elems = clone(r.elems) case Tag_Expr: - r.expr = clone(r.expr); + r.expr = clone(r.expr) case Unary_Expr: - r.expr = clone(r.expr); + r.expr = clone(r.expr) case Binary_Expr: - r.left = clone(r.left); - r.right = clone(r.right); + r.left = clone(r.left) + r.right = clone(r.right) case Paren_Expr: - r.expr = clone(r.expr); + r.expr = clone(r.expr) case Selector_Expr: - r.expr = clone(r.expr); - r.field = auto_cast clone(r.field); + r.expr = clone(r.expr) + r.field = auto_cast clone(r.field) case Implicit_Selector_Expr: - r.field = auto_cast clone(r.field); + r.field = auto_cast clone(r.field) case Selector_Call_Expr: - r.expr = clone(r.expr); - r.call = auto_cast clone(r.call); + r.expr = clone(r.expr) + r.call = auto_cast clone(r.call) case Index_Expr: - r.expr = clone(r.expr); - r.index = clone(r.index); + r.expr = clone(r.expr) + r.index = clone(r.index) case Deref_Expr: - r.expr = clone(r.expr); + r.expr = clone(r.expr) case Slice_Expr: - r.expr = clone(r.expr); - r.low = clone(r.low); - r.high = clone(r.high); + r.expr = clone(r.expr) + r.low = clone(r.low) + r.high = clone(r.high) case Call_Expr: - r.expr = clone(r.expr); - r.args = clone(r.args); + r.expr = clone(r.expr) + r.args = clone(r.args) case Field_Value: - r.field = clone(r.field); - r.value = clone(r.value); + r.field = clone(r.field) + r.value = clone(r.value) case Ternary_If_Expr: - r.x = clone(r.x); - r.cond = clone(r.cond); - r.y = clone(r.y); + r.x = clone(r.x) + r.cond = clone(r.cond) + r.y = clone(r.y) case Ternary_When_Expr: - r.x = clone(r.x); - r.cond = clone(r.cond); - r.y = clone(r.y); + r.x = clone(r.x) + r.cond = clone(r.cond) + r.y = clone(r.y) case Or_Else_Expr: - r.x = clone(r.x); - r.y = clone(r.y); + r.x = clone(r.x) + r.y = clone(r.y) case Or_Return_Expr: - r.expr = clone(r.expr); + r.expr = clone(r.expr) case Type_Assertion: - r.expr = clone(r.expr); - r.type = clone(r.type); + r.expr = clone(r.expr) + r.type = clone(r.type) case Type_Cast: - r.type = clone(r.type); - r.expr = clone(r.expr); + r.type = clone(r.type) + r.expr = clone(r.expr) case Auto_Cast: - r.expr = clone(r.expr); + r.expr = clone(r.expr) case Inline_Asm_Expr: - r.param_types = clone(r.param_types); - r.return_type = clone(r.return_type); - r.constraints_string = clone(r.constraints_string); - r.asm_string = clone(r.asm_string); + r.param_types = clone(r.param_types) + r.return_type = clone(r.return_type) + r.constraints_string = clone(r.constraints_string) + r.asm_string = clone(r.asm_string) case Bad_Stmt: // empty case Empty_Stmt: // empty case Expr_Stmt: - r.expr = clone(r.expr); + r.expr = clone(r.expr) case Tag_Stmt: - r.stmt = clone(r.stmt); + r.stmt = clone(r.stmt) case Assign_Stmt: - r.lhs = clone(r.lhs); - r.rhs = clone(r.rhs); + r.lhs = clone(r.lhs) + r.rhs = clone(r.rhs) case Block_Stmt: - r.label = auto_cast clone(r.label); - r.stmts = clone(r.stmts); + r.label = auto_cast clone(r.label) + r.stmts = clone(r.stmts) case If_Stmt: - r.label = auto_cast clone(r.label); - r.init = clone(r.init); - r.cond = clone(r.cond); - r.body = clone(r.body); - r.else_stmt = clone(r.else_stmt); + r.label = auto_cast clone(r.label) + r.init = clone(r.init) + r.cond = clone(r.cond) + r.body = clone(r.body) + r.else_stmt = clone(r.else_stmt) case When_Stmt: - r.cond = clone(r.cond); - r.body = clone(r.body); - r.else_stmt = clone(r.else_stmt); + r.cond = clone(r.cond) + r.body = clone(r.body) + r.else_stmt = clone(r.else_stmt) case Return_Stmt: - r.results = clone(r.results); + r.results = clone(r.results) case Defer_Stmt: - r.stmt = clone(r.stmt); + r.stmt = clone(r.stmt) case For_Stmt: - r.label = auto_cast clone(r.label); - r.init = clone(r.init); - r.cond = clone(r.cond); - r.post = clone(r.post); - r.body = clone(r.body); + r.label = auto_cast clone(r.label) + r.init = clone(r.init) + r.cond = clone(r.cond) + r.post = clone(r.post) + r.body = clone(r.body) case Range_Stmt: - r.label = auto_cast clone(r.label); - r.vals = clone(r.vals); - r.expr = clone(r.expr); - r.body = clone(r.body); + r.label = auto_cast clone(r.label) + r.vals = clone(r.vals) + r.expr = clone(r.expr) + r.body = clone(r.body) case Case_Clause: - r.list = clone(r.list); - r.body = clone(r.body); + r.list = clone(r.list) + r.body = clone(r.body) case Switch_Stmt: - r.label = auto_cast clone(r.label); - r.init = clone(r.init); - r.cond = clone(r.cond); - r.body = clone(r.body); + r.label = auto_cast clone(r.label) + r.init = clone(r.init) + r.cond = clone(r.cond) + r.body = clone(r.body) case Type_Switch_Stmt: - r.label = auto_cast clone(r.label); - r.tag = clone(r.tag); - r.expr = clone(r.expr); - r.body = clone(r.body); + r.label = auto_cast clone(r.label) + r.tag = clone(r.tag) + r.expr = clone(r.expr) + r.body = clone(r.body) case Branch_Stmt: - r.label = auto_cast clone(r.label); + r.label = auto_cast clone(r.label) case Using_Stmt: - r.list = clone(r.list); + r.list = clone(r.list) case Bad_Decl: case Value_Decl: - r.attributes = clone(r.attributes); - r.names = clone(r.names); - r.type = clone(r.type); - r.values = clone(r.values); + r.attributes = clone(r.attributes) + r.names = clone(r.names) + r.type = clone(r.type) + r.values = clone(r.values) case Package_Decl: case Import_Decl: case Foreign_Block_Decl: - r.attributes = clone(r.attributes); - r.foreign_library = clone(r.foreign_library); - r.body = clone(r.body); + r.attributes = clone(r.attributes) + r.foreign_library = clone(r.foreign_library) + r.body = clone(r.body) case Foreign_Import_Decl: - r.name = auto_cast clone(r.name); + r.name = auto_cast clone(r.name) case Proc_Group: - r.args = clone(r.args); + r.args = clone(r.args) case Attribute: - r.elems = clone(r.elems); + r.elems = clone(r.elems) case Field: - r.names = clone(r.names); - r.type = clone(r.type); - r.default_value = clone(r.default_value); + r.names = clone(r.names) + r.type = clone(r.type) + r.default_value = clone(r.default_value) case Field_List: - r.list = clone(r.list); + r.list = clone(r.list) case Typeid_Type: - r.specialization = clone(r.specialization); + r.specialization = clone(r.specialization) case Helper_Type: - r.type = clone(r.type); + r.type = clone(r.type) case Distinct_Type: - r.type = clone(r.type); + r.type = clone(r.type) case Poly_Type: - r.type = auto_cast clone(r.type); - r.specialization = clone(r.specialization); + r.type = auto_cast clone(r.type) + r.specialization = clone(r.specialization) case Proc_Type: - r.params = auto_cast clone(r.params); - r.results = auto_cast clone(r.results); + r.params = auto_cast clone(r.params) + r.results = auto_cast clone(r.results) case Pointer_Type: - r.elem = clone(r.elem); + r.elem = clone(r.elem) case Multi_Pointer_Type: - r.elem = clone(r.elem); + r.elem = clone(r.elem) case Array_Type: - r.len = clone(r.len); - r.elem = clone(r.elem); + r.len = clone(r.len) + r.elem = clone(r.elem) case Dynamic_Array_Type: - r.elem = clone(r.elem); + r.elem = clone(r.elem) case Struct_Type: - r.poly_params = auto_cast clone(r.poly_params); - r.align = clone(r.align); - r.fields = auto_cast clone(r.fields); + r.poly_params = auto_cast clone(r.poly_params) + r.align = clone(r.align) + r.fields = auto_cast clone(r.fields) case Union_Type: - r.poly_params = auto_cast clone(r.poly_params); - r.align = clone(r.align); - r.variants = clone(r.variants); + r.poly_params = auto_cast clone(r.poly_params) + r.align = clone(r.align) + r.variants = clone(r.variants) case Enum_Type: - r.base_type = clone(r.base_type); - r.fields = clone(r.fields); + r.base_type = clone(r.base_type) + r.fields = clone(r.fields) case Bit_Set_Type: - r.elem = clone(r.elem); - r.underlying = clone(r.underlying); + r.elem = clone(r.elem) + r.underlying = clone(r.underlying) case Map_Type: - r.key = clone(r.key); - r.value = clone(r.value); + r.key = clone(r.key) + r.value = clone(r.value) case: - fmt.panicf("Unhandled node kind: %T", r); + fmt.panicf("Unhandled node kind: %T", r) } - return res; + return res } diff --git a/core/odin/ast/walk.odin b/core/odin/ast/walk.odin index c6922fb35..f394a5e33 100644 --- a/core/odin/ast/walk.odin +++ b/core/odin/ast/walk.odin @@ -18,15 +18,15 @@ Visitor :: struct { inspect :: proc(node: ^Node, f: proc(^Node) -> bool) { v := &Visitor{ visit = proc(v: ^Visitor, node: ^Node) -> ^Visitor { - f := (proc(^Node) -> bool)(v.data); + f := (proc(^Node) -> bool)(v.data) if f(node) { - return v; + return v } - return nil; + return nil }, data = rawptr(f), - }; - walk(v, node); + } + walk(v, node) } @@ -37,36 +37,36 @@ inspect :: proc(node: ^Node, f: proc(^Node) -> bool) { walk :: proc(v: ^Visitor, node: ^Node) { walk_expr_list :: proc(v: ^Visitor, list: []^Expr) { for x in list { - walk(v, x); + walk(v, x) } } walk_stmt_list :: proc(v: ^Visitor, list: []^Stmt) { for x in list { - walk(v, x); + walk(v, x) } } walk_attribute_list :: proc(v: ^Visitor, list: []^Attribute) { for x in list { - walk(v, x); + walk(v, x) } } - v := v; + v := v if v = v->visit(node); v == nil { - return; + return } switch n in &node.derived { case File: if n.docs != nil { - walk(v, n.docs); + walk(v, n.docs) } - walk_stmt_list(v, n.decls[:]); + walk_stmt_list(v, n.decls[:]) case Package: for _, f in n.files { - walk(v, f); + walk(v, f) } case Comment_Group: @@ -79,330 +79,330 @@ walk :: proc(v: ^Visitor, node: ^Node) { case Basic_Directive: case Ellipsis: if n.expr != nil { - walk(v, n.expr); + walk(v, n.expr) } case Proc_Lit: - walk(v, n.type); - walk(v, n.body); - walk_expr_list(v, n.where_clauses); + walk(v, n.type) + walk(v, n.body) + walk_expr_list(v, n.where_clauses) case Comp_Lit: if n.type != nil { - walk(v, n.type); + walk(v, n.type) } - walk_expr_list(v, n.elems); + walk_expr_list(v, n.elems) case Tag_Expr: - walk(v, n.expr); + walk(v, n.expr) case Unary_Expr: - walk(v, n.expr); + walk(v, n.expr) case Binary_Expr: - walk(v, n.left); - walk(v, n.right); + walk(v, n.left) + walk(v, n.right) case Paren_Expr: - walk(v, n.expr); + walk(v, n.expr) case Selector_Expr: - walk(v, n.expr); - walk(v, n.field); + walk(v, n.expr) + walk(v, n.field) case Implicit_Selector_Expr: - walk(v, n.field); + walk(v, n.field) case Selector_Call_Expr: - walk(v, n.expr); - walk(v, n.call); + walk(v, n.expr) + walk(v, n.call) case Index_Expr: - walk(v, n.expr); - walk(v, n.index); + walk(v, n.expr) + walk(v, n.index) case Deref_Expr: - walk(v, n.expr); + walk(v, n.expr) case Slice_Expr: - walk(v, n.expr); + walk(v, n.expr) if n.low != nil { - walk(v, n.low); + walk(v, n.low) } if n.high != nil { - walk(v, n.high); + walk(v, n.high) } case Call_Expr: - walk(v, n.expr); - walk_expr_list(v, n.args); + walk(v, n.expr) + walk_expr_list(v, n.args) case Field_Value: - walk(v, n.field); - walk(v, n.value); + walk(v, n.field) + walk(v, n.value) case Ternary_If_Expr: - walk(v, n.x); - walk(v, n.cond); - walk(v, n.y); + walk(v, n.x) + walk(v, n.cond) + walk(v, n.y) case Ternary_When_Expr: - walk(v, n.x); - walk(v, n.cond); - walk(v, n.y); + walk(v, n.x) + walk(v, n.cond) + walk(v, n.y) case Or_Else_Expr: - walk(v, n.x); - walk(v, n.y); + walk(v, n.x) + walk(v, n.y) case Or_Return_Expr: - walk(v, n.expr); + walk(v, n.expr) case Type_Assertion: - walk(v, n.expr); + walk(v, n.expr) if n.type != nil { - walk(v, n.type); + walk(v, n.type) } case Type_Cast: - walk(v, n.type); - walk(v, n.expr); + walk(v, n.type) + walk(v, n.expr) case Auto_Cast: - walk(v, n.expr); + walk(v, n.expr) case Inline_Asm_Expr: - walk_expr_list(v, n.param_types); - walk(v, n.return_type); - walk(v, n.constraints_string); - walk(v, n.asm_string); + walk_expr_list(v, n.param_types) + walk(v, n.return_type) + walk(v, n.constraints_string) + walk(v, n.asm_string) case Bad_Stmt: case Empty_Stmt: case Expr_Stmt: - walk(v, n.expr); + walk(v, n.expr) case Tag_Stmt: - walk(v, n.stmt); + walk(v, n.stmt) case Assign_Stmt: - walk_expr_list(v, n.lhs); - walk_expr_list(v, n.rhs); + walk_expr_list(v, n.lhs) + walk_expr_list(v, n.rhs) case Block_Stmt: if n.label != nil { - walk(v, n.label); + walk(v, n.label) } - walk_stmt_list(v, n.stmts); + walk_stmt_list(v, n.stmts) case If_Stmt: if n.label != nil { - walk(v, n.label); + walk(v, n.label) } if n.init != nil { - walk(v, n.init); + walk(v, n.init) } - walk(v, n.cond); - walk(v, n.body); + walk(v, n.cond) + walk(v, n.body) if n.else_stmt != nil { - walk(v, n.else_stmt); + walk(v, n.else_stmt) } case When_Stmt: - walk(v, n.cond); - walk(v, n.body); + walk(v, n.cond) + walk(v, n.body) if n.else_stmt != nil { - walk(v, n.else_stmt); + walk(v, n.else_stmt) } case Return_Stmt: - walk_expr_list(v, n.results); + walk_expr_list(v, n.results) case Defer_Stmt: - walk(v, n.stmt); + walk(v, n.stmt) case For_Stmt: if n.label != nil { - walk(v, n.label); + walk(v, n.label) } if n.init != nil { - walk(v, n.init); + walk(v, n.init) } if n.cond != nil { - walk(v, n.cond); + walk(v, n.cond) } if n.post != nil { - walk(v, n.post); + walk(v, n.post) } - walk(v, n.body); + walk(v, n.body) case Range_Stmt: if n.label != nil { - walk(v, n.label); + walk(v, n.label) } for val in n.vals { if val != nil { - walk(v, val); + walk(v, val) } } - walk(v, n.expr); - walk(v, n.body); + walk(v, n.expr) + walk(v, n.body) case Inline_Range_Stmt: if n.label != nil { - walk(v, n.label); + walk(v, n.label) } if n.val0 != nil { - walk(v, n.val0); + walk(v, n.val0) } if n.val1 != nil { - walk(v, n.val1); + walk(v, n.val1) } - walk(v, n.expr); - walk(v, n.body); + walk(v, n.expr) + walk(v, n.body) case Case_Clause: - walk_expr_list(v, n.list); - walk_stmt_list(v, n.body); + walk_expr_list(v, n.list) + walk_stmt_list(v, n.body) case Switch_Stmt: if n.label != nil { - walk(v, n.label); + walk(v, n.label) } if n.init != nil { - walk(v, n.init); + walk(v, n.init) } if n.cond != nil { - walk(v, n.cond); + walk(v, n.cond) } - walk(v, n.body); + walk(v, n.body) case Type_Switch_Stmt: if n.label != nil { - walk(v, n.label); + walk(v, n.label) } if n.tag != nil { - walk(v, n.tag); + walk(v, n.tag) } if n.expr != nil { - walk(v, n.expr); + walk(v, n.expr) } - walk(v, n.body); + walk(v, n.body) case Branch_Stmt: if n.label != nil { - walk(v, n.label); + walk(v, n.label) } case Using_Stmt: - walk_expr_list(v, n.list); + walk_expr_list(v, n.list) case Bad_Decl: case Value_Decl: if n.docs != nil { - walk(v, n.docs); + walk(v, n.docs) } - walk_attribute_list(v, n.attributes[:]); - walk_expr_list(v, n.names); + walk_attribute_list(v, n.attributes[:]) + walk_expr_list(v, n.names) if n.type != nil { - walk(v, n.type); + walk(v, n.type) } - walk_expr_list(v, n.values); + walk_expr_list(v, n.values) if n.comment != nil { - walk(v, n.comment); + walk(v, n.comment) } case Package_Decl: if n.docs != nil { - walk(v, n.docs); + walk(v, n.docs) } if n.comment != nil { - walk(v, n.comment); + walk(v, n.comment) } case Import_Decl: if n.docs != nil { - walk(v, n.docs); + walk(v, n.docs) } if n.comment != nil { - walk(v, n.comment); + walk(v, n.comment) } case Foreign_Block_Decl: if n.docs != nil { - walk(v, n.docs); + walk(v, n.docs) } - walk_attribute_list(v, n.attributes[:]); + walk_attribute_list(v, n.attributes[:]) if n.foreign_library != nil { - walk(v, n.foreign_library); + walk(v, n.foreign_library) } - walk(v, n.body); + walk(v, n.body) case Foreign_Import_Decl: if n.docs != nil { - walk(v, n.docs); + walk(v, n.docs) } - walk_attribute_list(v, n.attributes[:]); - walk(v, n.name); + walk_attribute_list(v, n.attributes[:]) + walk(v, n.name) if n.comment != nil { - walk(v, n.comment); + walk(v, n.comment) } case Proc_Group: - walk_expr_list(v, n.args); + walk_expr_list(v, n.args) case Attribute: - walk_expr_list(v, n.elems); + walk_expr_list(v, n.elems) case Field: if n.docs != nil { - walk(v, n.docs); + walk(v, n.docs) } - walk_expr_list(v, n.names); + walk_expr_list(v, n.names) if n.type != nil { - walk(v, n.type); + walk(v, n.type) } if n.default_value != nil { - walk(v, n.default_value); + walk(v, n.default_value) } if n.comment != nil { - walk(v, n.comment); + walk(v, n.comment) } case Field_List: for x in n.list { - walk(v, x); + walk(v, x) } case Typeid_Type: if n.specialization != nil { - walk(v, n.specialization); + walk(v, n.specialization) } case Helper_Type: - walk(v, n.type); + walk(v, n.type) case Distinct_Type: - walk(v, n.type); + walk(v, n.type) case Poly_Type: - walk(v, n.type); + walk(v, n.type) if n.specialization != nil { - walk(v, n.specialization); + walk(v, n.specialization) } case Proc_Type: - walk(v, n.params); - walk(v, n.results); + walk(v, n.params) + walk(v, n.results) case Pointer_Type: - walk(v, n.elem); + walk(v, n.elem) case Multi_Pointer_Type: - walk(v, n.elem); + walk(v, n.elem) case Array_Type: if n.tag != nil { - walk(v, n.tag); + walk(v, n.tag) } if n.len != nil { - walk(v, n.len); + walk(v, n.len) } - walk(v, n.elem); + walk(v, n.elem) case Dynamic_Array_Type: if n.tag != nil { - walk(v, n.tag); + walk(v, n.tag) } - walk(v, n.elem); + walk(v, n.elem) case Struct_Type: if n.poly_params != nil { - walk(v, n.poly_params); + walk(v, n.poly_params) } if n.align != nil { - walk(v, n.align); + walk(v, n.align) } - walk_expr_list(v, n.where_clauses); - walk(v, n.fields); + walk_expr_list(v, n.where_clauses) + walk(v, n.fields) case Union_Type: if n.poly_params != nil { - walk(v, n.poly_params); + walk(v, n.poly_params) } if n.align != nil { - walk(v, n.align); + walk(v, n.align) } - walk_expr_list(v, n.where_clauses); - walk_expr_list(v, n.variants); + walk_expr_list(v, n.where_clauses) + walk_expr_list(v, n.variants) case Enum_Type: if n.base_type != nil { - walk(v, n.base_type); + walk(v, n.base_type) } - walk_expr_list(v, n.fields); + walk_expr_list(v, n.fields) case Bit_Set_Type: - walk(v, n.elem); + walk(v, n.elem) if n.underlying != nil { - walk(v, n.underlying); + walk(v, n.underlying) } case Map_Type: - walk(v, n.key); - walk(v, n.value); + walk(v, n.key) + walk(v, n.value) case Relative_Type: - walk(v, n.tag); - walk(v, n.type); + walk(v, n.tag) + walk(v, n.type) case: - fmt.panicf("ast.walk: unexpected node type %T", n); + fmt.panicf("ast.walk: unexpected node type %T", n) } - v->visit(nil); + v->visit(nil) } diff --git a/core/odin/doc-format/doc_format.odin b/core/odin/doc-format/doc_format.odin index f69d5d00d..6821f5ef9 100644 --- a/core/odin/doc-format/doc_format.odin +++ b/core/odin/doc-format/doc_format.odin @@ -7,24 +7,24 @@ Array :: struct($T: typeid) { length: u32le, } -String :: distinct Array(byte); +String :: distinct Array(byte) -Version_Type_Major :: 0; -Version_Type_Minor :: 1; -Version_Type_Patch :: 0; +Version_Type_Major :: 0 +Version_Type_Minor :: 1 +Version_Type_Patch :: 0 Version_Type :: struct { major, minor, patch: u8, _: u8, -}; +} Version_Type_Default :: Version_Type{ major=Version_Type_Major, minor=Version_Type_Minor, patch=Version_Type_Patch, -}; +} -Magic_String :: "odindoc\x00"; +Magic_String :: "odindoc\x00" Header_Base :: struct { magic: [8]byte, @@ -45,10 +45,10 @@ Header :: struct { types: Array(Type), } -File_Index :: distinct u32le; -Pkg_Index :: distinct u32le; -Entity_Index :: distinct u32le; -Type_Index :: distinct u32le; +File_Index :: distinct u32le +Pkg_Index :: distinct u32le +Entity_Index :: distinct u32le +Type_Index :: distinct u32le Position :: struct { @@ -56,7 +56,7 @@ Position :: struct { line: u32le, column: u32le, offset: u32le, -}; +} File :: struct { pkg: Pkg_Index, @@ -69,7 +69,7 @@ Pkg_Flag :: enum u32le { Init = 2, } -Pkg_Flags :: distinct bit_set[Pkg_Flag; u32le]; +Pkg_Flags :: distinct bit_set[Pkg_Flag; u32le] Pkg :: struct { fullpath: String, @@ -108,7 +108,7 @@ Entity_Flag :: enum u32le { Var_Static = 10, } -Entity_Flags :: distinct bit_set[Entity_Flag; u32le]; +Entity_Flags :: distinct bit_set[Entity_Flag; u32le] Entity :: struct { kind: Entity_Kind, @@ -169,7 +169,7 @@ Type_Kind :: enum u32le { Multi_Pointer = 22, } -Type_Elems_Cap :: 4; +Type_Elems_Cap :: 4 Type :: struct { kind: Type_Kind, @@ -239,26 +239,26 @@ Type :: struct { where_clauses: Array(String), } -Type_Flags_Basic :: distinct bit_set[Type_Flag_Basic; u32le]; +Type_Flags_Basic :: distinct bit_set[Type_Flag_Basic; u32le] Type_Flag_Basic :: enum u32le { Untyped = 1, } -Type_Flags_Struct :: distinct bit_set[Type_Flag_Struct; u32le]; +Type_Flags_Struct :: distinct bit_set[Type_Flag_Struct; u32le] Type_Flag_Struct :: enum u32le { Polymorphic = 0, Packed = 1, Raw_Union = 2, } -Type_Flags_Union :: distinct bit_set[Type_Flag_Union; u32le]; +Type_Flags_Union :: distinct bit_set[Type_Flag_Union; u32le] Type_Flag_Union :: enum u32le { Polymorphic = 0, No_Nil = 1, Maybe = 2, } -Type_Flags_Proc :: distinct bit_set[Type_Flag_Proc; u32le]; +Type_Flags_Proc :: distinct bit_set[Type_Flag_Proc; u32le] Type_Flag_Proc :: enum u32le { Polymorphic = 0, Diverging = 1, @@ -267,7 +267,7 @@ Type_Flag_Proc :: enum u32le { C_Vararg = 4, } -Type_Flags_Bit_Set :: distinct bit_set[Type_Flag_Bit_Set; u32le]; +Type_Flags_Bit_Set :: distinct bit_set[Type_Flag_Bit_Set; u32le] Type_Flag_Bit_Set :: enum u32le { Range = 1, Op_Lt = 2, @@ -276,13 +276,13 @@ Type_Flag_Bit_Set :: enum u32le { } from_array :: proc(base: ^Header_Base, a: $A/Array($T)) -> []T { - s: mem.Raw_Slice; - s.data = rawptr(uintptr(base) + uintptr(a.offset)); - s.len = int(a.length); - return transmute([]T)s; + s: mem.Raw_Slice + s.data = rawptr(uintptr(base) + uintptr(a.offset)) + s.len = int(a.length) + return transmute([]T)s } from_string :: proc(base: ^Header_Base, s: String) -> string { - return string(from_array(base, s)); + return string(from_array(base, s)) } @@ -298,22 +298,22 @@ Reader_Error :: enum { read_from_bytes :: proc(data: []byte) -> (h: ^Header, err: Reader_Error) { if len(data) < size_of(Header_Base) { - err = .Header_Too_Small; - return; + err = .Header_Too_Small + return } - header_base := (^Header_Base)(raw_data(data)); + header_base := (^Header_Base)(raw_data(data)) if header_base.magic != Magic_String { - err = .Invalid_Magic; - return; + err = .Invalid_Magic + return } if len(data) < int(header_base.total_size) { - err = .Data_Too_Small; - return; + err = .Data_Too_Small + return } if header_base.version != Version_Type_Default { - err = .Invalid_Version; - return; + err = .Invalid_Version + return } - h = (^Header)(header_base); - return; + h = (^Header)(header_base) + return } diff --git a/core/odin/format/format.odin b/core/odin/format/format.odin index 325881db8..66a7eb5f3 100644 --- a/core/odin/format/format.odin +++ b/core/odin/format/format.odin @@ -4,38 +4,38 @@ import "core:odin/printer" import "core:odin/parser" import "core:odin/ast" -default_style := printer.default_style; +default_style := printer.default_style simplify :: proc(file: ^ast.File) { } format :: proc(filepath: string, source: string, config: printer.Config, parser_flags := parser.Flags{}, allocator := context.allocator) -> (string, bool) { - config := config; + config := config pkg := ast.Package { kind = .Normal, - }; + } file := ast.File { pkg = &pkg, src = source, fullpath = filepath, - }; + } - config.newline_limit = clamp(config.newline_limit, 0, 16); - config.spaces = clamp(config.spaces, 1, 16); - config.align_length_break = clamp(config.align_length_break, 0, 64); + config.newline_limit = clamp(config.newline_limit, 0, 16) + config.spaces = clamp(config.spaces, 1, 16) + config.align_length_break = clamp(config.align_length_break, 0, 64) - p := parser.default_parser(parser_flags); + p := parser.default_parser(parser_flags) - ok := parser.parse_file(&p, &file); + ok := parser.parse_file(&p, &file) if !ok || file.syntax_error_count > 0 { - return {}, false; + return {}, false } - prnt := printer.make_printer(config, allocator); + prnt := printer.make_printer(config, allocator) - return printer.print(&prnt, &file), true; + return printer.print(&prnt, &file), true } diff --git a/core/odin/parser/parse_files.odin b/core/odin/parser/parse_files.odin index f622c9781..6452faf4c 100644 --- a/core/odin/parser/parse_files.odin +++ b/core/odin/parser/parse_files.odin @@ -8,82 +8,82 @@ import "core:os" import "core:slice" collect_package :: proc(path: string) -> (pkg: ^ast.Package, success: bool) { - NO_POS :: tokenizer.Pos{}; + NO_POS :: tokenizer.Pos{} - pkg_path, pkg_path_ok := filepath.abs(path); + pkg_path, pkg_path_ok := filepath.abs(path) if !pkg_path_ok { - return; + return } - path_pattern := fmt.tprintf("%s/*.odin", pkg_path); - matches, err := filepath.glob(path_pattern); - defer delete(matches); + path_pattern := fmt.tprintf("%s/*.odin", pkg_path) + matches, err := filepath.glob(path_pattern) + defer delete(matches) if err != nil { - return; + return } - pkg = ast.new(ast.Package, NO_POS, NO_POS); - pkg.fullpath = pkg_path; + pkg = ast.new(ast.Package, NO_POS, NO_POS) + pkg.fullpath = pkg_path for match in matches { - src: []byte; - fullpath, ok := filepath.abs(match); + src: []byte + fullpath, ok := filepath.abs(match) if !ok { - return; + return } - src, ok = os.read_entire_file(fullpath); + src, ok = os.read_entire_file(fullpath) if !ok { - delete(fullpath); - return; + delete(fullpath) + return } - file := ast.new(ast.File, NO_POS, NO_POS); - file.pkg = pkg; - file.src = string(src); - file.fullpath = fullpath; - pkg.files[fullpath] = file; + file := ast.new(ast.File, NO_POS, NO_POS) + file.pkg = pkg + file.src = string(src) + file.fullpath = fullpath + pkg.files[fullpath] = file } - success = true; - return; + success = true + return } parse_package :: proc(pkg: ^ast.Package, p: ^Parser = nil) -> bool { - p := p; + p := p if p == nil { - p = &Parser{}; - p^ = default_parser(); + p = &Parser{} + p^ = default_parser() } - ok := true; + ok := true - files := make([]^ast.File, len(pkg.files), context.temp_allocator); - i := 0; + files := make([]^ast.File, len(pkg.files), context.temp_allocator) + i := 0 for _, file in pkg.files { - files[i] = file; - i += 1; + files[i] = file + i += 1 } - slice.sort(files); + slice.sort(files) for file in files { if !parse_file(p, file) { - ok = false; + ok = false } if pkg.name == "" { - pkg.name = file.pkg_decl.name; + pkg.name = file.pkg_decl.name } else if pkg.name != file.pkg_decl.name { - error(p, file.pkg_decl.pos, "different package name, expected '%s', got '%s'", pkg.name, file.pkg_decl.name); + error(p, file.pkg_decl.pos, "different package name, expected '%s', got '%s'", pkg.name, file.pkg_decl.name) } } - return ok; + return ok } parse_package_from_path :: proc(path: string, p: ^Parser = nil) -> (pkg: ^ast.Package, ok: bool) { - pkg, ok = collect_package(path); + pkg, ok = collect_package(path) if !ok { - return; + return } - ok = parse_package(pkg, p); - return; + ok = parse_package(pkg, p) + return } diff --git a/core/odin/parser/parser.odin b/core/odin/parser/parser.odin index b08f9d479..3053f2255 100644 --- a/core/odin/parser/parser.odin +++ b/core/odin/parser/parser.odin @@ -5,14 +5,14 @@ import "core:odin/tokenizer" import "core:fmt" -Warning_Handler :: #type proc(pos: tokenizer.Pos, fmt: string, args: ..any); -Error_Handler :: #type proc(pos: tokenizer.Pos, fmt: string, args: ..any); +Warning_Handler :: #type proc(pos: tokenizer.Pos, fmt: string, args: ..any) +Error_Handler :: #type proc(pos: tokenizer.Pos, fmt: string, args: ..any) Flag :: enum u32 { Optional_Semicolons, } -Flags :: distinct bit_set[Flag; u32]; +Flags :: distinct bit_set[Flag; u32] Parser :: struct { @@ -49,13 +49,13 @@ Parser :: struct { fix_prev_pos: tokenizer.Pos, } -MAX_FIX_COUNT :: 10; +MAX_FIX_COUNT :: 10 Stmt_Allow_Flag :: enum { In, Label, } -Stmt_Allow_Flags :: distinct bit_set[Stmt_Allow_Flag]; +Stmt_Allow_Flags :: distinct bit_set[Stmt_Allow_Flag] Import_Decl_Kind :: enum { @@ -66,54 +66,54 @@ Import_Decl_Kind :: enum { default_warning_handler :: proc(pos: tokenizer.Pos, msg: string, args: ..any) { - fmt.eprintf("%s(%d:%d): Warning: ", pos.file, pos.line, pos.column); - fmt.eprintf(msg, ..args); - fmt.eprintf("\n"); + fmt.eprintf("%s(%d:%d): Warning: ", pos.file, pos.line, pos.column) + fmt.eprintf(msg, ..args) + fmt.eprintf("\n") } default_error_handler :: proc(pos: tokenizer.Pos, msg: string, args: ..any) { - fmt.eprintf("%s(%d:%d): ", pos.file, pos.line, pos.column); - fmt.eprintf(msg, ..args); - fmt.eprintf("\n"); + fmt.eprintf("%s(%d:%d): ", pos.file, pos.line, pos.column) + fmt.eprintf(msg, ..args) + fmt.eprintf("\n") } warn :: proc(p: ^Parser, pos: tokenizer.Pos, msg: string, args: ..any) { if p.warn != nil { - p.warn(pos, msg, ..args); + p.warn(pos, msg, ..args) } - p.file.syntax_warning_count += 1; + p.file.syntax_warning_count += 1 } error :: proc(p: ^Parser, pos: tokenizer.Pos, msg: string, args: ..any) { if p.err != nil { - p.err(pos, msg, ..args); + p.err(pos, msg, ..args) } - p.file.syntax_error_count += 1; - p.error_count += 1; + p.file.syntax_error_count += 1 + p.error_count += 1 } end_pos :: proc(tok: tokenizer.Token) -> tokenizer.Pos { - pos := tok.pos; - pos.offset += len(tok.text); + pos := tok.pos + pos.offset += len(tok.text) if tok.kind == .Comment { if tok.text[:2] != "/*" { - pos.column += len(tok.text); + pos.column += len(tok.text) } else { for i := 0; i < len(tok.text); i += 1 { - c := tok.text[i]; + c := tok.text[i] if c == '\n' { - pos.line += 1; - pos.column = 1; + pos.line += 1 + pos.column = 1 } else { - pos.column += 1; + pos.column += 1 } } } } else { - pos.column += len(tok.text); + pos.column += len(tok.text) } - return pos; + return pos } default_parser :: proc(flags := Flags{}) -> Parser { @@ -121,302 +121,302 @@ default_parser :: proc(flags := Flags{}) -> Parser { flags = flags, err = default_error_handler, warn = default_warning_handler, - }; + } } is_package_name_reserved :: proc(name: string) -> bool { switch name { case "builtin", "intrinsics": - return true; + return true } - return false; + return false } parse_file :: proc(p: ^Parser, file: ^ast.File) -> bool { zero_parser: { - p.prev_tok = {}; - p.curr_tok = {}; - p.expr_level = 0; - p.allow_range = false; - p.allow_in_expr = false; - p.in_foreign_block = false; - p.allow_type = false; - p.lead_comment = nil; - p.line_comment = nil; + p.prev_tok = {} + p.curr_tok = {} + p.expr_level = 0 + p.allow_range = false + p.allow_in_expr = false + p.in_foreign_block = false + p.allow_type = false + p.lead_comment = nil + p.line_comment = nil } - p.tok.flags += {.Insert_Semicolon}; + p.tok.flags += {.Insert_Semicolon} - p.file = file; - tokenizer.init(&p.tok, file.src, file.fullpath, p.err); + p.file = file + tokenizer.init(&p.tok, file.src, file.fullpath, p.err) if p.tok.ch <= 0 { - return true; + return true } - advance_token(p); - consume_comment_groups(p, p.prev_tok); + advance_token(p) + consume_comment_groups(p, p.prev_tok) - docs := p.lead_comment; + docs := p.lead_comment - p.file.pkg_token = expect_token(p, .Package); + p.file.pkg_token = expect_token(p, .Package) if p.file.pkg_token.kind != .Package { - return false; + return false } - pkg_name := expect_token_after(p, .Ident, "package"); + pkg_name := expect_token_after(p, .Ident, "package") if pkg_name.kind == .Ident { switch name := pkg_name.text; { case is_blank_ident(name): - error(p, pkg_name.pos, "invalid package name '_'"); + error(p, pkg_name.pos, "invalid package name '_'") case is_package_name_reserved(name), file.pkg != nil && file.pkg.kind != .Runtime && name == "runtime": - error(p, pkg_name.pos, "use of reserved package name '%s'", name); + error(p, pkg_name.pos, "use of reserved package name '%s'", name) } } - p.file.pkg_name = pkg_name.text; + p.file.pkg_name = pkg_name.text - pd := ast.new(ast.Package_Decl, pkg_name.pos, end_pos(p.prev_tok)); - pd.docs = docs; - pd.token = p.file.pkg_token; - pd.name = pkg_name.text; - pd.comment = p.line_comment; - p.file.pkg_decl = pd; + pd := ast.new(ast.Package_Decl, pkg_name.pos, end_pos(p.prev_tok)) + pd.docs = docs + pd.token = p.file.pkg_token + pd.name = pkg_name.text + pd.comment = p.line_comment + p.file.pkg_decl = pd - expect_semicolon(p, pd); + expect_semicolon(p, pd) if p.file.syntax_error_count > 0 { - return false; + return false } - p.file.decls = make([dynamic]^ast.Stmt); + p.file.decls = make([dynamic]^ast.Stmt) for p.curr_tok.kind != .EOF { - stmt := parse_stmt(p); + stmt := parse_stmt(p) if stmt != nil { if _, ok := stmt.derived.(ast.Empty_Stmt); !ok { - append(&p.file.decls, stmt); + append(&p.file.decls, stmt) if es, es_ok := stmt.derived.(ast.Expr_Stmt); es_ok && es.expr != nil { if _, pl_ok := es.expr.derived.(ast.Proc_Lit); pl_ok { - error(p, stmt.pos, "procedure literal evaluated but not used"); + error(p, stmt.pos, "procedure literal evaluated but not used") } } } } } - return true; + return true } peek_token_kind :: proc(p: ^Parser, kind: tokenizer.Token_Kind, lookahead := 0) -> (ok: bool) { - prev_parser := p^; - defer p^ = prev_parser; + prev_parser := p^ + defer p^ = prev_parser - p.tok.err = nil; + p.tok.err = nil for i := 0; i <= lookahead; i += 1 { - advance_token(p); + advance_token(p) } - ok = p.curr_tok.kind == kind; + ok = p.curr_tok.kind == kind - return; + return } peek_token :: proc(p: ^Parser, lookahead := 0) -> (tok: tokenizer.Token) { - prev_parser := p^; - defer p^ = prev_parser; + prev_parser := p^ + defer p^ = prev_parser - p.tok.err = nil; + p.tok.err = nil for i := 0; i <= lookahead; i += 1 { - advance_token(p); + advance_token(p) } - tok = p.curr_tok; - return; + tok = p.curr_tok + return } skip_possible_newline :: proc(p: ^Parser) -> bool { if .Optional_Semicolons not_in p.flags { - return false; + return false } - prev := p.curr_tok; + prev := p.curr_tok if tokenizer.is_newline(prev) { - advance_token(p); - return true; + advance_token(p) + return true } - return false; + return false } skip_possible_newline_for_literal :: proc(p: ^Parser) -> bool { if .Optional_Semicolons not_in p.flags { - return false; + return false } - curr_pos := p.curr_tok.pos; + curr_pos := p.curr_tok.pos if tokenizer.is_newline(p.curr_tok) { - next := peek_token(p); + next := peek_token(p) if curr_pos.line+1 >= next.pos.line { #partial switch next.kind { case .Open_Brace, .Else, .Where: - advance_token(p); - return true; + advance_token(p) + return true } } } - return false; + return false } next_token0 :: proc(p: ^Parser) -> bool { - p.curr_tok = tokenizer.scan(&p.tok); + p.curr_tok = tokenizer.scan(&p.tok) if p.curr_tok.kind == .EOF { // error(p, p.curr_tok.pos, "token is EOF"); - return false; + return false } - return true; + return true } consume_comment :: proc(p: ^Parser) -> (tok: tokenizer.Token, end_line: int) { - tok = p.curr_tok; - assert(tok.kind == .Comment); - end_line = tok.pos.line; + tok = p.curr_tok + assert(tok.kind == .Comment) + end_line = tok.pos.line if tok.text[1] == '*' { for c in tok.text { if c == '\n' { - end_line += 1; + end_line += 1 } } } - _ = next_token0(p); + _ = next_token0(p) if p.curr_tok.pos.line > tok.pos.line { - end_line += 1; + end_line += 1 } - return; + return } consume_comment_group :: proc(p: ^Parser, n: int) -> (comments: ^ast.Comment_Group, end_line: int) { - list: [dynamic]tokenizer.Token; - end_line = p.curr_tok.pos.line; + list: [dynamic]tokenizer.Token + end_line = p.curr_tok.pos.line for p.curr_tok.kind == .Comment && p.curr_tok.pos.line <= end_line+n { - comment: tokenizer.Token; - comment, end_line = consume_comment(p); - append(&list, comment); + comment: tokenizer.Token + comment, end_line = consume_comment(p) + append(&list, comment) } if len(list) > 0 { - comments = ast.new(ast.Comment_Group, list[0].pos, end_pos(list[len(list)-1])); - comments.list = list[:]; - append(&p.file.comments, comments); + comments = ast.new(ast.Comment_Group, list[0].pos, end_pos(list[len(list)-1])) + comments.list = list[:] + append(&p.file.comments, comments) } - return; + return } consume_comment_groups :: proc(p: ^Parser, prev: tokenizer.Token) { if p.curr_tok.kind == .Comment { - comment: ^ast.Comment_Group; - end_line := 0; + comment: ^ast.Comment_Group + end_line := 0 if p.curr_tok.pos.line == prev.pos.line { - comment, end_line = consume_comment_group(p, 0); + comment, end_line = consume_comment_group(p, 0) if p.curr_tok.pos.line != end_line || p.curr_tok.kind == .EOF { - p.line_comment = comment; + p.line_comment = comment } } - end_line = -1; + end_line = -1 for p.curr_tok.kind == .Comment { - comment, end_line = consume_comment_group(p, 1); + comment, end_line = consume_comment_group(p, 1) } if end_line+1 >= p.curr_tok.pos.line || end_line < 0 { - p.lead_comment = comment; + p.lead_comment = comment } - assert(p.curr_tok.kind != .Comment); + assert(p.curr_tok.kind != .Comment) } } advance_token :: proc(p: ^Parser) -> tokenizer.Token { - p.lead_comment = nil; - p.line_comment = nil; - p.prev_tok = p.curr_tok; - prev := p.prev_tok; + p.lead_comment = nil + p.line_comment = nil + p.prev_tok = p.curr_tok + prev := p.prev_tok if next_token0(p) { - consume_comment_groups(p, prev); + consume_comment_groups(p, prev) } - return prev; + return prev } expect_token :: proc(p: ^Parser, kind: tokenizer.Token_Kind) -> tokenizer.Token { - prev := p.curr_tok; + prev := p.curr_tok if prev.kind != kind { - e := tokenizer.to_string(kind); - g := tokenizer.token_to_string(prev); - error(p, prev.pos, "expected '%s', got '%s'", e, g); + e := tokenizer.to_string(kind) + g := tokenizer.token_to_string(prev) + error(p, prev.pos, "expected '%s', got '%s'", e, g) } - advance_token(p); - return prev; + advance_token(p) + return prev } expect_token_after :: proc(p: ^Parser, kind: tokenizer.Token_Kind, msg: string) -> tokenizer.Token { - prev := p.curr_tok; + prev := p.curr_tok if prev.kind != kind { - e := tokenizer.to_string(kind); - g := tokenizer.token_to_string(prev); - error(p, prev.pos, "expected '%s' after %s, got '%s'", e, msg, g); + e := tokenizer.to_string(kind) + g := tokenizer.token_to_string(prev) + error(p, prev.pos, "expected '%s' after %s, got '%s'", e, msg, g) } - advance_token(p); - return prev; + advance_token(p) + return prev } expect_operator :: proc(p: ^Parser) -> tokenizer.Token { - prev := p.curr_tok; + prev := p.curr_tok #partial switch prev.kind { case .If, .When, .Or_Else: // okay case: if !tokenizer.is_operator(prev.kind) { - g := tokenizer.token_to_string(prev); - error(p, prev.pos, "expected an operator, got '%s'", g); + g := tokenizer.token_to_string(prev) + error(p, prev.pos, "expected an operator, got '%s'", g) } } - advance_token(p); - return prev; + advance_token(p) + return prev } allow_token :: proc(p: ^Parser, kind: tokenizer.Token_Kind) -> bool { if p.curr_tok.kind == kind { - advance_token(p); - return true; + advance_token(p) + return true } - return false; + return false } end_of_line_pos :: proc(p: ^Parser, tok: tokenizer.Token) -> tokenizer.Pos { - offset := clamp(tok.pos.offset, 0, len(p.tok.src)-1); - s := p.tok.src[offset:]; - pos := tok.pos; - pos.column -= 1; + offset := clamp(tok.pos.offset, 0, len(p.tok.src)-1) + s := p.tok.src[offset:] + pos := tok.pos + pos.column -= 1 for len(s) != 0 && s[0] != 0 && s[0] != '\n' { - s = s[1:]; - pos.column += 1; + s = s[1:] + pos.column += 1 } - return pos; + return pos } expect_closing_brace_of_field_list :: proc(p: ^Parser) -> tokenizer.Token { - token := p.curr_tok; + token := p.curr_tok if allow_token(p, .Close_Brace) { - return token; + return token } if allow_token(p, .Semicolon) { - str := tokenizer.token_to_string(token); - error(p, end_of_line_pos(p, p.prev_tok), "expected a comma, got %s", p); + str := tokenizer.token_to_string(token) + error(p, end_of_line_pos(p, p.prev_tok), "expected a comma, got %s", p) } - return expect_token(p, .Close_Brace); + return expect_token(p, .Close_Brace) } @@ -424,28 +424,28 @@ is_blank_ident :: proc{ is_blank_ident_string, is_blank_ident_token, is_blank_ident_node, -}; +} is_blank_ident_string :: proc(str: string) -> bool { - return str == "_"; + return str == "_" } is_blank_ident_token :: proc(tok: tokenizer.Token) -> bool { if tok.kind == .Ident { - return is_blank_ident_string(tok.text); + return is_blank_ident_string(tok.text) } - return false; + return false } is_blank_ident_node :: proc(node: ^ast.Node) -> bool { if ident, ok := node.derived.(ast.Ident); ok { - return is_blank_ident(ident.name); + return is_blank_ident(ident.name) } - return true; + return true } fix_advance_to_next_stmt :: proc(p: ^Parser) { for { #partial switch t := p.curr_tok; t.kind { case .EOF, .Semicolon: - return; + return case .Package, .Foreign, .Import, .If, .For, .When, .Return, .Switch, @@ -455,66 +455,66 @@ fix_advance_to_next_stmt :: proc(p: ^Parser) { if t.pos == p.fix_prev_pos && p.fix_count < MAX_FIX_COUNT { - p.fix_count += 1; - return; + p.fix_count += 1 + return } if t.pos.offset < p.fix_prev_pos.offset { - p.fix_prev_pos = t.pos; - p.fix_count = 0; - return; + p.fix_prev_pos = t.pos + p.fix_count = 0 + return } } - advance_token(p); + advance_token(p) } } is_semicolon_optional_for_node :: proc(p: ^Parser, node: ^ast.Node) -> bool { if node == nil { - return false; + return false } if .Optional_Semicolons in p.flags { - return true; + return true } switch n in node.derived { case ast.Empty_Stmt, ast.Block_Stmt: - return true; + return true case ast.If_Stmt, ast.When_Stmt, ast.For_Stmt, ast.Range_Stmt, ast.Inline_Range_Stmt, ast.Switch_Stmt, ast.Type_Switch_Stmt: - return true; + return true case ast.Helper_Type: - return is_semicolon_optional_for_node(p, n.type); + return is_semicolon_optional_for_node(p, n.type) case ast.Distinct_Type: - return is_semicolon_optional_for_node(p, n.type); + return is_semicolon_optional_for_node(p, n.type) case ast.Pointer_Type: - return is_semicolon_optional_for_node(p, n.elem); + return is_semicolon_optional_for_node(p, n.elem) case ast.Struct_Type, ast.Union_Type, ast.Enum_Type: // Require semicolon within a procedure body - return p.curr_proc == nil; + return p.curr_proc == nil case ast.Proc_Lit: - return true; + return true case ast.Package_Decl, ast.Import_Decl, ast.Foreign_Import_Decl: - return true; + return true case ast.Foreign_Block_Decl: - return is_semicolon_optional_for_node(p, n.body); + return is_semicolon_optional_for_node(p, n.body) case ast.Value_Decl: if n.is_mutable { - return false; + return false } if len(n.values) > 0 { - return is_semicolon_optional_for_node(p, n.values[len(n.values)-1]); + return is_semicolon_optional_for_node(p, n.values[len(n.values)-1]) } } - return false; + return false } expect_semicolon_newline_error :: proc(p: ^Parser, token: tokenizer.Token, s: ^ast.Node) { @@ -523,733 +523,733 @@ expect_semicolon_newline_error :: proc(p: ^Parser, token: tokenizer.Token, s: ^a case .Close_Brace: case .Close_Paren: case .Else: - return; + return } if is_semicolon_optional_for_node(p, s) { - return; + return } - tok := token; - tok.pos.column -= 1; - error(p, tok.pos, "expected ';', got newline"); + tok := token + tok.pos.column -= 1 + error(p, tok.pos, "expected ';', got newline") } } expect_semicolon :: proc(p: ^Parser, node: ^ast.Node) -> bool { if allow_token(p, .Semicolon) { - expect_semicolon_newline_error(p, p.prev_tok, node); - return true; + expect_semicolon_newline_error(p, p.prev_tok, node) + return true } - prev := p.prev_tok; + prev := p.prev_tok if prev.kind == .Semicolon { - expect_semicolon_newline_error(p, p.prev_tok, node); - return true; + expect_semicolon_newline_error(p, p.prev_tok, node) + return true } if p.curr_tok.kind == .EOF { - return true; + return true } if node != nil { if .Insert_Semicolon in p.tok.flags { #partial switch p.curr_tok.kind { case .Close_Brace, .Close_Paren, .Else, .EOF: - return true; + return true } if is_semicolon_optional_for_node(p, node) { - return true; + return true } } else if prev.pos.line != p.curr_tok.pos.line { if is_semicolon_optional_for_node(p, node) { - return true; + return true } } else { #partial switch p.curr_tok.kind { case .Close_Brace, .Close_Paren, .Else: - return true; + return true case .EOF: if is_semicolon_optional_for_node(p, node) { - return true; + return true } } } } else { if p.curr_tok.kind == .EOF { - return true; + return true } } - error(p, prev.pos, "expected ';', got %s", tokenizer.token_to_string(p.curr_tok)); - fix_advance_to_next_stmt(p); - return false; + error(p, prev.pos, "expected ';', got %s", tokenizer.token_to_string(p.curr_tok)) + fix_advance_to_next_stmt(p) + return false } new_blank_ident :: proc(p: ^Parser, pos: tokenizer.Pos) -> ^ast.Ident { - tok: tokenizer.Token; - tok.pos = pos; - i := ast.new(ast.Ident, pos, end_pos(tok)); - i.name = "_"; - return i; + tok: tokenizer.Token + tok.pos = pos + i := ast.new(ast.Ident, pos, end_pos(tok)) + i.name = "_" + return i } parse_ident :: proc(p: ^Parser) -> ^ast.Ident { - tok := p.curr_tok; - pos := tok.pos; - name := "_"; + tok := p.curr_tok + pos := tok.pos + name := "_" if tok.kind == .Ident { - name = tok.text; - advance_token(p); + name = tok.text + advance_token(p) } else { - expect_token(p, .Ident); + expect_token(p, .Ident) } - i := ast.new(ast.Ident, pos, end_pos(tok)); - i.name = name; - return i; + i := ast.new(ast.Ident, pos, end_pos(tok)) + i.name = name + return i } parse_stmt_list :: proc(p: ^Parser) -> []^ast.Stmt { - list: [dynamic]^ast.Stmt; + list: [dynamic]^ast.Stmt for p.curr_tok.kind != .Case && p.curr_tok.kind != .Close_Brace && p.curr_tok.kind != .EOF { - stmt := parse_stmt(p); + stmt := parse_stmt(p) if stmt != nil { if _, ok := stmt.derived.(ast.Empty_Stmt); !ok { - append(&list, stmt); + append(&list, stmt) if es, es_ok := stmt.derived.(ast.Expr_Stmt); es_ok && es.expr != nil { if _, pl_ok := es.expr.derived.(ast.Proc_Lit); pl_ok { - error(p, stmt.pos, "procedure literal evaluated but not used"); + error(p, stmt.pos, "procedure literal evaluated but not used") } } } } } - return list[:]; + return list[:] } parse_block_stmt :: proc(p: ^Parser, is_when: bool) -> ^ast.Stmt { - skip_possible_newline_for_literal(p); + skip_possible_newline_for_literal(p) if !is_when && p.curr_proc == nil { - error(p, p.curr_tok.pos, "you cannot use a block statement in the file scope"); + error(p, p.curr_tok.pos, "you cannot use a block statement in the file scope") } - return parse_body(p); + return parse_body(p) } parse_when_stmt :: proc(p: ^Parser) -> ^ast.When_Stmt { - tok := expect_token(p, .When); + tok := expect_token(p, .When) - cond: ^ast.Expr; - body: ^ast.Stmt; - else_stmt: ^ast.Stmt; + cond: ^ast.Expr + body: ^ast.Stmt + else_stmt: ^ast.Stmt - prev_level := p.expr_level; - p.expr_level = -1; - cond = parse_expr(p, false); - p.expr_level = prev_level; + prev_level := p.expr_level + p.expr_level = -1 + cond = parse_expr(p, false) + p.expr_level = prev_level if cond == nil { - error(p, p.curr_tok.pos, "expected a condition for when statement"); + error(p, p.curr_tok.pos, "expected a condition for when statement") } if allow_token(p, .Do) { - body = convert_stmt_to_body(p, parse_stmt(p)); + body = convert_stmt_to_body(p, parse_stmt(p)) if cond.pos.line != body.pos.line { - error(p, body.pos, "the body of a 'do' must be on the same line as when statement"); + error(p, body.pos, "the body of a 'do' must be on the same line as when statement") } } else { - body = parse_block_stmt(p, true); + body = parse_block_stmt(p, true) } - skip_possible_newline_for_literal(p); + skip_possible_newline_for_literal(p) if p.curr_tok.kind == .Else { - else_tok := expect_token(p, .Else); + else_tok := expect_token(p, .Else) #partial switch p.curr_tok.kind { case .When: - else_stmt = parse_when_stmt(p); + else_stmt = parse_when_stmt(p) case .Open_Brace: - else_stmt = parse_block_stmt(p, true); + else_stmt = parse_block_stmt(p, true) case .Do: - expect_token(p, .Do); - else_stmt = convert_stmt_to_body(p, parse_stmt(p)); + expect_token(p, .Do) + else_stmt = convert_stmt_to_body(p, parse_stmt(p)) if else_tok.pos.line != else_stmt.pos.line { - error(p, else_stmt.pos, "the body of a 'do' must be on the same line as 'else'"); + error(p, else_stmt.pos, "the body of a 'do' must be on the same line as 'else'") } case: - error(p, p.curr_tok.pos, "expected when statement block statement"); - else_stmt = ast.new(ast.Bad_Stmt, p.curr_tok.pos, end_pos(p.curr_tok)); + error(p, p.curr_tok.pos, "expected when statement block statement") + else_stmt = ast.new(ast.Bad_Stmt, p.curr_tok.pos, end_pos(p.curr_tok)) } } - end := body.end; + end := body.end if else_stmt != nil { - end = else_stmt.end; + end = else_stmt.end } - when_stmt := ast.new(ast.When_Stmt, tok.pos, end); - when_stmt.when_pos = tok.pos; - when_stmt.cond = cond; - when_stmt.body = body; - when_stmt.else_stmt = else_stmt; - return when_stmt; + when_stmt := ast.new(ast.When_Stmt, tok.pos, end) + when_stmt.when_pos = tok.pos + when_stmt.cond = cond + when_stmt.body = body + when_stmt.else_stmt = else_stmt + return when_stmt } convert_stmt_to_expr :: proc(p: ^Parser, stmt: ^ast.Stmt, kind: string) -> ^ast.Expr { if stmt == nil { - return nil; + return nil } if es, ok := stmt.derived.(ast.Expr_Stmt); ok { - return es.expr; + return es.expr } - error(p, stmt.pos, "expected %s, found a simple statement", kind); - return ast.new(ast.Bad_Expr, p.curr_tok.pos, end_pos(p.curr_tok)); + error(p, stmt.pos, "expected %s, found a simple statement", kind) + return ast.new(ast.Bad_Expr, p.curr_tok.pos, end_pos(p.curr_tok)) } parse_if_stmt :: proc(p: ^Parser) -> ^ast.If_Stmt { - tok := expect_token(p, .If); + tok := expect_token(p, .If) - init: ^ast.Stmt; - cond: ^ast.Expr; - body: ^ast.Stmt; - else_stmt: ^ast.Stmt; + init: ^ast.Stmt + cond: ^ast.Expr + body: ^ast.Stmt + else_stmt: ^ast.Stmt - prev_level := p.expr_level; - p.expr_level = -1; - prev_allow_in_expr := p.allow_in_expr; - p.allow_in_expr = true; + prev_level := p.expr_level + p.expr_level = -1 + prev_allow_in_expr := p.allow_in_expr + p.allow_in_expr = true if allow_token(p, .Semicolon) { - cond = parse_expr(p, false); + cond = parse_expr(p, false) } else { - init = parse_simple_stmt(p, nil); + init = parse_simple_stmt(p, nil) if parse_control_statement_semicolon_separator(p) { - cond = parse_expr(p, false); + cond = parse_expr(p, false) } else { - cond = convert_stmt_to_expr(p, init, "boolean expression"); - init = nil; + cond = convert_stmt_to_expr(p, init, "boolean expression") + init = nil } } - p.expr_level = prev_level; - p.allow_in_expr = prev_allow_in_expr; + p.expr_level = prev_level + p.allow_in_expr = prev_allow_in_expr if cond == nil { - error(p, p.curr_tok.pos, "expected a condition for if statement"); + error(p, p.curr_tok.pos, "expected a condition for if statement") } if allow_token(p, .Do) { - body = convert_stmt_to_body(p, parse_stmt(p)); + body = convert_stmt_to_body(p, parse_stmt(p)) if cond.pos.line != body.pos.line { - error(p, body.pos, "the body of a 'do' must be on the same line as the if condition"); + error(p, body.pos, "the body of a 'do' must be on the same line as the if condition") } } else { - body = parse_block_stmt(p, false); + body = parse_block_stmt(p, false) } - else_tok := p.curr_tok.pos; + else_tok := p.curr_tok.pos - skip_possible_newline_for_literal(p); + skip_possible_newline_for_literal(p) if p.curr_tok.kind == .Else { - else_tok := expect_token(p, .Else); + else_tok := expect_token(p, .Else) #partial switch p.curr_tok.kind { case .If: - else_stmt = parse_if_stmt(p); + else_stmt = parse_if_stmt(p) case .Open_Brace: - else_stmt = parse_block_stmt(p, false); + else_stmt = parse_block_stmt(p, false) case .Do: - expect_token(p, .Do); - else_stmt = convert_stmt_to_body(p, parse_stmt(p)); + expect_token(p, .Do) + else_stmt = convert_stmt_to_body(p, parse_stmt(p)) if else_tok.pos.line != else_stmt.pos.line { - error(p, body.pos, "the body of a 'do' must be on the same line as 'else'"); + error(p, body.pos, "the body of a 'do' must be on the same line as 'else'") } case: - error(p, p.curr_tok.pos, "expected if statement block statement"); - else_stmt = ast.new(ast.Bad_Stmt, p.curr_tok.pos, end_pos(p.curr_tok)); + error(p, p.curr_tok.pos, "expected if statement block statement") + else_stmt = ast.new(ast.Bad_Stmt, p.curr_tok.pos, end_pos(p.curr_tok)) } } - end := body.end; + end := body.end if else_stmt != nil { - end = else_stmt.end; + end = else_stmt.end } - if_stmt := ast.new(ast.If_Stmt, tok.pos, end); - if_stmt.if_pos = tok.pos; - if_stmt.init = init; - if_stmt.cond = cond; - if_stmt.body = body; - if_stmt.else_stmt = else_stmt; - if_stmt.else_pos = else_tok; - return if_stmt; + if_stmt := ast.new(ast.If_Stmt, tok.pos, end) + if_stmt.if_pos = tok.pos + if_stmt.init = init + if_stmt.cond = cond + if_stmt.body = body + if_stmt.else_stmt = else_stmt + if_stmt.else_pos = else_tok + return if_stmt } parse_control_statement_semicolon_separator :: proc(p: ^Parser) -> bool { - tok := peek_token(p); + tok := peek_token(p) if tok.kind != .Open_Brace { - return allow_token(p, .Semicolon); + return allow_token(p, .Semicolon) } if tok.text == ";" { - return allow_token(p, .Semicolon); + return allow_token(p, .Semicolon) } - return false; + return false } parse_for_stmt :: proc(p: ^Parser) -> ^ast.Stmt { if p.curr_proc == nil { - error(p, p.curr_tok.pos, "you cannot use a for statement in the file scope"); + error(p, p.curr_tok.pos, "you cannot use a for statement in the file scope") } - tok := expect_token(p, .For); + tok := expect_token(p, .For) - init: ^ast.Stmt; - cond: ^ast.Stmt; - post: ^ast.Stmt; - body: ^ast.Stmt; - is_range := false; + init: ^ast.Stmt + cond: ^ast.Stmt + post: ^ast.Stmt + body: ^ast.Stmt + is_range := false if p.curr_tok.kind != .Open_Brace && p.curr_tok.kind != .Do { - prev_level := p.expr_level; - defer p.expr_level = prev_level; - p.expr_level = -1; + prev_level := p.expr_level + defer p.expr_level = prev_level + p.expr_level = -1 if p.curr_tok.kind == .In { - in_tok := expect_token(p, .In); - rhs: ^ast.Expr; + in_tok := expect_token(p, .In) + rhs: ^ast.Expr - prev_allow_range := p.allow_range; - p.allow_range = true; - rhs = parse_expr(p, false); - p.allow_range = prev_allow_range; + prev_allow_range := p.allow_range + p.allow_range = true + rhs = parse_expr(p, false) + p.allow_range = prev_allow_range if allow_token(p, .Do) { - body = convert_stmt_to_body(p, parse_stmt(p)); + body = convert_stmt_to_body(p, parse_stmt(p)) if tok.pos.line != body.pos.line { - error(p, body.pos, "the body of a 'do' must be on the same line as 'else'"); + error(p, body.pos, "the body of a 'do' must be on the same line as 'else'") } } else { - body = parse_body(p); + body = parse_body(p) } - range_stmt := ast.new(ast.Range_Stmt, tok.pos, body.end); - range_stmt.for_pos = tok.pos; - range_stmt.in_pos = in_tok.pos; - range_stmt.expr = rhs; - range_stmt.body = body; - return range_stmt; + range_stmt := ast.new(ast.Range_Stmt, tok.pos, body.end) + range_stmt.for_pos = tok.pos + range_stmt.in_pos = in_tok.pos + range_stmt.expr = rhs + range_stmt.body = body + return range_stmt } if p.curr_tok.kind != .Semicolon { - cond = parse_simple_stmt(p, {Stmt_Allow_Flag.In}); + cond = parse_simple_stmt(p, {Stmt_Allow_Flag.In}) if as, ok := cond.derived.(ast.Assign_Stmt); ok && as.op.kind == .In { - is_range = true; + is_range = true } } if !is_range && parse_control_statement_semicolon_separator(p) { - init = cond; - cond = nil; + init = cond + cond = nil if p.curr_tok.kind == .Open_Brace || p.curr_tok.kind == .Do { - error(p, p.curr_tok.pos, "Expected ';', followed by a condition expression and post statement, got %s", tokenizer.tokens[p.curr_tok.kind]); + error(p, p.curr_tok.pos, "Expected ';', followed by a condition expression and post statement, got %s", tokenizer.tokens[p.curr_tok.kind]) } else { if p.curr_tok.kind != .Semicolon { - cond = parse_simple_stmt(p, nil); + cond = parse_simple_stmt(p, nil) } if p.curr_tok.text != ";" { - error(p, p.curr_tok.pos, "Expected ';', got %s", tokenizer.token_to_string(p.curr_tok)); + error(p, p.curr_tok.pos, "Expected ';', got %s", tokenizer.token_to_string(p.curr_tok)) } else { - expect_semicolon(p, nil); + expect_semicolon(p, nil) } if p.curr_tok.kind != .Open_Brace && p.curr_tok.kind != .Do { - post = parse_simple_stmt(p, nil); + post = parse_simple_stmt(p, nil) } } } } if allow_token(p, .Do) { - body = convert_stmt_to_body(p, parse_stmt(p)); + body = convert_stmt_to_body(p, parse_stmt(p)) if tok.pos.line != body.pos.line { - error(p, body.pos, "the body of a 'do' must be on the same line as the 'for' token"); + error(p, body.pos, "the body of a 'do' must be on the same line as the 'for' token") } } else { - body = parse_body(p); + body = parse_body(p) } if is_range { - assign_stmt := cond.derived.(ast.Assign_Stmt); - vals := assign_stmt.lhs[:]; + assign_stmt := cond.derived.(ast.Assign_Stmt) + vals := assign_stmt.lhs[:] - rhs: ^ast.Expr; + rhs: ^ast.Expr if len(assign_stmt.rhs) > 0 { - rhs = assign_stmt.rhs[0]; + rhs = assign_stmt.rhs[0] } - range_stmt := ast.new(ast.Range_Stmt, tok.pos, body.end); - range_stmt.for_pos = tok.pos; - range_stmt.vals = vals; - range_stmt.in_pos = assign_stmt.op.pos; - range_stmt.expr = rhs; - range_stmt.body = body; - return range_stmt; + range_stmt := ast.new(ast.Range_Stmt, tok.pos, body.end) + range_stmt.for_pos = tok.pos + range_stmt.vals = vals + range_stmt.in_pos = assign_stmt.op.pos + range_stmt.expr = rhs + range_stmt.body = body + return range_stmt } - cond_expr := convert_stmt_to_expr(p, cond, "boolean expression"); - for_stmt := ast.new(ast.For_Stmt, tok.pos, body.end); - for_stmt.for_pos = tok.pos; - for_stmt.init = init; - for_stmt.cond = cond_expr; - for_stmt.post = post; - for_stmt.body = body; - return for_stmt; + cond_expr := convert_stmt_to_expr(p, cond, "boolean expression") + for_stmt := ast.new(ast.For_Stmt, tok.pos, body.end) + for_stmt.for_pos = tok.pos + for_stmt.init = init + for_stmt.cond = cond_expr + for_stmt.post = post + for_stmt.body = body + return for_stmt } parse_case_clause :: proc(p: ^Parser, is_type_switch: bool) -> ^ast.Case_Clause { - tok := expect_token(p, .Case); + tok := expect_token(p, .Case) - list: []^ast.Expr; + list: []^ast.Expr if p.curr_tok.kind != .Colon { - prev_allow_range, prev_allow_in_expr := p.allow_range, p.allow_in_expr; - defer p.allow_range, p.allow_in_expr = prev_allow_range, prev_allow_in_expr; - p.allow_range, p.allow_in_expr = !is_type_switch, !is_type_switch; + prev_allow_range, prev_allow_in_expr := p.allow_range, p.allow_in_expr + defer p.allow_range, p.allow_in_expr = prev_allow_range, prev_allow_in_expr + p.allow_range, p.allow_in_expr = !is_type_switch, !is_type_switch - list = parse_rhs_expr_list(p); + list = parse_rhs_expr_list(p) } - terminator := expect_token(p, .Colon); + terminator := expect_token(p, .Colon) - stmts := parse_stmt_list(p); + stmts := parse_stmt_list(p) - cc := ast.new(ast.Case_Clause, tok.pos, end_pos(p.prev_tok)); - cc.list = list; - cc.terminator = terminator; - cc.body = stmts; - cc.case_pos = tok.pos; - return cc; + cc := ast.new(ast.Case_Clause, tok.pos, end_pos(p.prev_tok)) + cc.list = list + cc.terminator = terminator + cc.body = stmts + cc.case_pos = tok.pos + return cc } parse_switch_stmt :: proc(p: ^Parser) -> ^ast.Stmt { - tok := expect_token(p, .Switch); + tok := expect_token(p, .Switch) - init: ^ast.Stmt; - tag: ^ast.Stmt; - is_type_switch := false; - clauses: [dynamic]^ast.Stmt; + init: ^ast.Stmt + tag: ^ast.Stmt + is_type_switch := false + clauses: [dynamic]^ast.Stmt if p.curr_tok.kind != .Open_Brace { - prev_level := p.expr_level; - defer p.expr_level = prev_level; - p.expr_level = -1; + prev_level := p.expr_level + defer p.expr_level = prev_level + p.expr_level = -1 if p.curr_tok.kind == .In { - in_tok := expect_token(p, .In); - is_type_switch = true; - - lhs := make([]^ast.Expr, 1); - rhs := make([]^ast.Expr, 1); - lhs[0] = new_blank_ident(p, tok.pos); - rhs[0] = parse_expr(p, true); - - as := ast.new(ast.Assign_Stmt, tok.pos, rhs[0].end); - as.lhs = lhs; - as.op = in_tok; - as.rhs = rhs; - tag = as; + in_tok := expect_token(p, .In) + is_type_switch = true + + lhs := make([]^ast.Expr, 1) + rhs := make([]^ast.Expr, 1) + lhs[0] = new_blank_ident(p, tok.pos) + rhs[0] = parse_expr(p, true) + + as := ast.new(ast.Assign_Stmt, tok.pos, rhs[0].end) + as.lhs = lhs + as.op = in_tok + as.rhs = rhs + tag = as } else { - tag = parse_simple_stmt(p, {Stmt_Allow_Flag.In}); + tag = parse_simple_stmt(p, {Stmt_Allow_Flag.In}) if as, ok := tag.derived.(ast.Assign_Stmt); ok && as.op.kind == .In { - is_type_switch = true; + is_type_switch = true } else if parse_control_statement_semicolon_separator(p) { - init = tag; - tag = nil; + init = tag + tag = nil if p.curr_tok.kind != .Open_Brace { - tag = parse_simple_stmt(p, nil); + tag = parse_simple_stmt(p, nil) } } } } - skip_possible_newline(p); - open := expect_token(p, .Open_Brace); + skip_possible_newline(p) + open := expect_token(p, .Open_Brace) for p.curr_tok.kind == .Case { - clause := parse_case_clause(p, is_type_switch); - append(&clauses, clause); + clause := parse_case_clause(p, is_type_switch) + append(&clauses, clause) } - close := expect_token(p, .Close_Brace); + close := expect_token(p, .Close_Brace) - body := ast.new(ast.Block_Stmt, open.pos, end_pos(close)); - body.stmts = clauses[:]; + body := ast.new(ast.Block_Stmt, open.pos, end_pos(close)) + body.stmts = clauses[:] if is_type_switch { - ts := ast.new(ast.Type_Switch_Stmt, tok.pos, body.end); - ts.tag = tag; - ts.body = body; - ts.switch_pos = tok.pos; - return ts; + ts := ast.new(ast.Type_Switch_Stmt, tok.pos, body.end) + ts.tag = tag + ts.body = body + ts.switch_pos = tok.pos + return ts } else { - cond := convert_stmt_to_expr(p, tag, "switch expression"); - ts := ast.new(ast.Switch_Stmt, tok.pos, body.end); - ts.init = init; - ts.cond = cond; - ts.body = body; - ts.switch_pos = tok.pos; - return ts; + cond := convert_stmt_to_expr(p, tag, "switch expression") + ts := ast.new(ast.Switch_Stmt, tok.pos, body.end) + ts.init = init + ts.cond = cond + ts.body = body + ts.switch_pos = tok.pos + return ts } } parse_attribute :: proc(p: ^Parser, tok: tokenizer.Token, open_kind, close_kind: tokenizer.Token_Kind, docs: ^ast.Comment_Group) -> ^ast.Stmt { - elems: [dynamic]^ast.Expr; + elems: [dynamic]^ast.Expr - open, close: tokenizer.Token; + open, close: tokenizer.Token if p.curr_tok.kind == .Ident { - elem := parse_ident(p); - append(&elems, elem); + elem := parse_ident(p) + append(&elems, elem) } else { - open = expect_token(p, open_kind); - p.expr_level += 1; + open = expect_token(p, open_kind) + p.expr_level += 1 for p.curr_tok.kind != close_kind && p.curr_tok.kind != .EOF { - elem: ^ast.Expr; - elem = parse_ident(p); + elem: ^ast.Expr + elem = parse_ident(p) if p.curr_tok.kind == .Eq { - eq := expect_token(p, .Eq); - value := parse_value(p); - fv := ast.new(ast.Field_Value, elem.pos, value.end); - fv.field = elem; - fv.sep = eq.pos; - fv.value = value; + eq := expect_token(p, .Eq) + value := parse_value(p) + fv := ast.new(ast.Field_Value, elem.pos, value.end) + fv.field = elem + fv.sep = eq.pos + fv.value = value - elem = fv; + elem = fv } - append(&elems, elem); + append(&elems, elem) if !allow_token(p, .Comma) { - break; + break } } - p.expr_level -= 1; - close = expect_token_after(p, close_kind, "attribute"); + p.expr_level -= 1 + close = expect_token_after(p, close_kind, "attribute") } - attribute := ast.new(ast.Attribute, tok.pos, end_pos(close)); - attribute.tok = tok.kind; - attribute.open = open.pos; - attribute.elems = elems[:]; - attribute.close = close.pos; + attribute := ast.new(ast.Attribute, tok.pos, end_pos(close)) + attribute.tok = tok.kind + attribute.open = open.pos + attribute.elems = elems[:] + attribute.close = close.pos - skip_possible_newline(p); + skip_possible_newline(p) - decl := parse_stmt(p); + decl := parse_stmt(p) switch d in &decl.derived { case ast.Value_Decl: if d.docs == nil { d.docs = docs; } - append(&d.attributes, attribute); + append(&d.attributes, attribute) case ast.Foreign_Block_Decl: if d.docs == nil { d.docs = docs; } - append(&d.attributes, attribute); + append(&d.attributes, attribute) case ast.Foreign_Import_Decl: if d.docs == nil { d.docs = docs; } - append(&d.attributes, attribute); + append(&d.attributes, attribute) case: - error(p, decl.pos, "expected a value or foreign declaration after an attribute"); - free(attribute); - delete(elems); + error(p, decl.pos, "expected a value or foreign declaration after an attribute") + free(attribute) + delete(elems) } - return decl; + return decl } parse_foreign_block_decl :: proc(p: ^Parser) -> ^ast.Stmt { - decl := parse_stmt(p); + decl := parse_stmt(p) switch in decl.derived { case ast.Empty_Stmt, ast.Bad_Stmt, ast.Bad_Decl: // Ignore - return nil; + return nil case ast.When_Stmt, ast.Value_Decl: - return decl; + return decl } - error(p, decl.pos, "foreign blocks only allow procedure and variable declarations"); + error(p, decl.pos, "foreign blocks only allow procedure and variable declarations") - return nil; + return nil } parse_foreign_block :: proc(p: ^Parser, tok: tokenizer.Token) -> ^ast.Foreign_Block_Decl { - docs := p.lead_comment; + docs := p.lead_comment - foreign_library: ^ast.Expr; + foreign_library: ^ast.Expr #partial switch p.curr_tok.kind { case .Open_Brace: - i := ast.new(ast.Ident, tok.pos, end_pos(tok)); - i.name = "_"; - foreign_library = i; + i := ast.new(ast.Ident, tok.pos, end_pos(tok)) + i.name = "_" + foreign_library = i case: - foreign_library = parse_ident(p); + foreign_library = parse_ident(p) } - decls: [dynamic]^ast.Stmt; + decls: [dynamic]^ast.Stmt - prev_in_foreign_block := p.in_foreign_block; - defer p.in_foreign_block = prev_in_foreign_block; - p.in_foreign_block = true; + prev_in_foreign_block := p.in_foreign_block + defer p.in_foreign_block = prev_in_foreign_block + p.in_foreign_block = true - skip_possible_newline_for_literal(p); - open := expect_token(p, .Open_Brace); + skip_possible_newline_for_literal(p) + open := expect_token(p, .Open_Brace) for p.curr_tok.kind != .Close_Brace && p.curr_tok.kind != .EOF { - decl := parse_foreign_block_decl(p); + decl := parse_foreign_block_decl(p) if decl != nil { - append(&decls, decl); + append(&decls, decl) } } - close := expect_token(p, .Close_Brace); + close := expect_token(p, .Close_Brace) - body := ast.new(ast.Block_Stmt, open.pos, end_pos(close)); - body.open = open.pos; - body.stmts = decls[:]; - body.close = close.pos; + body := ast.new(ast.Block_Stmt, open.pos, end_pos(close)) + body.open = open.pos + body.stmts = decls[:] + body.close = close.pos - decl := ast.new(ast.Foreign_Block_Decl, tok.pos, body.end); - decl.docs = docs; - decl.tok = tok; - decl.foreign_library = foreign_library; - decl.body = body; - return decl; + decl := ast.new(ast.Foreign_Block_Decl, tok.pos, body.end) + decl.docs = docs + decl.tok = tok + decl.foreign_library = foreign_library + decl.body = body + return decl } parse_foreign_decl :: proc(p: ^Parser) -> ^ast.Decl { - docs := p.lead_comment; - tok := expect_token(p, .Foreign); + docs := p.lead_comment + tok := expect_token(p, .Foreign) #partial switch p.curr_tok.kind { case .Ident, .Open_Brace: - return parse_foreign_block(p, tok); + return parse_foreign_block(p, tok) case .Import: - import_tok := expect_token(p, .Import); - name: ^ast.Ident; + import_tok := expect_token(p, .Import) + name: ^ast.Ident if p.curr_tok.kind == .Ident { - name = parse_ident(p); + name = parse_ident(p) } if name != nil && is_blank_ident(name) { - error(p, name.pos, "illegal foreign import name: '_'"); + error(p, name.pos, "illegal foreign import name: '_'") } - fullpaths: [dynamic]string; + fullpaths: [dynamic]string if allow_token(p, .Open_Brace) { for p.curr_tok.kind != .Close_Brace && p.curr_tok.kind != .EOF { - path := expect_token(p, .String); - append(&fullpaths, path.text); + path := expect_token(p, .String) + append(&fullpaths, path.text) if !allow_token(p, .Comma) { - break; + break } } - expect_token(p, .Close_Brace); + expect_token(p, .Close_Brace) } else { - path := expect_token(p, .String); - reserve(&fullpaths, 1); - append(&fullpaths, path.text); + path := expect_token(p, .String) + reserve(&fullpaths, 1) + append(&fullpaths, path.text) } if len(fullpaths) == 0 { - error(p, import_tok.pos, "foreign import without any paths"); + error(p, import_tok.pos, "foreign import without any paths") } - decl := ast.new(ast.Foreign_Import_Decl, tok.pos, end_pos(p.prev_tok)); - decl.docs = docs; - decl.foreign_tok = tok; - decl.import_tok = import_tok; - decl.name = name; - decl.fullpaths = fullpaths[:]; - expect_semicolon(p, decl); - decl.comment = p.line_comment; - return decl; + decl := ast.new(ast.Foreign_Import_Decl, tok.pos, end_pos(p.prev_tok)) + decl.docs = docs + decl.foreign_tok = tok + decl.import_tok = import_tok + decl.name = name + decl.fullpaths = fullpaths[:] + expect_semicolon(p, decl) + decl.comment = p.line_comment + return decl } - error(p, tok.pos, "invalid foreign declaration"); - return ast.new(ast.Bad_Decl, tok.pos, end_pos(tok)); + error(p, tok.pos, "invalid foreign declaration") + return ast.new(ast.Bad_Decl, tok.pos, end_pos(tok)) } parse_unrolled_for_loop :: proc(p: ^Parser, inline_tok: tokenizer.Token) -> ^ast.Stmt { - for_tok := expect_token(p, .For); - val0, val1: ^ast.Expr; - in_tok: tokenizer.Token; - expr: ^ast.Expr; - body: ^ast.Stmt; + for_tok := expect_token(p, .For) + val0, val1: ^ast.Expr + in_tok: tokenizer.Token + expr: ^ast.Expr + body: ^ast.Stmt - bad_stmt := false; + bad_stmt := false if p.curr_tok.kind != .In { - idents := parse_ident_list(p, false); + idents := parse_ident_list(p, false) switch len(idents) { case 1: - val0 = idents[0]; + val0 = idents[0] case 2: - val0, val1 = idents[0], idents[1]; + val0, val1 = idents[0], idents[1] case: - error(p, for_tok.pos, "expected either 1 or 2 identifiers"); - bad_stmt = true; + error(p, for_tok.pos, "expected either 1 or 2 identifiers") + bad_stmt = true } } - in_tok = expect_token(p, .In); + in_tok = expect_token(p, .In) - prev_allow_range := p.allow_range; - prev_level := p.expr_level; - p.allow_range = true; - p.expr_level = -1; + prev_allow_range := p.allow_range + prev_level := p.expr_level + p.allow_range = true + p.expr_level = -1 - expr = parse_expr(p, false); + expr = parse_expr(p, false) - p.expr_level = prev_level; - p.allow_range = prev_allow_range; + p.expr_level = prev_level + p.allow_range = prev_allow_range if allow_token(p, .Do) { - body = convert_stmt_to_body(p, parse_stmt(p)); + body = convert_stmt_to_body(p, parse_stmt(p)) if for_tok.pos.line != body.pos.line { - error(p, body.pos, "the body of a 'do' must be on the same line as the 'for' token"); + error(p, body.pos, "the body of a 'do' must be on the same line as the 'for' token") } } else { - body = parse_block_stmt(p, false); + body = parse_block_stmt(p, false) } if bad_stmt { - return ast.new(ast.Bad_Stmt, inline_tok.pos, end_pos(p.prev_tok)); + return ast.new(ast.Bad_Stmt, inline_tok.pos, end_pos(p.prev_tok)) } - range_stmt := ast.new(ast.Inline_Range_Stmt, inline_tok.pos, body.end); - range_stmt.inline_pos = inline_tok.pos; - range_stmt.for_pos = for_tok.pos; - range_stmt.val0 = val0; - range_stmt.val1 = val1; - range_stmt.in_pos = in_tok.pos; - range_stmt.expr = expr; - range_stmt.body = body; - return range_stmt; + range_stmt := ast.new(ast.Inline_Range_Stmt, inline_tok.pos, body.end) + range_stmt.inline_pos = inline_tok.pos + range_stmt.for_pos = for_tok.pos + range_stmt.val0 = val0 + range_stmt.val1 = val1 + range_stmt.in_pos = in_tok.pos + range_stmt.expr = expr + range_stmt.body = body + return range_stmt } parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt { #partial switch p.curr_tok.kind { case .Inline: if peek_token_kind(p, .For) { - inline_tok := expect_token(p, .Inline); - return parse_unrolled_for_loop(p, inline_tok); + inline_tok := expect_token(p, .Inline) + return parse_unrolled_for_loop(p, inline_tok) } - fallthrough; + fallthrough // Operands case .No_Inline, .Context, // Also allows for 'context = ' @@ -1263,326 +1263,326 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt { // Unary Expressions .Add, .Sub, .Xor, .Not, .And: - s := parse_simple_stmt(p, {Stmt_Allow_Flag.Label}); - expect_semicolon(p, s); - return s; + s := parse_simple_stmt(p, {Stmt_Allow_Flag.Label}) + expect_semicolon(p, s) + return s - case .Foreign: return parse_foreign_decl(p); - case .Import: return parse_import_decl(p); - case .If: return parse_if_stmt(p); - case .When: return parse_when_stmt(p); - case .For: return parse_for_stmt(p); - case .Switch: return parse_switch_stmt(p); + case .Foreign: return parse_foreign_decl(p) + case .Import: return parse_import_decl(p) + case .If: return parse_if_stmt(p) + case .When: return parse_when_stmt(p) + case .For: return parse_for_stmt(p) + case .Switch: return parse_switch_stmt(p) case .Defer: - tok := advance_token(p); - stmt := parse_stmt(p); + tok := advance_token(p) + stmt := parse_stmt(p) switch s in stmt.derived { case ast.Empty_Stmt: - error(p, s.pos, "empty statement after defer (e.g. ';')"); + error(p, s.pos, "empty statement after defer (e.g. ';')") case ast.Defer_Stmt: - error(p, s.pos, "you cannot defer a defer statement"); - stmt = s.stmt; + error(p, s.pos, "you cannot defer a defer statement") + stmt = s.stmt case ast.Return_Stmt: - error(p, s.pos, "you cannot defer a return statement"); + error(p, s.pos, "you cannot defer a return statement") } - ds := ast.new(ast.Defer_Stmt, tok.pos, stmt.end); - ds.stmt = stmt; - return ds; + ds := ast.new(ast.Defer_Stmt, tok.pos, stmt.end) + ds.stmt = stmt + return ds case .Return: - tok := advance_token(p); + tok := advance_token(p) if p.expr_level > 0 { - error(p, tok.pos, "you cannot use a return statement within an expression"); + error(p, tok.pos, "you cannot use a return statement within an expression") } - results: [dynamic]^ast.Expr; + results: [dynamic]^ast.Expr for p.curr_tok.kind != .Semicolon { - result := parse_expr(p, false); - append(&results, result); + result := parse_expr(p, false) + append(&results, result) if p.curr_tok.kind != .Comma || p.curr_tok.kind == .EOF { - break; + break } - advance_token(p); + advance_token(p) } - end := end_pos(tok); + end := end_pos(tok) if len(results) > 0 { - end = results[len(results)-1].end; + end = results[len(results)-1].end } - rs := ast.new(ast.Return_Stmt, tok.pos, end); - rs.results = results[:]; - return rs; + rs := ast.new(ast.Return_Stmt, tok.pos, end) + rs.results = results[:] + return rs case .Break, .Continue, .Fallthrough: - tok := advance_token(p); - label: ^ast.Ident; + tok := advance_token(p) + label: ^ast.Ident if tok.kind != .Fallthrough && p.curr_tok.kind == .Ident { - label = parse_ident(p); + label = parse_ident(p) } - end := label.end if label != nil else end_pos(tok); - s := ast.new(ast.Branch_Stmt, tok.pos, end); - s.tok = tok; - s.label = label; - expect_semicolon(p, s); - return s; + end := label.end if label != nil else end_pos(tok) + s := ast.new(ast.Branch_Stmt, tok.pos, end) + s.tok = tok + s.label = label + expect_semicolon(p, s) + return s case .Using: - docs := p.lead_comment; - tok := expect_token(p, .Using); + docs := p.lead_comment + tok := expect_token(p, .Using) if p.curr_tok.kind == .Import { - return parse_import_decl(p, Import_Decl_Kind.Using); + return parse_import_decl(p, Import_Decl_Kind.Using) } - list := parse_lhs_expr_list(p); + list := parse_lhs_expr_list(p) if len(list) == 0 { - error(p, tok.pos, "illegal use of 'using' statement"); - expect_semicolon(p, nil); - return ast.new(ast.Bad_Stmt, tok.pos, end_pos(p.prev_tok)); + error(p, tok.pos, "illegal use of 'using' statement") + expect_semicolon(p, nil) + return ast.new(ast.Bad_Stmt, tok.pos, end_pos(p.prev_tok)) } if p.curr_tok.kind != .Colon { - end := list[len(list)-1]; - expect_semicolon(p, end); - us := ast.new(ast.Using_Stmt, tok.pos, end.end); - us.list = list; - return us; - } - expect_token_after(p, .Colon, "identifier list"); - decl := parse_value_decl(p, list, docs); + end := list[len(list)-1] + expect_semicolon(p, end) + us := ast.new(ast.Using_Stmt, tok.pos, end.end) + us.list = list + return us + } + expect_token_after(p, .Colon, "identifier list") + decl := parse_value_decl(p, list, docs) if decl != nil { switch d in &decl.derived { case ast.Value_Decl: - d.is_using = true; - return decl; + d.is_using = true + return decl } } - error(p, tok.pos, "illegal use of 'using' statement"); - return ast.new(ast.Bad_Stmt, tok.pos, end_pos(p.prev_tok)); + error(p, tok.pos, "illegal use of 'using' statement") + return ast.new(ast.Bad_Stmt, tok.pos, end_pos(p.prev_tok)) case .At: - docs := p.lead_comment; - tok := advance_token(p); - return parse_attribute(p, tok, .Open_Paren, .Close_Paren, docs); + docs := p.lead_comment + tok := advance_token(p) + return parse_attribute(p, tok, .Open_Paren, .Close_Paren, docs) case .Hash: - tok := expect_token(p, .Hash); - tag := expect_token(p, .Ident); - name := tag.text; + tok := expect_token(p, .Hash) + tag := expect_token(p, .Ident) + name := tag.text switch name { case "bounds_check", "no_bounds_check": - stmt := parse_stmt(p); + stmt := parse_stmt(p) switch name { case "bounds_check": - stmt.state_flags += {.Bounds_Check}; + stmt.state_flags += {.Bounds_Check} case "no_bounds_check": - stmt.state_flags += {.No_Bounds_Check}; + stmt.state_flags += {.No_Bounds_Check} } - return stmt; + return stmt case "partial": - stmt := parse_stmt(p); + stmt := parse_stmt(p) switch s in &stmt.derived { - case ast.Switch_Stmt: s.partial = true; - case ast.Type_Switch_Stmt: s.partial = true; - case: error(p, stmt.pos, "#partial can only be applied to a switch statement"); + case ast.Switch_Stmt: s.partial = true + case ast.Type_Switch_Stmt: s.partial = true + case: error(p, stmt.pos, "#partial can only be applied to a switch statement") } - return stmt; + return stmt case "assert", "panic": - bd := ast.new(ast.Basic_Directive, tok.pos, end_pos(tag)); - bd.tok = tok; - bd.name = name; - ce := parse_call_expr(p, bd); - es := ast.new(ast.Expr_Stmt, ce.pos, ce.end); - es.expr = ce; - return es; + bd := ast.new(ast.Basic_Directive, tok.pos, end_pos(tag)) + bd.tok = tok + bd.name = name + ce := parse_call_expr(p, bd) + es := ast.new(ast.Expr_Stmt, ce.pos, ce.end) + es.expr = ce + return es case "force_inline", "force_no_inline": - expr := parse_inlining_operand(p, true, tok); - es := ast.new(ast.Expr_Stmt, expr.pos, expr.end); - es.expr = expr; - return es; + expr := parse_inlining_operand(p, true, tok) + es := ast.new(ast.Expr_Stmt, expr.pos, expr.end) + es.expr = expr + return es case "unroll": - return parse_unrolled_for_loop(p, tag); + return parse_unrolled_for_loop(p, tag) case "include": - error(p, tag.pos, "#include is not a valid import declaration kind. Did you meant 'import'?"); - return ast.new(ast.Bad_Stmt, tok.pos, end_pos(tag)); + error(p, tag.pos, "#include is not a valid import declaration kind. Did you meant 'import'?") + return ast.new(ast.Bad_Stmt, tok.pos, end_pos(tag)) case: - stmt := parse_stmt(p); - te := ast.new(ast.Tag_Stmt, tok.pos, stmt.pos); - te.op = tok; - te.name = name; - te.stmt = stmt; + stmt := parse_stmt(p) + te := ast.new(ast.Tag_Stmt, tok.pos, stmt.pos) + te.op = tok + te.name = name + te.stmt = stmt - fix_advance_to_next_stmt(p); - return te; + fix_advance_to_next_stmt(p) + return te } case .Open_Brace: - return parse_block_stmt(p, false); + return parse_block_stmt(p, false) case .Semicolon: - tok := advance_token(p); - s := ast.new(ast.Empty_Stmt, tok.pos, end_pos(tok)); - return s; + tok := advance_token(p) + s := ast.new(ast.Empty_Stmt, tok.pos, end_pos(tok)) + return s } #partial switch p.curr_tok.kind { case .Else: - token := expect_token(p, .Else); - error(p, token.pos, "'else' unattached to an 'if' statement"); + token := expect_token(p, .Else) + error(p, token.pos, "'else' unattached to an 'if' statement") #partial switch p.curr_tok.kind { case .If: - return parse_if_stmt(p); + return parse_if_stmt(p) case .When: - return parse_when_stmt(p); + return parse_when_stmt(p) case .Open_Brace: - return parse_block_stmt(p, true); + return parse_block_stmt(p, true) case .Do: - expect_token(p, .Do); - return convert_stmt_to_body(p, parse_stmt(p)); + expect_token(p, .Do) + return convert_stmt_to_body(p, parse_stmt(p)) case: - fix_advance_to_next_stmt(p); - return ast.new(ast.Bad_Stmt, token.pos, end_pos(p.curr_tok)); + fix_advance_to_next_stmt(p) + return ast.new(ast.Bad_Stmt, token.pos, end_pos(p.curr_tok)) } } - tok := advance_token(p); - error(p, tok.pos, "expected a statement, got %s", tokenizer.token_to_string(tok)); - fix_advance_to_next_stmt(p); - s := ast.new(ast.Bad_Stmt, tok.pos, end_pos(tok)); - return s; + tok := advance_token(p) + error(p, tok.pos, "expected a statement, got %s", tokenizer.token_to_string(tok)) + fix_advance_to_next_stmt(p) + s := ast.new(ast.Bad_Stmt, tok.pos, end_pos(tok)) + return s } token_precedence :: proc(p: ^Parser, kind: tokenizer.Token_Kind) -> int { #partial switch kind { case .Question, .If, .When, .Or_Else: - return 1; + return 1 case .Ellipsis, .Range_Half, .Range_Full: if !p.allow_range { - return 0; + return 0 } - return 2; + return 2 case .Cmp_Or: - return 3; + return 3 case .Cmp_And: - return 4; + return 4 case .Cmp_Eq, .Not_Eq, .Lt, .Gt, .Lt_Eq, .Gt_Eq: - return 5; + return 5 case .In, .Not_In: if p.expr_level < 0 && !p.allow_in_expr { - return 0; + return 0 } - fallthrough; + fallthrough case .Add, .Sub, .Or, .Xor: - return 6; + return 6 case .Mul, .Quo, .Mod, .Mod_Mod, .And, .And_Not, .Shl, .Shr: - return 7; + return 7 } - return 0; + return 0 } parse_type_or_ident :: proc(p: ^Parser) -> ^ast.Expr { - prev_allow_type := p.allow_type; - prev_expr_level := p.expr_level; + prev_allow_type := p.allow_type + prev_expr_level := p.expr_level defer { - p.allow_type = prev_allow_type; - p.expr_level = prev_expr_level; + p.allow_type = prev_allow_type + p.expr_level = prev_expr_level } - p.allow_type = true; - p.expr_level = -1; + p.allow_type = true + p.expr_level = -1 - lhs := true; - return parse_atom_expr(p, parse_operand(p, lhs), lhs); + lhs := true + return parse_atom_expr(p, parse_operand(p, lhs), lhs) } parse_type :: proc(p: ^Parser) -> ^ast.Expr { - type := parse_type_or_ident(p); + type := parse_type_or_ident(p) if type == nil { - error(p, p.curr_tok.pos, "expected a type"); - return ast.new(ast.Bad_Expr, p.curr_tok.pos, end_pos(p.curr_tok)); + error(p, p.curr_tok.pos, "expected a type") + return ast.new(ast.Bad_Expr, p.curr_tok.pos, end_pos(p.curr_tok)) } - return type; + return type } parse_body :: proc(p: ^Parser) -> ^ast.Block_Stmt { - prev_expr_level := p.expr_level; - defer p.expr_level = prev_expr_level; + prev_expr_level := p.expr_level + defer p.expr_level = prev_expr_level - p.expr_level = 0; - open := expect_token(p, .Open_Brace); - stmts := parse_stmt_list(p); - close := expect_token(p, .Close_Brace); + p.expr_level = 0 + open := expect_token(p, .Open_Brace) + stmts := parse_stmt_list(p) + close := expect_token(p, .Close_Brace) - bs := ast.new(ast.Block_Stmt, open.pos, end_pos(close)); - bs.open = open.pos; - bs.stmts = stmts; - bs.close = close.pos; - return bs; + bs := ast.new(ast.Block_Stmt, open.pos, end_pos(close)) + bs.open = open.pos + bs.stmts = stmts + bs.close = close.pos + return bs } convert_stmt_to_body :: proc(p: ^Parser, stmt: ^ast.Stmt) -> ^ast.Stmt { switch s in stmt.derived { case ast.Block_Stmt: - error(p, stmt.pos, "expected a normal statement rather than a block statement"); - return stmt; + error(p, stmt.pos, "expected a normal statement rather than a block statement") + return stmt case ast.Empty_Stmt: - error(p, stmt.pos, "expected a non-empty statement"); + error(p, stmt.pos, "expected a non-empty statement") } - bs := ast.new(ast.Block_Stmt, stmt.pos, stmt.end); - bs.open = stmt.pos; - bs.stmts = make([]^ast.Stmt, 1); - bs.stmts[0] = stmt; - bs.close = stmt.end; - bs.uses_do = true; - return bs; + bs := ast.new(ast.Block_Stmt, stmt.pos, stmt.end) + bs.open = stmt.pos + bs.stmts = make([]^ast.Stmt, 1) + bs.stmts[0] = stmt + bs.close = stmt.end + bs.uses_do = true + return bs } new_ast_field :: proc(names: []^ast.Expr, type: ^ast.Expr, default_value: ^ast.Expr) -> ^ast.Field { - pos, end: tokenizer.Pos; + pos, end: tokenizer.Pos if len(names) > 0 { - pos = names[0].pos; + pos = names[0].pos if default_value != nil { - end = default_value.end; + end = default_value.end } else if type != nil { - end = type.end; + end = type.end } else { - end = names[len(names)-1].pos; + end = names[len(names)-1].pos } } else { if type != nil { - pos = type.pos; + pos = type.pos } else if default_value != nil { - pos = default_value.pos; + pos = default_value.pos } if default_value != nil { - end = default_value.end; + end = default_value.end } else if type != nil { - end = type.end; + end = type.end } } - field := ast.new(ast.Field, pos, end); - field.names = names; - field.type = type; - field.default_value = default_value; - return field; + field := ast.new(ast.Field, pos, end) + field.names = names + field.type = type + field.default_value = default_value + return field } @@ -1597,7 +1597,7 @@ Field_Prefix :: enum { Any_Int, } -Field_Prefixes :: distinct bit_set[Field_Prefix]; +Field_Prefixes :: distinct bit_set[Field_Prefix] Expr_And_Flags :: struct { expr: ^ast.Expr, @@ -1605,16 +1605,16 @@ Expr_And_Flags :: struct { } convert_to_ident_list :: proc(p: ^Parser, list: []Expr_And_Flags, ignore_flags, allow_poly_names: bool) -> []^ast.Expr { - idents := make([dynamic]^ast.Expr, 0, len(list)); + idents := make([dynamic]^ast.Expr, 0, len(list)) for ident, i in list { if !ignore_flags { if i != 0 { - error(p, ident.expr.pos, "illegal use of prefixes in parameter list"); + error(p, ident.expr.pos, "illegal use of prefixes in parameter list") } } - id: ^ast.Expr = ident.expr; + id: ^ast.Expr = ident.expr switch n in ident.expr.derived { case ast.Ident: @@ -1622,74 +1622,74 @@ convert_to_ident_list :: proc(p: ^Parser, list: []Expr_And_Flags, ignore_flags, case ast.Poly_Type: if allow_poly_names { if n.specialization == nil { - break; + break } else { - error(p, ident.expr.pos, "expected a polymorphic identifier without an specialization"); + error(p, ident.expr.pos, "expected a polymorphic identifier without an specialization") } } else { - error(p, ident.expr.pos, "expected a non-polymorphic identifier"); + error(p, ident.expr.pos, "expected a non-polymorphic identifier") } case: - error(p, ident.expr.pos, "expected an identifier"); - id = ast.new(ast.Ident, ident.expr.pos, ident.expr.end); + error(p, ident.expr.pos, "expected an identifier") + id = ast.new(ast.Ident, ident.expr.pos, ident.expr.end) } - append(&idents, id); + append(&idents, id) } - return idents[:]; + return idents[:] } is_token_field_prefix :: proc(p: ^Parser) -> Field_Prefix { #partial switch p.curr_tok.kind { case .EOF: - return .Invalid; + return .Invalid case .Using: - advance_token(p); - return .Using; + advance_token(p) + return .Using case .Auto_Cast: - advance_token(p); - return .Auto_Cast; + advance_token(p) + return .Auto_Cast case .Hash: - advance_token(p); - defer advance_token(p); + advance_token(p) + defer advance_token(p) #partial switch p.curr_tok.kind { case .Ident: switch p.curr_tok.text { case "no_alias": - return .No_Alias; + return .No_Alias case "c_vararg": - return .C_Vararg; + return .C_Vararg case "any_int": - return .Any_Int; + return .Any_Int } } - return .Unknown; + return .Unknown } - return .Invalid; + return .Invalid } parse_field_prefixes :: proc(p: ^Parser) -> ast.Field_Flags { - counts: [len(Field_Prefix)]int; + counts: [len(Field_Prefix)]int for { - kind := is_token_field_prefix(p); + kind := is_token_field_prefix(p) if kind == .Invalid { - break; + break } if kind == .Unknown { - error(p, p.curr_tok.pos, "unknown prefix kind '#%s'", p.curr_tok.text); - continue; + error(p, p.curr_tok.pos, "unknown prefix kind '#%s'", p.curr_tok.text) + continue } - counts[kind] += 1; + counts[kind] += 1 } - flags: ast.Field_Flags; + flags: ast.Field_Flags for kind in Field_Prefix { - count := counts[kind]; + count := counts[kind] switch kind { case .Invalid, .Unknown: // Ignore case .Using: @@ -1710,129 +1710,129 @@ parse_field_prefixes :: proc(p: ^Parser) -> ast.Field_Flags { } } - return flags; + return flags } check_field_flag_prefixes :: proc(p: ^Parser, name_count: int, allowed_flags, set_flags: ast.Field_Flags) -> (flags: ast.Field_Flags) { - flags = set_flags; + flags = set_flags if name_count > 1 && .Using in flags { - error(p, p.curr_tok.pos, "cannot apply 'using' to more than one of the same type"); - flags -= {.Using}; + error(p, p.curr_tok.pos, "cannot apply 'using' to more than one of the same type") + flags -= {.Using} } for flag in ast.Field_Flag { if flag not_in allowed_flags && flag in flags { switch flag { case .Using: - error(p, p.curr_tok.pos, "'using' is not allowed within this field list"); + error(p, p.curr_tok.pos, "'using' is not allowed within this field list") case .No_Alias: - error(p, p.curr_tok.pos, "'#no_alias' is not allowed within this field list"); + error(p, p.curr_tok.pos, "'#no_alias' is not allowed within this field list") case .C_Vararg: - error(p, p.curr_tok.pos, "'#c_vararg' is not allowed within this field list"); + error(p, p.curr_tok.pos, "'#c_vararg' is not allowed within this field list") case .Auto_Cast: - error(p, p.curr_tok.pos, "'auto_cast' is not allowed within this field list"); + error(p, p.curr_tok.pos, "'auto_cast' is not allowed within this field list") case .Any_Int: - error(p, p.curr_tok.pos, "'#any_int' is not allowed within this field list"); + error(p, p.curr_tok.pos, "'#any_int' is not allowed within this field list") case .Tags, .Ellipsis, .Results, .Default_Parameters, .Typeid_Token: - panic("Impossible prefixes"); + panic("Impossible prefixes") } - flags -= {flag}; + flags -= {flag} } } - return flags; + return flags } parse_var_type :: proc(p: ^Parser, flags: ast.Field_Flags) -> ^ast.Expr { if .Ellipsis in flags && p.curr_tok.kind == .Ellipsis { - tok := advance_token(p); - type := parse_type_or_ident(p); + tok := advance_token(p) + type := parse_type_or_ident(p) if type == nil { - error(p, tok.pos, "variadic field missing type after '..'"); - type = ast.new(ast.Bad_Expr, tok.pos, end_pos(tok)); + error(p, tok.pos, "variadic field missing type after '..'") + type = ast.new(ast.Bad_Expr, tok.pos, end_pos(tok)) } - e := ast.new(ast.Ellipsis, type.pos, type.end); - e.expr = type; - return e; + e := ast.new(ast.Ellipsis, type.pos, type.end) + e.expr = type + return e } - type: ^ast.Expr; + type: ^ast.Expr if .Typeid_Token in flags && p.curr_tok.kind == .Typeid { - tok := expect_token(p, .Typeid); - specialization: ^ast.Expr; - end := tok.pos; + tok := expect_token(p, .Typeid) + specialization: ^ast.Expr + end := tok.pos if allow_token(p, .Quo) { - specialization = parse_type(p); - end = specialization.end; + specialization = parse_type(p) + end = specialization.end } - ti := ast.new(ast.Typeid_Type, tok.pos, end); - ti.tok = tok.kind; - ti.specialization = specialization; - type = ti; + ti := ast.new(ast.Typeid_Type, tok.pos, end) + ti.tok = tok.kind + ti.specialization = specialization + type = ti } else { - type = parse_type(p); + type = parse_type(p) } - return type; + return type } check_procedure_name_list :: proc(p: ^Parser, names: []^ast.Expr) -> bool { if len(names) == 0 { - return false; + return false } - _, first_is_polymorphic := names[0].derived.(ast.Poly_Type); - any_polymorphic_names := first_is_polymorphic; + _, first_is_polymorphic := names[0].derived.(ast.Poly_Type) + any_polymorphic_names := first_is_polymorphic for i := 1; i < len(names); i += 1 { - name := names[i]; + name := names[i] if first_is_polymorphic { if _, ok := name.derived.(ast.Poly_Type); ok { - any_polymorphic_names = true; + any_polymorphic_names = true } else { - error(p, name.pos, "mixture of polymorphic and non-polymorphic identifiers"); - return any_polymorphic_names; + error(p, name.pos, "mixture of polymorphic and non-polymorphic identifiers") + return any_polymorphic_names } } else { if _, ok := name.derived.(ast.Poly_Type); ok { - any_polymorphic_names = true; - error(p, name.pos, "mixture of polymorphic and non-polymorphic identifiers"); - return any_polymorphic_names; + any_polymorphic_names = true + error(p, name.pos, "mixture of polymorphic and non-polymorphic identifiers") + return any_polymorphic_names } else { // Okay } } } - return any_polymorphic_names; + return any_polymorphic_names } parse_ident_list :: proc(p: ^Parser, allow_poly_names: bool) -> []^ast.Expr { - list: [dynamic]^ast.Expr; + list: [dynamic]^ast.Expr for { if allow_poly_names && p.curr_tok.kind == .Dollar { - tok := expect_token(p, .Dollar); - ident := parse_ident(p); + tok := expect_token(p, .Dollar) + ident := parse_ident(p) if is_blank_ident(ident) { - error(p, ident.pos, "invalid polymorphic type definition with a blank identifier"); + error(p, ident.pos, "invalid polymorphic type definition with a blank identifier") } - poly_name := ast.new(ast.Poly_Type, tok.pos, ident.end); - poly_name.type = ident; - append(&list, poly_name); + poly_name := ast.new(ast.Poly_Type, tok.pos, ident.end) + poly_name.type = ident + append(&list, poly_name) } else { - ident := parse_ident(p); - append(&list, ident); + ident := parse_ident(p) + append(&list, ident) } if p.curr_tok.kind != .Comma || p.curr_tok.kind == .EOF { - break; + break } - advance_token(p); + advance_token(p) } - return list[:]; + return list[:] } @@ -1846,957 +1846,957 @@ parse_field_list :: proc(p: ^Parser, follow: tokenizer.Token_Kind, allowed_flags ) -> bool { expect_field_separator :: proc(p: ^Parser, param: ^ast.Expr) -> bool { - tok := p.curr_tok; + tok := p.curr_tok if allow_token(p, .Comma) { - return true; + return true } if allow_token(p, .Semicolon) { - error(p, tok.pos, "expected a comma, got a semicolon"); - return true; + error(p, tok.pos, "expected a comma, got a semicolon") + return true } - return false; + return false } is_type_ellipsis :: proc(type: ^ast.Expr) -> bool { if type == nil { - return false; + return false } - _, ok := type.derived.(ast.Ellipsis); - return ok; + _, ok := type.derived.(ast.Ellipsis) + return ok } - is_signature := (allowed_flags & ast.Field_Flags_Signature_Params) == ast.Field_Flags_Signature_Params; + is_signature := (allowed_flags & ast.Field_Flags_Signature_Params) == ast.Field_Flags_Signature_Params - any_polymorphic_names := check_procedure_name_list(p, names); - flags := check_field_flag_prefixes(p, len(names), allowed_flags, set_flags); + any_polymorphic_names := check_procedure_name_list(p, names) + flags := check_field_flag_prefixes(p, len(names), allowed_flags, set_flags) - type: ^ast.Expr; - default_value: ^ast.Expr; - tag: tokenizer.Token; + type: ^ast.Expr + default_value: ^ast.Expr + tag: tokenizer.Token - expect_token_after(p, .Colon, "field list"); + expect_token_after(p, .Colon, "field list") if p.curr_tok.kind != .Eq { - type = parse_var_type(p, allowed_flags); - tt := ast.unparen_expr(type); + type = parse_var_type(p, allowed_flags) + tt := ast.unparen_expr(type) if is_signature && !any_polymorphic_names { if ti, ok := tt.derived.(ast.Typeid_Type); ok && ti.specialization != nil { - error(p, tt.pos, "specialization of typeid is not allowed without polymorphic names"); + error(p, tt.pos, "specialization of typeid is not allowed without polymorphic names") } } } if allow_token(p, .Eq) { - default_value = parse_expr(p, false); + default_value = parse_expr(p, false) if .Default_Parameters not_in allowed_flags { - error(p, p.curr_tok.pos, "default parameters are only allowed for procedures"); - default_value = nil; + error(p, p.curr_tok.pos, "default parameters are only allowed for procedures") + default_value = nil } } if default_value != nil && len(names) > 1 { - error(p, p.curr_tok.pos, "default parameters can only be applied to single values"); + error(p, p.curr_tok.pos, "default parameters can only be applied to single values") } if allowed_flags == ast.Field_Flags_Struct && default_value != nil { - error(p, default_value.pos, "default parameters are not allowed for structs"); - default_value = nil; + error(p, default_value.pos, "default parameters are not allowed for structs") + default_value = nil } if is_type_ellipsis(type) { if seen_ellipsis^ { - error(p, type.pos, "extra variadic parameter after ellipsis"); + error(p, type.pos, "extra variadic parameter after ellipsis") } - seen_ellipsis^ = true; + seen_ellipsis^ = true if len(names) != 1 { - error(p, type.pos, "variadic parameters can only have one field name"); + error(p, type.pos, "variadic parameters can only have one field name") } } else if seen_ellipsis^ && default_value == nil { - error(p, p.curr_tok.pos, "extra parameter after ellipsis without a default value"); + error(p, p.curr_tok.pos, "extra parameter after ellipsis without a default value") } if type != nil && default_value == nil { if p.curr_tok.kind == .String { - tag = expect_token(p, .String); + tag = expect_token(p, .String) if .Tags not_in allowed_flags { - error(p, tag.pos, "Field tags are only allowed within structures"); + error(p, tag.pos, "Field tags are only allowed within structures") } } } - ok := expect_field_separator(p, type); + ok := expect_field_separator(p, type) - field := new_ast_field(names, type, default_value); - field.tag = tag; - field.docs = docs; - field.flags = flags; - field.comment = p.line_comment; - append(fields, field); + field := new_ast_field(names, type, default_value) + field.tag = tag + field.docs = docs + field.flags = flags + field.comment = p.line_comment + append(fields, field) - return ok; + return ok } - start_tok := p.curr_tok; + start_tok := p.curr_tok - docs := p.lead_comment; + docs := p.lead_comment - fields: [dynamic]^ast.Field; + fields: [dynamic]^ast.Field - list: [dynamic]Expr_And_Flags; - defer delete(list); + list: [dynamic]Expr_And_Flags + defer delete(list) - seen_ellipsis := false; + seen_ellipsis := false - allow_typeid_token := .Typeid_Token in allowed_flags; - allow_poly_names := allow_typeid_token; + allow_typeid_token := .Typeid_Token in allowed_flags + allow_poly_names := allow_typeid_token for p.curr_tok.kind != follow && p.curr_tok.kind != .Colon && p.curr_tok.kind != .EOF { - prefix_flags := parse_field_prefixes(p); - param := parse_var_type(p, allowed_flags & {.Typeid_Token, .Ellipsis}); + prefix_flags := parse_field_prefixes(p) + param := parse_var_type(p, allowed_flags & {.Typeid_Token, .Ellipsis}) if _, ok := param.derived.(ast.Ellipsis); ok { if seen_ellipsis { - error(p, param.pos, "extra variadic parameter after ellipsis"); + error(p, param.pos, "extra variadic parameter after ellipsis") } - seen_ellipsis = true; + seen_ellipsis = true } else if seen_ellipsis { - error(p, param.pos, "extra parameter after ellipsis"); + error(p, param.pos, "extra parameter after ellipsis") } - eaf := Expr_And_Flags{param, prefix_flags}; - append(&list, eaf); + eaf := Expr_And_Flags{param, prefix_flags} + append(&list, eaf) if !allow_token(p, .Comma) { - break; + break } } if p.curr_tok.kind != .Colon { for eaf in list { - type := eaf.expr; - tok: tokenizer.Token; - tok.pos = type.pos; + type := eaf.expr + tok: tokenizer.Token + tok.pos = type.pos if .Results not_in allowed_flags { - tok.text = "_"; + tok.text = "_" } - names := make([]^ast.Expr, 1); - names[0] = ast.new(ast.Ident, tok.pos, end_pos(tok)); + names := make([]^ast.Expr, 1) + names[0] = ast.new(ast.Ident, tok.pos, end_pos(tok)) switch ident in &names[0].derived { case ast.Ident: - ident.name = tok.text; + ident.name = tok.text case: - unreachable(); + unreachable() } - flags := check_field_flag_prefixes(p, len(list), allowed_flags, eaf.flags); + flags := check_field_flag_prefixes(p, len(list), allowed_flags, eaf.flags) - field := new_ast_field(names, type, nil); - field.docs = docs; - field.flags = flags; - field.comment = p.line_comment; - append(&fields, field); + field := new_ast_field(names, type, nil) + field.docs = docs + field.flags = flags + field.comment = p.line_comment + append(&fields, field) } } else { - names := convert_to_ident_list(p, list[:], true, allow_poly_names); + names := convert_to_ident_list(p, list[:], true, allow_poly_names) if len(names) == 0 { - error(p, p.curr_tok.pos, "empty field declaration"); + error(p, p.curr_tok.pos, "empty field declaration") } - set_flags: ast.Field_Flags; + set_flags: ast.Field_Flags if len(list) > 0 { - set_flags = list[0].flags; + set_flags = list[0].flags } - total_name_count += len(names); - handle_field(p, &seen_ellipsis, &fields, docs, names, allowed_flags, set_flags); + total_name_count += len(names) + handle_field(p, &seen_ellipsis, &fields, docs, names, allowed_flags, set_flags) for p.curr_tok.kind != follow && p.curr_tok.kind != .EOF { - docs = p.lead_comment; - set_flags = parse_field_prefixes(p); - names = parse_ident_list(p, allow_poly_names); + docs = p.lead_comment + set_flags = parse_field_prefixes(p) + names = parse_ident_list(p, allow_poly_names) - total_name_count += len(names); - ok := handle_field(p, &seen_ellipsis, &fields, docs, names, allowed_flags, set_flags); + total_name_count += len(names) + ok := handle_field(p, &seen_ellipsis, &fields, docs, names, allowed_flags, set_flags) if !ok { - break; + break } } } - field_list = ast.new(ast.Field_List, start_tok.pos, p.curr_tok.pos); - field_list.list = fields[:]; - return; + field_list = ast.new(ast.Field_List, start_tok.pos, p.curr_tok.pos) + field_list.list = fields[:] + return } parse_results :: proc(p: ^Parser) -> (list: ^ast.Field_List, diverging: bool) { if !allow_token(p, .Arrow_Right) { - return; + return } if allow_token(p, .Not) { - diverging = true; - return; + diverging = true + return } - prev_level := p.expr_level; - defer p.expr_level = prev_level; + prev_level := p.expr_level + defer p.expr_level = prev_level if p.curr_tok.kind != .Open_Paren { - type := parse_type(p); - field := new_ast_field(nil, type, nil); + type := parse_type(p) + field := new_ast_field(nil, type, nil) - list = ast.new(ast.Field_List, field.pos, field.end); - list.list = make([]^ast.Field, 1); - list.list[0] = field; - return; + list = ast.new(ast.Field_List, field.pos, field.end) + list.list = make([]^ast.Field, 1) + list.list[0] = field + return } - expect_token(p, .Open_Paren); - list, _ = parse_field_list(p, .Close_Paren, ast.Field_Flags_Signature_Results); - expect_token_after(p, .Close_Paren, "parameter list"); - return; + expect_token(p, .Open_Paren) + list, _ = parse_field_list(p, .Close_Paren, ast.Field_Flags_Signature_Results) + expect_token_after(p, .Close_Paren, "parameter list") + return } string_to_calling_convention :: proc(s: string) -> ast.Proc_Calling_Convention { if s[0] != '"' && s[0] != '`' { - return nil; + return nil } if len(s) == 2 { - return nil; + return nil } - return s; + return s } parse_proc_tags :: proc(p: ^Parser) -> (tags: ast.Proc_Tags) { for p.curr_tok.kind == .Hash { - _ = expect_token(p, .Hash); - ident := expect_token(p, .Ident); + _ = expect_token(p, .Hash) + ident := expect_token(p, .Ident) switch ident.text { - case "bounds_check": tags += {.Bounds_Check}; - case "no_bounds_check": tags += {.No_Bounds_Check}; - case "optional_ok": tags += {.Optional_Ok}; - case "optional_second": tags += {.Optional_Second}; + case "bounds_check": tags += {.Bounds_Check} + case "no_bounds_check": tags += {.No_Bounds_Check} + case "optional_ok": tags += {.Optional_Ok} + case "optional_second": tags += {.Optional_Second} case: } } if .Bounds_Check in tags && .No_Bounds_Check in tags { - p.err(p.curr_tok.pos, "#bounds_check and #no_bounds_check applied to the same procedure type"); + p.err(p.curr_tok.pos, "#bounds_check and #no_bounds_check applied to the same procedure type") } - return; + return } parse_proc_type :: proc(p: ^Parser, tok: tokenizer.Token) -> ^ast.Proc_Type { - cc: ast.Proc_Calling_Convention; + cc: ast.Proc_Calling_Convention if p.curr_tok.kind == .String { - str := expect_token(p, .String); - cc = string_to_calling_convention(str.text); + str := expect_token(p, .String) + cc = string_to_calling_convention(str.text) if cc == nil { - error(p, str.pos, "unknown calling convention '%s'", str.text); + error(p, str.pos, "unknown calling convention '%s'", str.text) } } if cc == nil && p.in_foreign_block { - cc = .Foreign_Block_Default; + cc = .Foreign_Block_Default } - expect_token(p, .Open_Paren); - params, _ := parse_field_list(p, .Close_Paren, ast.Field_Flags_Signature_Params); - expect_token(p, .Close_Paren); - results, diverging := parse_results(p); + expect_token(p, .Open_Paren) + params, _ := parse_field_list(p, .Close_Paren, ast.Field_Flags_Signature_Params) + expect_token(p, .Close_Paren) + results, diverging := parse_results(p) - is_generic := false; + is_generic := false loop: for param in params.list { if param.type != nil { if _, ok := param.type.derived.(ast.Poly_Type); ok { - is_generic = true; - break loop; + is_generic = true + break loop } for name in param.names { if _, ok := name.derived.(ast.Poly_Type); ok { - is_generic = true; - break loop; + is_generic = true + break loop } } } } - end := end_pos(p.prev_tok); - pt := ast.new(ast.Proc_Type, tok.pos, end); - pt.tok = tok; - pt.calling_convention = cc; - pt.params = params; - pt.results = results; - pt.diverging = diverging; - pt.generic = is_generic; - return pt; + end := end_pos(p.prev_tok) + pt := ast.new(ast.Proc_Type, tok.pos, end) + pt.tok = tok + pt.calling_convention = cc + pt.params = params + pt.results = results + pt.diverging = diverging + pt.generic = is_generic + return pt } parse_inlining_operand :: proc(p: ^Parser, lhs: bool, tok: tokenizer.Token) -> ^ast.Expr { - expr := parse_unary_expr(p, lhs); + expr := parse_unary_expr(p, lhs) - pi := ast.Proc_Inlining.None; + pi := ast.Proc_Inlining.None #partial switch tok.kind { case .Inline: - pi = .Inline; + pi = .Inline case .No_Inline: - pi = .No_Inline; + pi = .No_Inline case .Ident: switch tok.text { case "force_inline": - pi = .Inline; + pi = .Inline case "force_no_inline": - pi = .No_Inline; + pi = .No_Inline } } switch e in &ast.unparen_expr(expr).derived { case ast.Proc_Lit: if e.inlining != .None && e.inlining != pi { - error(p, expr.pos, "both 'inline' and 'no_inline' cannot be applied to a procedure literal"); + error(p, expr.pos, "both 'inline' and 'no_inline' cannot be applied to a procedure literal") } - e.inlining = pi; + e.inlining = pi case ast.Call_Expr: if e.inlining != .None && e.inlining != pi { - error(p, expr.pos, "both 'inline' and 'no_inline' cannot be applied to a procedure call"); + error(p, expr.pos, "both 'inline' and 'no_inline' cannot be applied to a procedure call") } - e.inlining = pi; + e.inlining = pi case: - error(p, tok.pos, "'%s' must be followed by a procedure literal or call", tok.text); - return ast.new(ast.Bad_Expr, tok.pos, expr.end); + error(p, tok.pos, "'%s' must be followed by a procedure literal or call", tok.text) + return ast.new(ast.Bad_Expr, tok.pos, expr.end) } - return expr; + return expr } parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { #partial switch p.curr_tok.kind { case .Ident: - return parse_ident(p); + return parse_ident(p) case .Undef: - tok := expect_token(p, .Undef); - undef := ast.new(ast.Undef, tok.pos, end_pos(tok)); - undef.tok = tok.kind; - return undef; + tok := expect_token(p, .Undef) + undef := ast.new(ast.Undef, tok.pos, end_pos(tok)) + undef.tok = tok.kind + return undef case .Context: - tok := expect_token(p, .Context); - ctx := ast.new(ast.Implicit, tok.pos, end_pos(tok)); - ctx.tok = tok; - return ctx; + tok := expect_token(p, .Context) + ctx := ast.new(ast.Implicit, tok.pos, end_pos(tok)) + ctx.tok = tok + return ctx case .Integer, .Float, .Imag, .Rune, .String: - tok := advance_token(p); - bl := ast.new(ast.Basic_Lit, tok.pos, end_pos(tok)); - bl.tok = tok; - return bl; + tok := advance_token(p) + bl := ast.new(ast.Basic_Lit, tok.pos, end_pos(tok)) + bl.tok = tok + return bl case .Open_Brace: if !lhs { - return parse_literal_value(p, nil); + return parse_literal_value(p, nil) } case .Open_Paren: - open := expect_token(p, .Open_Paren); - p.expr_level += 1; - expr := parse_expr(p, false); - p.expr_level -= 1; - close := expect_token(p, .Close_Paren); - - pe := ast.new(ast.Paren_Expr, open.pos, end_pos(close)); - pe.open = open.pos; - pe.expr = expr; - pe.close = close.pos; - return pe; + open := expect_token(p, .Open_Paren) + p.expr_level += 1 + expr := parse_expr(p, false) + p.expr_level -= 1 + close := expect_token(p, .Close_Paren) + + pe := ast.new(ast.Paren_Expr, open.pos, end_pos(close)) + pe.open = open.pos + pe.expr = expr + pe.close = close.pos + return pe case .Distinct: - tok := advance_token(p); - type := parse_type(p); - dt := ast.new(ast.Distinct_Type, tok.pos, type.end); - dt.tok = tok.kind; - dt.type = type; - return dt; + tok := advance_token(p) + type := parse_type(p) + dt := ast.new(ast.Distinct_Type, tok.pos, type.end) + dt.tok = tok.kind + dt.type = type + return dt case .Hash: - tok := expect_token(p, .Hash); - name := expect_token(p, .Ident); + tok := expect_token(p, .Hash) + name := expect_token(p, .Ident) switch name.text { case "type": - type := parse_type(p); - hp := ast.new(ast.Helper_Type, tok.pos, type.end); - hp.tok = tok.kind; - hp.type = type; - return hp; + type := parse_type(p) + hp := ast.new(ast.Helper_Type, tok.pos, type.end) + hp.tok = tok.kind + hp.type = type + return hp case "file", "line", "procedure", "caller_location": - bd := ast.new(ast.Basic_Directive, tok.pos, end_pos(name)); - bd.tok = tok; - bd.name = name.text; - return bd; + bd := ast.new(ast.Basic_Directive, tok.pos, end_pos(name)) + bd.tok = tok + bd.name = name.text + return bd case "location", "load", "assert", "defined", "config": - bd := ast.new(ast.Basic_Directive, tok.pos, end_pos(name)); - bd.tok = tok; - bd.name = name.text; - return parse_call_expr(p, bd); + bd := ast.new(ast.Basic_Directive, tok.pos, end_pos(name)) + bd.tok = tok + bd.name = name.text + return parse_call_expr(p, bd) case "soa", "simd": - bd := ast.new(ast.Basic_Directive, tok.pos, end_pos(name)); - bd.tok = tok; - bd.name = name.text; - original_type := parse_type(p); - type := ast.unparen_expr(original_type); + bd := ast.new(ast.Basic_Directive, tok.pos, end_pos(name)) + bd.tok = tok + bd.name = name.text + original_type := parse_type(p) + type := ast.unparen_expr(original_type) switch t in &type.derived { - case ast.Array_Type: t.tag = bd; - case ast.Dynamic_Array_Type: t.tag = bd; + case ast.Array_Type: t.tag = bd + case ast.Dynamic_Array_Type: t.tag = bd case: - error(p, original_type.pos, "expected an array type after #%s", name.text); + error(p, original_type.pos, "expected an array type after #%s", name.text) } - return original_type; + return original_type case "partial": - tag := ast.new(ast.Basic_Directive, tok.pos, end_pos(name)); - tag.tok = tok; - tag.name = name.text; - original_type := parse_type(p); - type := ast.unparen_expr(original_type); + tag := ast.new(ast.Basic_Directive, tok.pos, end_pos(name)) + tag.tok = tok + tag.name = name.text + original_type := parse_type(p) + type := ast.unparen_expr(original_type) switch t in &type.derived { case ast.Array_Type: - t.tag = tag; + t.tag = tag case: - error(p, tok.pos, "expected an enumerated array type after #%s", name.text); + error(p, tok.pos, "expected an enumerated array type after #%s", name.text) } - return original_type; + return original_type case "bounds_check", "no_bounds_check": - operand := parse_expr(p, lhs); + operand := parse_expr(p, lhs) switch name.text { case "bounds_check": - operand.state_flags += {.Bounds_Check}; + operand.state_flags += {.Bounds_Check} if .No_Bounds_Check in operand.state_flags { - error(p, name.pos, "#bounds_check and #no_bounds_check cannot be applied together"); + error(p, name.pos, "#bounds_check and #no_bounds_check cannot be applied together") } case "no_bounds_check": - operand.state_flags += {.No_Bounds_Check}; + operand.state_flags += {.No_Bounds_Check} if .Bounds_Check in operand.state_flags { - error(p, name.pos, "#bounds_check and #no_bounds_check cannot be applied together"); + error(p, name.pos, "#bounds_check and #no_bounds_check cannot be applied together") } - case: unimplemented(); + case: unimplemented() } - return operand; + return operand case "relative": - tag := ast.new(ast.Basic_Directive, tok.pos, end_pos(name)); - tag.tok = tok; - tag.name = name.text; + tag := ast.new(ast.Basic_Directive, tok.pos, end_pos(name)) + tag.tok = tok + tag.name = name.text - tag_call := parse_call_expr(p, tag); - type := parse_type(p); + tag_call := parse_call_expr(p, tag) + type := parse_type(p) - rt := ast.new(ast.Relative_Type, tok.pos, type.end); - rt.tag = tag_call; - rt.type = type; - return rt; + rt := ast.new(ast.Relative_Type, tok.pos, type.end) + rt.tag = tag_call + rt.type = type + return rt case "force_inline", "force_no_inline": - return parse_inlining_operand(p, lhs, tok); + return parse_inlining_operand(p, lhs, tok) case: - expr := parse_expr(p, lhs); - te := ast.new(ast.Tag_Expr, tok.pos, expr.pos); - te.op = tok; - te.name = name.text; - te.expr = expr; - return te; + expr := parse_expr(p, lhs) + te := ast.new(ast.Tag_Expr, tok.pos, expr.pos) + te.op = tok + te.name = name.text + te.expr = expr + return te } case .Inline, .No_Inline: - tok := advance_token(p); - return parse_inlining_operand(p, lhs, tok); + tok := advance_token(p) + return parse_inlining_operand(p, lhs, tok) case .Proc: - tok := expect_token(p, .Proc); + tok := expect_token(p, .Proc) if p.curr_tok.kind == .Open_Brace { - open := expect_token(p, .Open_Brace); + open := expect_token(p, .Open_Brace) - args: [dynamic]^ast.Expr; + args: [dynamic]^ast.Expr for p.curr_tok.kind != .Close_Brace && p.curr_tok.kind != .EOF { - elem := parse_expr(p, false); - append(&args, elem); + elem := parse_expr(p, false) + append(&args, elem) if !allow_token(p, .Comma) { - break; + break } } - close := expect_token(p, .Close_Brace); + close := expect_token(p, .Close_Brace) if len(args) == 0 { - error(p, tok.pos, "expected at least 1 argument in procedure group"); + error(p, tok.pos, "expected at least 1 argument in procedure group") } - pg := ast.new(ast.Proc_Group, tok.pos, end_pos(close)); - pg.tok = tok; - pg.open = open.pos; - pg.args = args[:]; - pg.close = close.pos; - return pg; + pg := ast.new(ast.Proc_Group, tok.pos, end_pos(close)) + pg.tok = tok + pg.open = open.pos + pg.args = args[:] + pg.close = close.pos + return pg } - type := parse_proc_type(p, tok); - tags: ast.Proc_Tags; - where_token: tokenizer.Token; - where_clauses: []^ast.Expr; + type := parse_proc_type(p, tok) + tags: ast.Proc_Tags + where_token: tokenizer.Token + where_clauses: []^ast.Expr - skip_possible_newline_for_literal(p); + skip_possible_newline_for_literal(p) if p.curr_tok.kind == .Where { - where_token = expect_token(p, .Where); - prev_level := p.expr_level; - p.expr_level = -1; - where_clauses = parse_rhs_expr_list(p); - p.expr_level = prev_level; + where_token = expect_token(p, .Where) + prev_level := p.expr_level + p.expr_level = -1 + where_clauses = parse_rhs_expr_list(p) + p.expr_level = prev_level } - tags = parse_proc_tags(p); - type.tags = tags; + tags = parse_proc_tags(p) + type.tags = tags if p.allow_type && p.expr_level < 0 { if where_token.kind != .Invalid { - error(p, where_token.pos, "'where' clauses are not allowed on procedure types"); + error(p, where_token.pos, "'where' clauses are not allowed on procedure types") } - return type; + return type } - body: ^ast.Stmt; + body: ^ast.Stmt - skip_possible_newline_for_literal(p); + skip_possible_newline_for_literal(p) if allow_token(p, .Undef) { - body = nil; + body = nil if where_token.kind != .Invalid { - error(p, where_token.pos, "'where' clauses are not allowed on procedure literals without a defined body (replaced with ---"); + error(p, where_token.pos, "'where' clauses are not allowed on procedure literals without a defined body (replaced with ---") } } else if p.curr_tok.kind == .Open_Brace { - prev_proc := p.curr_proc; - p.curr_proc = type; - body = parse_body(p); - p.curr_proc = prev_proc; + prev_proc := p.curr_proc + p.curr_proc = type + body = parse_body(p) + p.curr_proc = prev_proc } else if allow_token(p, .Do) { - prev_proc := p.curr_proc; - p.curr_proc = type; - body = convert_stmt_to_body(p, parse_stmt(p)); - p.curr_proc = prev_proc; + prev_proc := p.curr_proc + p.curr_proc = type + body = convert_stmt_to_body(p, parse_stmt(p)) + p.curr_proc = prev_proc if type.pos.line != body.pos.line { - error(p, body.pos, "the body of a 'do' must be on the same line as the signature"); + error(p, body.pos, "the body of a 'do' must be on the same line as the signature") } } else { - return type; + return type } - pl := ast.new(ast.Proc_Lit, tok.pos, end_pos(p.prev_tok)); - pl.type = type; - pl.body = body; - pl.tags = tags; - pl.where_token = where_token; - pl.where_clauses = where_clauses; - return pl; + pl := ast.new(ast.Proc_Lit, tok.pos, end_pos(p.prev_tok)) + pl.type = type + pl.body = body + pl.tags = tags + pl.where_token = where_token + pl.where_clauses = where_clauses + return pl case .Dollar: - tok := advance_token(p); - type := parse_ident(p); - end := type.end; + tok := advance_token(p) + type := parse_ident(p) + end := type.end - specialization: ^ast.Expr; + specialization: ^ast.Expr if allow_token(p, .Quo) { - specialization = parse_type(p); - end = specialization.pos; + specialization = parse_type(p) + end = specialization.pos } if is_blank_ident(type) { - error(p, type.pos, "invalid polymorphic type definition with a blank identifier"); + error(p, type.pos, "invalid polymorphic type definition with a blank identifier") } - pt := ast.new(ast.Poly_Type, tok.pos, end); - pt.dollar = tok.pos; - pt.type = type; - pt.specialization = specialization; - return pt; + pt := ast.new(ast.Poly_Type, tok.pos, end) + pt.dollar = tok.pos + pt.type = type + pt.specialization = specialization + return pt case .Typeid: - tok := advance_token(p); - ti := ast.new(ast.Typeid_Type, tok.pos, end_pos(tok)); - ti.tok = tok.kind; - ti.specialization = nil; - return ti; + tok := advance_token(p) + ti := ast.new(ast.Typeid_Type, tok.pos, end_pos(tok)) + ti.tok = tok.kind + ti.specialization = nil + return ti case .Pointer: - tok := expect_token(p, .Pointer); - elem := parse_type(p); - ptr := ast.new(ast.Pointer_Type, tok.pos, elem.end); - ptr.pointer = tok.pos; - ptr.elem = elem; - return ptr; + tok := expect_token(p, .Pointer) + elem := parse_type(p) + ptr := ast.new(ast.Pointer_Type, tok.pos, elem.end) + ptr.pointer = tok.pos + ptr.elem = elem + return ptr case .Open_Bracket: - open := expect_token(p, .Open_Bracket); - count: ^ast.Expr; + open := expect_token(p, .Open_Bracket) + count: ^ast.Expr #partial switch p.curr_tok.kind { case .Pointer: - tok := expect_token(p, .Pointer); - close := expect_token(p, .Close_Bracket); - elem := parse_type(p); - t := ast.new(ast.Multi_Pointer_Type, open.pos, elem.end); - t.open = open.pos; - t.pointer = tok.pos; - t.close = close.pos; - t.elem = elem; - return t; + tok := expect_token(p, .Pointer) + close := expect_token(p, .Close_Bracket) + elem := parse_type(p) + t := ast.new(ast.Multi_Pointer_Type, open.pos, elem.end) + t.open = open.pos + t.pointer = tok.pos + t.close = close.pos + t.elem = elem + return t case .Dynamic: - tok := expect_token(p, .Dynamic); - close := expect_token(p, .Close_Bracket); - elem := parse_type(p); - da := ast.new(ast.Dynamic_Array_Type, open.pos, elem.end); - da.open = open.pos; - da.dynamic_pos = tok.pos; - da.close = close.pos; - da.elem = elem; - return da; + tok := expect_token(p, .Dynamic) + close := expect_token(p, .Close_Bracket) + elem := parse_type(p) + da := ast.new(ast.Dynamic_Array_Type, open.pos, elem.end) + da.open = open.pos + da.dynamic_pos = tok.pos + da.close = close.pos + da.elem = elem + return da case .Question: - tok := expect_token(p, .Question); - q := ast.new(ast.Unary_Expr, tok.pos, end_pos(tok)); - q.op = tok; - count = q; + tok := expect_token(p, .Question) + q := ast.new(ast.Unary_Expr, tok.pos, end_pos(tok)) + q.op = tok + count = q case: - p.expr_level += 1; - count = parse_expr(p, false); - p.expr_level -= 1; + p.expr_level += 1 + count = parse_expr(p, false) + p.expr_level -= 1 case .Close_Bracket: // handle below } - close := expect_token(p, .Close_Bracket); - elem := parse_type(p); - at := ast.new(ast.Array_Type, open.pos, elem.end); - at.open = open.pos; - at.len = count; - at.close = close.pos; - at.elem = elem; - return at; + close := expect_token(p, .Close_Bracket) + elem := parse_type(p) + at := ast.new(ast.Array_Type, open.pos, elem.end) + at.open = open.pos + at.len = count + at.close = close.pos + at.elem = elem + return at case .Map: - tok := expect_token(p, .Map); - expect_token(p, .Open_Bracket); - key := parse_type(p); - expect_token(p, .Close_Bracket); - value := parse_type(p); - - mt := ast.new(ast.Map_Type, tok.pos, value.end); - mt.tok_pos = tok.pos; - mt.key = key; - mt.value = value; - return mt; + tok := expect_token(p, .Map) + expect_token(p, .Open_Bracket) + key := parse_type(p) + expect_token(p, .Close_Bracket) + value := parse_type(p) + + mt := ast.new(ast.Map_Type, tok.pos, value.end) + mt.tok_pos = tok.pos + mt.key = key + mt.value = value + return mt case .Struct: - tok := expect_token(p, .Struct); + tok := expect_token(p, .Struct) - poly_params: ^ast.Field_List; - align: ^ast.Expr; - is_packed: bool; - is_raw_union: bool; - fields: ^ast.Field_List; - name_count: int; + poly_params: ^ast.Field_List + align: ^ast.Expr + is_packed: bool + is_raw_union: bool + fields: ^ast.Field_List + name_count: int if allow_token(p, .Open_Paren) { - param_count: int; - poly_params, param_count = parse_field_list(p, .Close_Paren, ast.Field_Flags_Record_Poly_Params); + param_count: int + poly_params, param_count = parse_field_list(p, .Close_Paren, ast.Field_Flags_Record_Poly_Params) if param_count == 0 { - error(p, poly_params.pos, "expected at least 1 polymorphic parameter"); - poly_params = nil; + error(p, poly_params.pos, "expected at least 1 polymorphic parameter") + poly_params = nil } - expect_token_after(p, .Close_Paren, "parameter list"); + expect_token_after(p, .Close_Paren, "parameter list") } - prev_level := p.expr_level; - p.expr_level = -1; + prev_level := p.expr_level + p.expr_level = -1 for allow_token(p, .Hash) { - tag := expect_token_after(p, .Ident, "#"); + tag := expect_token_after(p, .Ident, "#") switch tag.text { case "packed": if is_packed { - error(p, tag.pos, "duplicate struct tag '#%s'", tag.text); + error(p, tag.pos, "duplicate struct tag '#%s'", tag.text) } - is_packed = true; + is_packed = true case "align": if align != nil { - error(p, tag.pos, "duplicate struct tag '#%s'", tag.text); + error(p, tag.pos, "duplicate struct tag '#%s'", tag.text) } - align = parse_expr(p, true); + align = parse_expr(p, true) case "raw_union": if is_raw_union { - error(p, tag.pos, "duplicate struct tag '#%s'", tag.text); + error(p, tag.pos, "duplicate struct tag '#%s'", tag.text) } - is_raw_union = true; + is_raw_union = true case: - error(p, tag.pos, "invalid struct tag '#%s", tag.text); + error(p, tag.pos, "invalid struct tag '#%s", tag.text) } } - p.expr_level = prev_level; + p.expr_level = prev_level if is_raw_union && is_packed { - is_packed = false; - error(p, tok.pos, "'#raw_union' cannot also be '#packed"); + is_packed = false + error(p, tok.pos, "'#raw_union' cannot also be '#packed") } - where_token: tokenizer.Token; - where_clauses: []^ast.Expr; + where_token: tokenizer.Token + where_clauses: []^ast.Expr - skip_possible_newline_for_literal(p); + skip_possible_newline_for_literal(p) if p.curr_tok.kind == .Where { - where_token = expect_token(p, .Where); - where_prev_level := p.expr_level; - p.expr_level = -1; - where_clauses = parse_rhs_expr_list(p); - p.expr_level = where_prev_level; - } - - skip_possible_newline_for_literal(p); - expect_token(p, .Open_Brace); - fields, name_count = parse_field_list(p, .Close_Brace, ast.Field_Flags_Struct); - close := expect_closing_brace_of_field_list(p); - - st := ast.new(ast.Struct_Type, tok.pos, end_pos(close)); - st.poly_params = poly_params; - st.align = align; - st.is_packed = is_packed; - st.is_raw_union = is_raw_union; - st.fields = fields; - st.name_count = name_count; - st.where_token = where_token; - st.where_clauses = where_clauses; - return st; + where_token = expect_token(p, .Where) + where_prev_level := p.expr_level + p.expr_level = -1 + where_clauses = parse_rhs_expr_list(p) + p.expr_level = where_prev_level + } + + skip_possible_newline_for_literal(p) + expect_token(p, .Open_Brace) + fields, name_count = parse_field_list(p, .Close_Brace, ast.Field_Flags_Struct) + close := expect_closing_brace_of_field_list(p) + + st := ast.new(ast.Struct_Type, tok.pos, end_pos(close)) + st.poly_params = poly_params + st.align = align + st.is_packed = is_packed + st.is_raw_union = is_raw_union + st.fields = fields + st.name_count = name_count + st.where_token = where_token + st.where_clauses = where_clauses + return st case .Union: - tok := expect_token(p, .Union); - poly_params: ^ast.Field_List; - align: ^ast.Expr; - is_maybe: bool; + tok := expect_token(p, .Union) + poly_params: ^ast.Field_List + align: ^ast.Expr + is_maybe: bool if allow_token(p, .Open_Paren) { - param_count: int; - poly_params, param_count = parse_field_list(p, .Close_Paren, ast.Field_Flags_Record_Poly_Params); + param_count: int + poly_params, param_count = parse_field_list(p, .Close_Paren, ast.Field_Flags_Record_Poly_Params) if param_count == 0 { - error(p, poly_params.pos, "expected at least 1 polymorphic parameter"); - poly_params = nil; + error(p, poly_params.pos, "expected at least 1 polymorphic parameter") + poly_params = nil } - expect_token_after(p, .Close_Paren, "parameter list"); + expect_token_after(p, .Close_Paren, "parameter list") } - prev_level := p.expr_level; - p.expr_level = -1; + prev_level := p.expr_level + p.expr_level = -1 for allow_token(p, .Hash) { - tag := expect_token_after(p, .Ident, "#"); + tag := expect_token_after(p, .Ident, "#") switch tag.text { case "align": if align != nil { - error(p, tag.pos, "duplicate union tag '#%s'", tag.text); + error(p, tag.pos, "duplicate union tag '#%s'", tag.text) } - align = parse_expr(p, true); + align = parse_expr(p, true) case "maybe": if is_maybe { - error(p, tag.pos, "duplicate union tag '#%s'", tag.text); + error(p, tag.pos, "duplicate union tag '#%s'", tag.text) } - is_maybe = true; + is_maybe = true case: - error(p, tag.pos, "invalid union tag '#%s", tag.text); + error(p, tag.pos, "invalid union tag '#%s", tag.text) } } - p.expr_level = prev_level; + p.expr_level = prev_level - where_token: tokenizer.Token; - where_clauses: []^ast.Expr; + where_token: tokenizer.Token + where_clauses: []^ast.Expr - skip_possible_newline_for_literal(p); + skip_possible_newline_for_literal(p) if p.curr_tok.kind == .Where { - where_token = expect_token(p, .Where); - where_prev_level := p.expr_level; - p.expr_level = -1; - where_clauses = parse_rhs_expr_list(p); - p.expr_level = where_prev_level; + where_token = expect_token(p, .Where) + where_prev_level := p.expr_level + p.expr_level = -1 + where_clauses = parse_rhs_expr_list(p) + p.expr_level = where_prev_level } - skip_possible_newline_for_literal(p); - expect_token_after(p, .Open_Brace, "union"); + skip_possible_newline_for_literal(p) + expect_token_after(p, .Open_Brace, "union") - variants: [dynamic]^ast.Expr; + variants: [dynamic]^ast.Expr for p.curr_tok.kind != .Close_Brace && p.curr_tok.kind != .EOF { - type := parse_type(p); + type := parse_type(p) if _, ok := type.derived.(ast.Bad_Expr); !ok { - append(&variants, type); + append(&variants, type) } if !allow_token(p, .Comma) { - break; + break } } - close := expect_closing_brace_of_field_list(p); + close := expect_closing_brace_of_field_list(p) - ut := ast.new(ast.Union_Type, tok.pos, end_pos(close)); - ut.poly_params = poly_params; - ut.variants = variants[:]; - ut.align = align; - ut.where_token = where_token; - ut.where_clauses = where_clauses; - ut.is_maybe = is_maybe; + ut := ast.new(ast.Union_Type, tok.pos, end_pos(close)) + ut.poly_params = poly_params + ut.variants = variants[:] + ut.align = align + ut.where_token = where_token + ut.where_clauses = where_clauses + ut.is_maybe = is_maybe - return ut; + return ut case .Enum: - tok := expect_token(p, .Enum); - base_type: ^ast.Expr; + tok := expect_token(p, .Enum) + base_type: ^ast.Expr if p.curr_tok.kind != .Open_Brace { - base_type = parse_type(p); + base_type = parse_type(p) } - skip_possible_newline_for_literal(p); - open := expect_token(p, .Open_Brace); - fields := parse_elem_list(p); - close := expect_closing_brace_of_field_list(p); + skip_possible_newline_for_literal(p) + open := expect_token(p, .Open_Brace) + fields := parse_elem_list(p) + close := expect_closing_brace_of_field_list(p) - et := ast.new(ast.Enum_Type, tok.pos, end_pos(close)); - et.base_type = base_type; - et.open = open.pos; - et.fields = fields; - et.close = close.pos; - return et; + et := ast.new(ast.Enum_Type, tok.pos, end_pos(close)) + et.base_type = base_type + et.open = open.pos + et.fields = fields + et.close = close.pos + return et case .Bit_Set: - tok := expect_token(p, .Bit_Set); - open := expect_token(p, .Open_Bracket); - elem, underlying: ^ast.Expr; + tok := expect_token(p, .Bit_Set) + open := expect_token(p, .Open_Bracket) + elem, underlying: ^ast.Expr - prev_allow_range := p.allow_range; - p.allow_range = true; - elem = parse_expr(p, false); - p.allow_range = prev_allow_range; + prev_allow_range := p.allow_range + p.allow_range = true + elem = parse_expr(p, false) + p.allow_range = prev_allow_range if allow_token(p, .Semicolon) { - underlying = parse_type(p); + underlying = parse_type(p) } - close := expect_token(p, .Close_Bracket); + close := expect_token(p, .Close_Bracket) - bst := ast.new(ast.Bit_Set_Type, tok.pos, end_pos(close)); - bst.tok_pos = tok.pos; - bst.open = open.pos; - bst.elem = elem; - bst.underlying = underlying; - bst.close = close.pos; - return bst; + bst := ast.new(ast.Bit_Set_Type, tok.pos, end_pos(close)) + bst.tok_pos = tok.pos + bst.open = open.pos + bst.elem = elem + bst.underlying = underlying + bst.close = close.pos + return bst case .Asm: - tok := expect_token(p, .Asm); + tok := expect_token(p, .Asm) - param_types: [dynamic]^ast.Expr; - return_type: ^ast.Expr; + param_types: [dynamic]^ast.Expr + return_type: ^ast.Expr if allow_token(p, .Open_Paren) { for p.curr_tok.kind != .Close_Paren && p.curr_tok.kind != .EOF { - t := parse_type(p); - append(¶m_types, t); + t := parse_type(p) + append(¶m_types, t) if p.curr_tok.kind != .Comma || p.curr_tok.kind == .EOF { - break; + break } - advance_token(p); + advance_token(p) } - expect_token(p, .Close_Paren); + expect_token(p, .Close_Paren) if allow_token(p, .Arrow_Right) { - return_type = parse_type(p); + return_type = parse_type(p) } } - has_side_effects := false; - is_align_stack := false; - dialect := ast.Inline_Asm_Dialect.Default; + has_side_effects := false + is_align_stack := false + dialect := ast.Inline_Asm_Dialect.Default for allow_token(p, .Hash) { if p.curr_tok.kind == .Ident { - name := advance_token(p); + name := advance_token(p) switch name.text { case "side_effects": if has_side_effects { - error(p, tok.pos, "duplicate directive on inline asm expression: '#side_effects'"); + error(p, tok.pos, "duplicate directive on inline asm expression: '#side_effects'") } - has_side_effects = true; + has_side_effects = true case "align_stack": if is_align_stack { - error(p, tok.pos, "duplicate directive on inline asm expression: '#align_stack'"); + error(p, tok.pos, "duplicate directive on inline asm expression: '#align_stack'") } - is_align_stack = true; + is_align_stack = true case "att": if dialect == .ATT { - error(p, tok.pos, "duplicate directive on inline asm expression: '#att'"); + error(p, tok.pos, "duplicate directive on inline asm expression: '#att'") } else if dialect != .Default { - error(p, tok.pos, "conflicting asm dialects"); + error(p, tok.pos, "conflicting asm dialects") } else { - dialect = .ATT; + dialect = .ATT } case "intel": if dialect == .Intel { - error(p, tok.pos, "duplicate directive on inline asm expression: '#intel'"); + error(p, tok.pos, "duplicate directive on inline asm expression: '#intel'") } else if dialect != .Default { - error(p, tok.pos, "conflicting asm dialects"); + error(p, tok.pos, "conflicting asm dialects") } else { - dialect = .Intel; + dialect = .Intel } } } else { - error(p, p.curr_tok.pos, "expected an identifier after hash"); + error(p, p.curr_tok.pos, "expected an identifier after hash") } } - skip_possible_newline_for_literal(p); - open := expect_token(p, .Open_Brace); - asm_string := parse_expr(p, false); - expect_token(p, .Comma); - constraints_string := parse_expr(p, false); - allow_token(p, .Comma); - close := expect_closing_brace_of_field_list(p); + skip_possible_newline_for_literal(p) + open := expect_token(p, .Open_Brace) + asm_string := parse_expr(p, false) + expect_token(p, .Comma) + constraints_string := parse_expr(p, false) + allow_token(p, .Comma) + close := expect_closing_brace_of_field_list(p) - e := ast.new(ast.Inline_Asm_Expr, tok.pos, end_pos(close)); - e.tok = tok; - e.param_types = param_types[:]; - e.return_type = return_type; - e.constraints_string = constraints_string; - e.has_side_effects = has_side_effects; - e.is_align_stack = is_align_stack; - e.dialect = dialect; - e.open = open.pos; - e.asm_string = asm_string; - e.close = close.pos; + e := ast.new(ast.Inline_Asm_Expr, tok.pos, end_pos(close)) + e.tok = tok + e.param_types = param_types[:] + e.return_type = return_type + e.constraints_string = constraints_string + e.has_side_effects = has_side_effects + e.is_align_stack = is_align_stack + e.dialect = dialect + e.open = open.pos + e.asm_string = asm_string + e.close = close.pos - return e; + return e } - return nil; + return nil } is_literal_type :: proc(expr: ^ast.Expr) -> bool { - val := ast.unparen_expr(expr); + val := ast.unparen_expr(expr) if val == nil { - return false; + return false } switch _ in val.derived { case ast.Bad_Expr, @@ -2810,672 +2810,672 @@ is_literal_type :: proc(expr: ^ast.Expr) -> bool { ast.Map_Type, ast.Bit_Set_Type, ast.Call_Expr: - return true; + return true } - return false; + return false } parse_value :: proc(p: ^Parser) -> ^ast.Expr { if p.curr_tok.kind == .Open_Brace { - return parse_literal_value(p, nil); + return parse_literal_value(p, nil) } - prev_allow_range := p.allow_range; - defer p.allow_range = prev_allow_range; - p.allow_range = true; - return parse_expr(p, false); + prev_allow_range := p.allow_range + defer p.allow_range = prev_allow_range + p.allow_range = true + return parse_expr(p, false) } parse_elem_list :: proc(p: ^Parser) -> []^ast.Expr { - elems: [dynamic]^ast.Expr; + elems: [dynamic]^ast.Expr for p.curr_tok.kind != .Close_Brace && p.curr_tok.kind != .EOF { - elem := parse_value(p); + elem := parse_value(p) if p.curr_tok.kind == .Eq { - eq := expect_token(p, .Eq); - value := parse_value(p); + eq := expect_token(p, .Eq) + value := parse_value(p) - fv := ast.new(ast.Field_Value, elem.pos, value.end); - fv.field = elem; - fv.sep = eq.pos; - fv.value = value; + fv := ast.new(ast.Field_Value, elem.pos, value.end) + fv.field = elem + fv.sep = eq.pos + fv.value = value - elem = fv; + elem = fv } - append(&elems, elem); + append(&elems, elem) if !allow_token(p, .Comma) { - break; + break } } - return elems[:]; + return elems[:] } parse_literal_value :: proc(p: ^Parser, type: ^ast.Expr) -> ^ast.Comp_Lit { - elems: []^ast.Expr; - open := expect_token(p, .Open_Brace); - p.expr_level += 1; + elems: []^ast.Expr + open := expect_token(p, .Open_Brace) + p.expr_level += 1 if p.curr_tok.kind != .Close_Brace { - elems = parse_elem_list(p); + elems = parse_elem_list(p) } - p.expr_level -= 1; + p.expr_level -= 1 - close := expect_token_after(p, .Close_Brace, "compound literal"); + close := expect_token_after(p, .Close_Brace, "compound literal") - pos := type.pos if type != nil else open.pos; - lit := ast.new(ast.Comp_Lit, pos, end_pos(close)); - lit.type = type; - lit.open = open.pos; - lit.elems = elems; - lit.close = close.pos; - return lit; + pos := type.pos if type != nil else open.pos + lit := ast.new(ast.Comp_Lit, pos, end_pos(close)) + lit.type = type + lit.open = open.pos + lit.elems = elems + lit.close = close.pos + return lit } parse_call_expr :: proc(p: ^Parser, operand: ^ast.Expr) -> ^ast.Expr { - args: [dynamic]^ast.Expr; + args: [dynamic]^ast.Expr - ellipsis: tokenizer.Token; + ellipsis: tokenizer.Token - p.expr_level += 1; - open := expect_token(p, .Open_Paren); + p.expr_level += 1 + open := expect_token(p, .Open_Paren) for p.curr_tok.kind != .Close_Paren && p.curr_tok.kind != .EOF && ellipsis.pos.line == 0 { if p.curr_tok.kind == .Comma { - error(p, p.curr_tok.pos, "expected an expression not ,"); + error(p, p.curr_tok.pos, "expected an expression not ,") } else if p.curr_tok.kind == .Eq { - error(p, p.curr_tok.pos, "expected an expression not ="); + error(p, p.curr_tok.pos, "expected an expression not =") } - prefix_ellipsis := false; + prefix_ellipsis := false if p.curr_tok.kind == .Ellipsis { - prefix_ellipsis = true; - ellipsis = expect_token(p, .Ellipsis); + prefix_ellipsis = true + ellipsis = expect_token(p, .Ellipsis) } - arg := parse_expr(p, false); + arg := parse_expr(p, false) if p.curr_tok.kind == .Eq { - eq := expect_token(p, .Eq); + eq := expect_token(p, .Eq) if prefix_ellipsis { - error(p, ellipsis.pos, "'..' must be applied to value rather than a field name"); + error(p, ellipsis.pos, "'..' must be applied to value rather than a field name") } - value := parse_value(p); - fv := ast.new(ast.Field_Value, arg.pos, value.end); - fv.field = arg; - fv.sep = eq.pos; - fv.value = value; + value := parse_value(p) + fv := ast.new(ast.Field_Value, arg.pos, value.end) + fv.field = arg + fv.sep = eq.pos + fv.value = value - arg = fv; + arg = fv } - append(&args, arg); + append(&args, arg) if !allow_token(p, .Comma) { - break; + break } } - close := expect_token_after(p, .Close_Paren, "argument list"); - p.expr_level -= 1; + close := expect_token_after(p, .Close_Paren, "argument list") + p.expr_level -= 1 - ce := ast.new(ast.Call_Expr, operand.pos, end_pos(close)); - ce.expr = operand; - ce.open = open.pos; - ce.args = args[:]; - ce.ellipsis = ellipsis; - ce.close = close.pos; + ce := ast.new(ast.Call_Expr, operand.pos, end_pos(close)) + ce.expr = operand + ce.open = open.pos + ce.args = args[:] + ce.ellipsis = ellipsis + ce.close = close.pos - o := ast.unparen_expr(operand); + o := ast.unparen_expr(operand) if se, ok := o.derived.(ast.Selector_Expr); ok && se.op.kind == .Arrow_Right { - sce := ast.new(ast.Selector_Call_Expr, ce.pos, ce.end); - sce.expr = o; - sce.call = ce; - return sce; + sce := ast.new(ast.Selector_Call_Expr, ce.pos, ce.end) + sce.expr = o + sce.call = ce + return sce } - return ce; + return ce } parse_atom_expr :: proc(p: ^Parser, value: ^ast.Expr, lhs: bool) -> (operand: ^ast.Expr) { - operand = value; + operand = value if operand == nil { if p.allow_type { - return nil; + return nil } - error(p, p.curr_tok.pos, "expected an operand"); - fix_advance_to_next_stmt(p); - be := ast.new(ast.Bad_Expr, p.curr_tok.pos, end_pos(p.curr_tok)); - operand = be; + error(p, p.curr_tok.pos, "expected an operand") + fix_advance_to_next_stmt(p) + be := ast.new(ast.Bad_Expr, p.curr_tok.pos, end_pos(p.curr_tok)) + operand = be } - loop := true; - is_lhs := lhs; + loop := true + is_lhs := lhs for loop { #partial switch p.curr_tok.kind { case: - loop = false; + loop = false case .Open_Paren: - operand = parse_call_expr(p, operand); + operand = parse_call_expr(p, operand) case .Open_Bracket: - prev_allow_range := p.allow_range; - defer p.allow_range = prev_allow_range; - p.allow_range = false; + prev_allow_range := p.allow_range + defer p.allow_range = prev_allow_range + p.allow_range = false - indicies: [2]^ast.Expr; - interval: tokenizer.Token; - is_slice_op := false; + indicies: [2]^ast.Expr + interval: tokenizer.Token + is_slice_op := false - p.expr_level += 1; - open := expect_token(p, .Open_Bracket); + p.expr_level += 1 + open := expect_token(p, .Open_Bracket) #partial switch p.curr_tok.kind { case .Colon, .Ellipsis, .Range_Half, .Range_Full: // NOTE(bill): Do not err yet - break; + break case: - indicies[0] = parse_expr(p, false); + indicies[0] = parse_expr(p, false) } #partial switch p.curr_tok.kind { case .Ellipsis, .Range_Half, .Range_Full: - error(p, p.curr_tok.pos, "expected a colon, not a range"); - fallthrough; + error(p, p.curr_tok.pos, "expected a colon, not a range") + fallthrough case .Colon: - interval = advance_token(p); - is_slice_op = true; + interval = advance_token(p) + is_slice_op = true if p.curr_tok.kind != .Close_Bracket && p.curr_tok.kind != .EOF { - indicies[1] = parse_expr(p, false); + indicies[1] = parse_expr(p, false) } } - close := expect_token(p, .Close_Bracket); - p.expr_level -= 1; + close := expect_token(p, .Close_Bracket) + p.expr_level -= 1 if is_slice_op { - se := ast.new(ast.Slice_Expr, operand.pos, end_pos(close)); - se.expr = operand; - se.open = open.pos; - se.low = indicies[0]; - se.interval = interval; - se.high = indicies[1]; - se.close = close.pos; - - operand = se; + se := ast.new(ast.Slice_Expr, operand.pos, end_pos(close)) + se.expr = operand + se.open = open.pos + se.low = indicies[0] + se.interval = interval + se.high = indicies[1] + se.close = close.pos + + operand = se } else { - ie := ast.new(ast.Index_Expr, operand.pos, end_pos(close)); - ie.expr = operand; - ie.open = open.pos; - ie.index = indicies[0]; - ie.close = close.pos; + ie := ast.new(ast.Index_Expr, operand.pos, end_pos(close)) + ie.expr = operand + ie.open = open.pos + ie.index = indicies[0] + ie.close = close.pos - operand = ie; + operand = ie } case .Period: - tok := expect_token(p, .Period); + tok := expect_token(p, .Period) #partial switch p.curr_tok.kind { case .Ident: - field := parse_ident(p); + field := parse_ident(p) - sel := ast.new(ast.Selector_Expr, operand.pos, field.end); - sel.expr = operand; - sel.op = tok; - sel.field = field; + sel := ast.new(ast.Selector_Expr, operand.pos, field.end) + sel.expr = operand + sel.op = tok + sel.field = field - operand = sel; + operand = sel case .Open_Paren: - open := expect_token(p, .Open_Paren); - type := parse_type(p); - close := expect_token(p, .Close_Paren); + open := expect_token(p, .Open_Paren) + type := parse_type(p) + close := expect_token(p, .Close_Paren) - ta := ast.new(ast.Type_Assertion, operand.pos, end_pos(close)); - ta.expr = operand; - ta.open = open.pos; - ta.type = type; - ta.close = close.pos; + ta := ast.new(ast.Type_Assertion, operand.pos, end_pos(close)) + ta.expr = operand + ta.open = open.pos + ta.type = type + ta.close = close.pos - operand = ta; + operand = ta case .Question: - question := expect_token(p, .Question); - type := ast.new(ast.Unary_Expr, question.pos, end_pos(question)); - type.op = question; - type.expr = nil; + question := expect_token(p, .Question) + type := ast.new(ast.Unary_Expr, question.pos, end_pos(question)) + type.op = question + type.expr = nil - ta := ast.new(ast.Type_Assertion, operand.pos, type.end); - ta.expr = operand; - ta.type = type; + ta := ast.new(ast.Type_Assertion, operand.pos, type.end) + ta.expr = operand + ta.type = type - operand = ta; + operand = ta case: - error(p, p.curr_tok.pos, "expected a selector"); - advance_token(p); - operand = ast.new(ast.Bad_Expr, operand.pos, end_pos(tok)); + error(p, p.curr_tok.pos, "expected a selector") + advance_token(p) + operand = ast.new(ast.Bad_Expr, operand.pos, end_pos(tok)) } case .Arrow_Right: - tok := expect_token(p, .Arrow_Right); + tok := expect_token(p, .Arrow_Right) #partial switch p.curr_tok.kind { case .Ident: - field := parse_ident(p); + field := parse_ident(p) - sel := ast.new(ast.Selector_Expr, operand.pos, field.end); - sel.expr = operand; - sel.op = tok; - sel.field = field; + sel := ast.new(ast.Selector_Expr, operand.pos, field.end) + sel.expr = operand + sel.op = tok + sel.field = field - operand = sel; + operand = sel case: - error(p, p.curr_tok.pos, "expected a selector"); - advance_token(p); - operand = ast.new(ast.Bad_Expr, operand.pos, end_pos(tok)); + error(p, p.curr_tok.pos, "expected a selector") + advance_token(p) + operand = ast.new(ast.Bad_Expr, operand.pos, end_pos(tok)) } case .Pointer: - op := expect_token(p, .Pointer); - deref := ast.new(ast.Deref_Expr, operand.pos, end_pos(op)); - deref.expr = operand; - deref.op = op; + op := expect_token(p, .Pointer) + deref := ast.new(ast.Deref_Expr, operand.pos, end_pos(op)) + deref.expr = operand + deref.op = op - operand = deref; + operand = deref case .Or_Return: - token := expect_token(p, .Or_Return); - oe := ast.new(ast.Or_Return_Expr, operand.pos, end_pos(token)); - oe.expr = operand; - oe.token = token; + token := expect_token(p, .Or_Return) + oe := ast.new(ast.Or_Return_Expr, operand.pos, end_pos(token)) + oe.expr = operand + oe.token = token - operand = oe; + operand = oe case .Open_Brace: if !is_lhs && is_literal_type(operand) && p.expr_level >= 0 { - operand = parse_literal_value(p, operand); + operand = parse_literal_value(p, operand) } else { - loop = false; + loop = false } case .Increment, .Decrement: if !lhs { - tok := advance_token(p); - error(p, tok.pos, "postfix '%s' operator is not supported", tok.text); + tok := advance_token(p) + error(p, tok.pos, "postfix '%s' operator is not supported", tok.text) } else { - loop = false; + loop = false } } - is_lhs = false; + is_lhs = false } - return operand; + return operand } parse_expr :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { - return parse_binary_expr(p, lhs, 0+1); + return parse_binary_expr(p, lhs, 0+1) } parse_unary_expr :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { #partial switch p.curr_tok.kind { case .Transmute, .Cast: - tok := advance_token(p); - open := expect_token(p, .Open_Paren); - type := parse_type(p); - close := expect_token(p, .Close_Paren); - expr := parse_unary_expr(p, lhs); - - tc := ast.new(ast.Type_Cast, tok.pos, expr.end); - tc.tok = tok; - tc.open = open.pos; - tc.type = type; - tc.close = close.pos; - tc.expr = expr; - return tc; + tok := advance_token(p) + open := expect_token(p, .Open_Paren) + type := parse_type(p) + close := expect_token(p, .Close_Paren) + expr := parse_unary_expr(p, lhs) + + tc := ast.new(ast.Type_Cast, tok.pos, expr.end) + tc.tok = tok + tc.open = open.pos + tc.type = type + tc.close = close.pos + tc.expr = expr + return tc case .Auto_Cast: - op := advance_token(p); - expr := parse_unary_expr(p, lhs); + op := advance_token(p) + expr := parse_unary_expr(p, lhs) - ac := ast.new(ast.Auto_Cast, op.pos, expr.end); - ac.op = op; - ac.expr = expr; - return ac; + ac := ast.new(ast.Auto_Cast, op.pos, expr.end) + ac.op = op + ac.expr = expr + return ac case .Add, .Sub, .Not, .Xor, .And: - op := advance_token(p); - expr := parse_unary_expr(p, lhs); + op := advance_token(p) + expr := parse_unary_expr(p, lhs) - ue := ast.new(ast.Unary_Expr, op.pos, expr.end); - ue.op = op; - ue.expr = expr; - return ue; + ue := ast.new(ast.Unary_Expr, op.pos, expr.end) + ue.op = op + ue.expr = expr + return ue case .Increment, .Decrement: - op := advance_token(p); - error(p, op.pos, "unary '%s' operator is not supported", op.text); - expr := parse_unary_expr(p, lhs); + op := advance_token(p) + error(p, op.pos, "unary '%s' operator is not supported", op.text) + expr := parse_unary_expr(p, lhs) - ue := ast.new(ast.Unary_Expr, op.pos, expr.end); - ue.op = op; - ue.expr = expr; - return ue; + ue := ast.new(ast.Unary_Expr, op.pos, expr.end) + ue.op = op + ue.expr = expr + return ue case .Period: - op := advance_token(p); - field := parse_ident(p); - ise := ast.new(ast.Implicit_Selector_Expr, op.pos, field.end); - ise.field = field; - return ise; + op := advance_token(p) + field := parse_ident(p) + ise := ast.new(ast.Implicit_Selector_Expr, op.pos, field.end) + ise.field = field + return ise } - return parse_atom_expr(p, parse_operand(p, lhs), lhs); + return parse_atom_expr(p, parse_operand(p, lhs), lhs) } parse_binary_expr :: proc(p: ^Parser, lhs: bool, prec_in: int) -> ^ast.Expr { - start_pos := p.curr_tok.pos; - expr := parse_unary_expr(p, lhs); + start_pos := p.curr_tok.pos + expr := parse_unary_expr(p, lhs) if expr == nil { - return ast.new(ast.Bad_Expr, start_pos, end_pos(p.prev_tok)); + return ast.new(ast.Bad_Expr, start_pos, end_pos(p.prev_tok)) } for prec := token_precedence(p, p.curr_tok.kind); prec >= prec_in; prec -= 1 { loop: for { - op := p.curr_tok; - op_prec := token_precedence(p, op.kind); + op := p.curr_tok + op_prec := token_precedence(p, op.kind) if op_prec != prec { - break loop; + break loop } #partial switch op.kind { case .If, .When: if p.prev_tok.pos.line < op.pos.line { // NOTE(bill): Check to see if the `if` or `when` is on the same line of the `lhs` condition - break loop; + break loop } } - expect_operator(p); + expect_operator(p) #partial switch op.kind { case .Question: - cond := expr; - x := parse_expr(p, lhs); - colon := expect_token(p, .Colon); - y := parse_expr(p, lhs); - te := ast.new(ast.Ternary_If_Expr, expr.pos, end_pos(p.prev_tok)); - te.cond = cond; - te.op1 = op; - te.x = x; - te.op2 = colon; - te.y = y; - - expr = te; + cond := expr + x := parse_expr(p, lhs) + colon := expect_token(p, .Colon) + y := parse_expr(p, lhs) + te := ast.new(ast.Ternary_If_Expr, expr.pos, end_pos(p.prev_tok)) + te.cond = cond + te.op1 = op + te.x = x + te.op2 = colon + te.y = y + + expr = te case .If: - x := expr; - cond := parse_expr(p, lhs); - else_tok := expect_token(p, .Else); - y := parse_expr(p, lhs); - te := ast.new(ast.Ternary_If_Expr, expr.pos, end_pos(p.prev_tok)); - te.x = x; - te.op1 = op; - te.cond = cond; - te.op2 = else_tok; - te.y = y; - - expr = te; + x := expr + cond := parse_expr(p, lhs) + else_tok := expect_token(p, .Else) + y := parse_expr(p, lhs) + te := ast.new(ast.Ternary_If_Expr, expr.pos, end_pos(p.prev_tok)) + te.x = x + te.op1 = op + te.cond = cond + te.op2 = else_tok + te.y = y + + expr = te case .When: - x := expr; - cond := parse_expr(p, lhs); - else_tok := expect_token(p, .Else); - y := parse_expr(p, lhs); - te := ast.new(ast.Ternary_When_Expr, expr.pos, end_pos(p.prev_tok)); - te.x = x; - te.op1 = op; - te.cond = cond; - te.op2 = else_tok; - te.y = y; - - expr = te; + x := expr + cond := parse_expr(p, lhs) + else_tok := expect_token(p, .Else) + y := parse_expr(p, lhs) + te := ast.new(ast.Ternary_When_Expr, expr.pos, end_pos(p.prev_tok)) + te.x = x + te.op1 = op + te.cond = cond + te.op2 = else_tok + te.y = y + + expr = te case .Or_Else: - x := expr; - y := parse_expr(p, lhs); - oe := ast.new(ast.Or_Else_Expr, expr.pos, end_pos(p.prev_tok)); - oe.x = x; - oe.token = op; - oe.y = y; + x := expr + y := parse_expr(p, lhs) + oe := ast.new(ast.Or_Else_Expr, expr.pos, end_pos(p.prev_tok)) + oe.x = x + oe.token = op + oe.y = y - expr = oe; + expr = oe case: - right := parse_binary_expr(p, false, prec+1); + right := parse_binary_expr(p, false, prec+1) if right == nil { - error(p, op.pos, "expected expression on the right-hand side of the binary operator"); + error(p, op.pos, "expected expression on the right-hand side of the binary operator") } - be := ast.new(ast.Binary_Expr, expr.pos, end_pos(p.prev_tok)); - be.left = expr; - be.op = op; - be.right = right; + be := ast.new(ast.Binary_Expr, expr.pos, end_pos(p.prev_tok)) + be.left = expr + be.op = op + be.right = right - expr = be; + expr = be } } } - return expr; + return expr } parse_expr_list :: proc(p: ^Parser, lhs: bool) -> ([]^ast.Expr) { - list: [dynamic]^ast.Expr; + list: [dynamic]^ast.Expr for { - expr := parse_expr(p, lhs); - append(&list, expr); + expr := parse_expr(p, lhs) + append(&list, expr) if p.curr_tok.kind != .Comma || p.curr_tok.kind == .EOF { - break; + break } - advance_token(p); + advance_token(p) } - return list[:]; + return list[:] } parse_lhs_expr_list :: proc(p: ^Parser) -> []^ast.Expr { - return parse_expr_list(p, true); + return parse_expr_list(p, true) } parse_rhs_expr_list :: proc(p: ^Parser) -> []^ast.Expr { - return parse_expr_list(p, false); + return parse_expr_list(p, false) } parse_simple_stmt :: proc(p: ^Parser, flags: Stmt_Allow_Flags) -> ^ast.Stmt { - start_tok := p.curr_tok; - docs := p.lead_comment; + start_tok := p.curr_tok + docs := p.lead_comment - lhs := parse_lhs_expr_list(p); - op := p.curr_tok; + lhs := parse_lhs_expr_list(p) + op := p.curr_tok switch { case tokenizer.is_assignment_operator(op.kind): // if p.curr_proc == nil { // error(p, p.curr_tok.pos, "simple statements are not allowed at the file scope"); // return ast.new(ast.Bad_Stmt, start_tok.pos, end_pos(p.curr_tok)); // } - advance_token(p); - rhs := parse_rhs_expr_list(p); + advance_token(p) + rhs := parse_rhs_expr_list(p) if len(rhs) == 0 { - error(p, p.curr_tok.pos, "no right-hand side in assignment statement"); - return ast.new(ast.Bad_Stmt, start_tok.pos, end_pos(p.curr_tok)); + error(p, p.curr_tok.pos, "no right-hand side in assignment statement") + return ast.new(ast.Bad_Stmt, start_tok.pos, end_pos(p.curr_tok)) } - stmt := ast.new(ast.Assign_Stmt, lhs[0].pos, rhs[len(rhs)-1].end); - stmt.lhs = lhs; - stmt.op = op; - stmt.rhs = rhs; - return stmt; + stmt := ast.new(ast.Assign_Stmt, lhs[0].pos, rhs[len(rhs)-1].end) + stmt.lhs = lhs + stmt.op = op + stmt.rhs = rhs + return stmt case op.kind == .In: if .In in flags { - allow_token(p, .In); - prev_allow_range := p.allow_range; - p.allow_range = true; - expr := parse_expr(p, false); - p.allow_range = prev_allow_range; + allow_token(p, .In) + prev_allow_range := p.allow_range + p.allow_range = true + expr := parse_expr(p, false) + p.allow_range = prev_allow_range - rhs := make([]^ast.Expr, 1); - rhs[0] = expr; + rhs := make([]^ast.Expr, 1) + rhs[0] = expr - stmt := ast.new(ast.Assign_Stmt, lhs[0].pos, rhs[len(rhs)-1].end); - stmt.lhs = lhs; - stmt.op = op; - stmt.rhs = rhs; - return stmt; + stmt := ast.new(ast.Assign_Stmt, lhs[0].pos, rhs[len(rhs)-1].end) + stmt.lhs = lhs + stmt.op = op + stmt.rhs = rhs + return stmt } case op.kind == .Colon: - expect_token_after(p, .Colon, "identifier list"); + expect_token_after(p, .Colon, "identifier list") if .Label in flags && len(lhs) == 1 { #partial switch p.curr_tok.kind { case .Open_Brace, .If, .For, .Switch: - label := lhs[0]; - stmt := parse_stmt(p); + label := lhs[0] + stmt := parse_stmt(p) if stmt != nil { switch n in &stmt.derived { - case ast.Block_Stmt: n.label = label; - case ast.If_Stmt: n.label = label; - case ast.For_Stmt: n.label = label; - case ast.Switch_Stmt: n.label = label; - case ast.Type_Switch_Stmt: n.label = label; - case ast.Range_Stmt: n.label = label; + case ast.Block_Stmt: n.label = label + case ast.If_Stmt: n.label = label + case ast.For_Stmt: n.label = label + case ast.Switch_Stmt: n.label = label + case ast.Type_Switch_Stmt: n.label = label + case ast.Range_Stmt: n.label = label } } - return stmt; + return stmt } } - return parse_value_decl(p, lhs, docs); + return parse_value_decl(p, lhs, docs) } if len(lhs) > 1 { - error(p, op.pos, "expected 1 expression, got %d", len(lhs)); - return ast.new(ast.Bad_Stmt, start_tok.pos, end_pos(p.curr_tok)); + error(p, op.pos, "expected 1 expression, got %d", len(lhs)) + return ast.new(ast.Bad_Stmt, start_tok.pos, end_pos(p.curr_tok)) } #partial switch op.kind { case .Increment, .Decrement: - advance_token(p); - error(p, op.pos, "postfix '%s' statement is not supported", op.text); + advance_token(p) + error(p, op.pos, "postfix '%s' statement is not supported", op.text) } - es := ast.new(ast.Expr_Stmt, lhs[0].pos, lhs[0].end); - es.expr = lhs[0]; - return es; + es := ast.new(ast.Expr_Stmt, lhs[0].pos, lhs[0].end) + es.expr = lhs[0] + return es } parse_value_decl :: proc(p: ^Parser, names: []^ast.Expr, docs: ^ast.Comment_Group) -> ^ast.Decl { - is_mutable := true; + is_mutable := true - values: []^ast.Expr; - type := parse_type_or_ident(p); + values: []^ast.Expr + type := parse_type_or_ident(p) #partial switch p.curr_tok.kind { case .Eq, .Colon: - sep := advance_token(p); - is_mutable = sep.kind != .Colon; + sep := advance_token(p) + is_mutable = sep.kind != .Colon - values = parse_rhs_expr_list(p); + values = parse_rhs_expr_list(p) if len(values) > len(names) { - error(p, p.curr_tok.pos, "too many values on the right-hand side of the declaration"); + error(p, p.curr_tok.pos, "too many values on the right-hand side of the declaration") } else if len(values) < len(names) && !is_mutable { - error(p, p.curr_tok.pos, "all constant declarations must be defined"); + error(p, p.curr_tok.pos, "all constant declarations must be defined") } else if len(values) == 0 { - error(p, p.curr_tok.pos, "expected an expression for this declaration"); + error(p, p.curr_tok.pos, "expected an expression for this declaration") } } if is_mutable { if type == nil && len(values) == 0 { - error(p, p.curr_tok.pos, "missing variable type or initialization"); - return ast.new(ast.Bad_Decl, names[0].pos, end_pos(p.curr_tok)); + error(p, p.curr_tok.pos, "missing variable type or initialization") + return ast.new(ast.Bad_Decl, names[0].pos, end_pos(p.curr_tok)) } } else { if type == nil && len(values) == 0 && len(names) > 0 { - error(p, p.curr_tok.pos, "missing constant value"); - return ast.new(ast.Bad_Decl, names[0].pos, end_pos(p.curr_tok)); + error(p, p.curr_tok.pos, "missing constant value") + return ast.new(ast.Bad_Decl, names[0].pos, end_pos(p.curr_tok)) } } if p.expr_level >= 0 { - end: ^ast.Expr; + end: ^ast.Expr if !is_mutable && len(values) > 0 { - end = values[len(values)-1]; + end = values[len(values)-1] } if p.curr_tok.kind == .Close_Brace && p.curr_tok.pos.line == p.prev_tok.pos.line { } else { - expect_semicolon(p, end); + expect_semicolon(p, end) } } if p.curr_proc == nil { if len(values) > 0 && len(names) != len(values) { - error(p, values[0].pos, "expected %d expressions on the right-hand side, got %d", len(names), len(values)); + error(p, values[0].pos, "expected %d expressions on the right-hand side, got %d", len(names), len(values)) } } - decl := ast.new(ast.Value_Decl, names[0].pos, end_pos(p.prev_tok)); - decl.docs = docs; - decl.names = names; - decl.type = type; - decl.values = values; - decl.is_mutable = is_mutable; - return decl; + decl := ast.new(ast.Value_Decl, names[0].pos, end_pos(p.prev_tok)) + decl.docs = docs + decl.names = names + decl.type = type + decl.values = values + decl.is_mutable = is_mutable + return decl } parse_import_decl :: proc(p: ^Parser, kind := Import_Decl_Kind.Standard) -> ^ast.Import_Decl { - docs := p.lead_comment; - tok := expect_token(p, .Import); + docs := p.lead_comment + tok := expect_token(p, .Import) - import_name: tokenizer.Token; - is_using := kind != Import_Decl_Kind.Standard; + import_name: tokenizer.Token + is_using := kind != Import_Decl_Kind.Standard #partial switch p.curr_tok.kind { case .Ident: - import_name = advance_token(p); + import_name = advance_token(p) case: - import_name.pos = p.curr_tok.pos; + import_name.pos = p.curr_tok.pos } if !is_using && is_blank_ident(import_name) { - error(p, import_name.pos, "illegal import name: '_'"); + error(p, import_name.pos, "illegal import name: '_'") } - path := expect_token_after(p, .String, "import"); + path := expect_token_after(p, .String, "import") - decl := ast.new(ast.Import_Decl, tok.pos, end_pos(path)); - decl.docs = docs; - decl.is_using = is_using; - decl.import_tok = tok; - decl.name = import_name; - decl.relpath = path; - decl.fullpath = path.text; + decl := ast.new(ast.Import_Decl, tok.pos, end_pos(path)) + decl.docs = docs + decl.is_using = is_using + decl.import_tok = tok + decl.name = import_name + decl.relpath = path + decl.fullpath = path.text if p.curr_proc != nil { - error(p, decl.pos, "import declarations cannot be used within a procedure, it must be done at the file scope"); + error(p, decl.pos, "import declarations cannot be used within a procedure, it must be done at the file scope") } else { - append(&p.file.imports, decl); + append(&p.file.imports, decl) } - expect_semicolon(p, decl); - decl.comment = p.line_comment; + expect_semicolon(p, decl) + decl.comment = p.line_comment - return decl; + return decl } diff --git a/core/odin/printer/printer.odin b/core/odin/printer/printer.odin index f99bd2b56..c0c1ef2d5 100644 --- a/core/odin/printer/printer.odin +++ b/core/odin/printer/printer.odin @@ -8,9 +8,9 @@ import "core:fmt" import "core:unicode/utf8"
import "core:mem"
-Type_Enum :: enum {Line_Comment, Value_Decl, Switch_Stmt, Struct, Assign, Call, Enum, If, For, Proc_Lit};
+Type_Enum :: enum {Line_Comment, Value_Decl, Switch_Stmt, Struct, Assign, Call, Enum, If, For, Proc_Lit}
-Line_Type :: bit_set[Type_Enum];
+Line_Type :: bit_set[Type_Enum]
/*
Represents an unwrapped line
@@ -115,147 +115,147 @@ default_style := Config { align_enums = true,
newline_style = .CRLF,
align_length_break = 9,
-};
+}
make_printer :: proc(config: Config, allocator := context.allocator) -> Printer {
return {
config = config,
allocator = allocator,
debug = false,
- };
+ }
}
print :: proc(p: ^Printer, file: ^ast.File) -> string {
- p.comments = file.comments;
+ p.comments = file.comments
if len(file.decls) > 0 {
- p.lines = make([dynamic]Line, 0, (file.decls[len(file.decls) - 1].end.line - file.decls[0].pos.line) * 2, context.temp_allocator);
+ p.lines = make([dynamic]Line, 0, (file.decls[len(file.decls) - 1].end.line - file.decls[0].pos.line) * 2, context.temp_allocator)
}
- set_source_position(p, file.pkg_token.pos);
+ set_source_position(p, file.pkg_token.pos)
- p.last_source_position.line = 1;
+ p.last_source_position.line = 1
- set_line(p, 0);
+ set_line(p, 0)
- push_generic_token(p, .Package, 0);
- push_ident_token(p, file.pkg_name, 1);
+ push_generic_token(p, .Package, 0)
+ push_ident_token(p, file.pkg_name, 1)
for decl in file.decls {
- visit_decl(p, cast(^ast.Decl)decl);
+ visit_decl(p, cast(^ast.Decl)decl)
}
if len(p.comments) > 0 {
- infinite := p.comments[len(p.comments) - 1].end;
- infinite.offset = 9999999;
- push_comments(p, infinite);
+ infinite := p.comments[len(p.comments) - 1].end
+ infinite.offset = 9999999
+ push_comments(p, infinite)
}
- fix_lines(p);
+ fix_lines(p)
- builder := strings.make_builder(0, mem.megabytes(5), p.allocator);
+ builder := strings.make_builder(0, mem.megabytes(5), p.allocator)
- last_line := 0;
+ last_line := 0
- newline: string;
+ newline: string
if p.config.newline_style == .LF {
- newline = "\n";
+ newline = "\n"
} else {
- newline = "\r\n";
+ newline = "\r\n"
}
for line, line_index in p.lines {
- diff_line := line_index - last_line;
+ diff_line := line_index - last_line
for i := 0; i < diff_line; i += 1 {
- strings.write_string(&builder, newline);
+ strings.write_string(&builder, newline)
}
if p.config.tabs {
for i := 0; i < line.depth; i += 1 {
- strings.write_byte(&builder, '\t');
+ strings.write_byte(&builder, '\t')
}
} else {
for i := 0; i < line.depth * p.config.spaces; i += 1 {
- strings.write_byte(&builder, ' ');
+ strings.write_byte(&builder, ' ')
}
}
if p.debug {
- strings.write_string(&builder, fmt.tprintf("line %v: ", line_index));
+ strings.write_string(&builder, fmt.tprintf("line %v: ", line_index))
}
for format_token in line.format_tokens {
for i := 0; i < format_token.spaces_before; i += 1 {
- strings.write_byte(&builder, ' ');
+ strings.write_byte(&builder, ' ')
}
- strings.write_string(&builder, format_token.text);
+ strings.write_string(&builder, format_token.text)
}
- last_line = line_index;
+ last_line = line_index
}
- strings.write_string(&builder, newline);
+ strings.write_string(&builder, newline)
- return strings.to_string(builder);
+ return strings.to_string(builder)
}
fix_lines :: proc(p: ^Printer) {
- align_var_decls(p);
- format_generic(p);
- align_comments(p); //align them last since they rely on the other alignments
+ align_var_decls(p)
+ format_generic(p)
+ align_comments(p) //align them last since they rely on the other alignments
}
format_value_decl :: proc(p: ^Printer, index: int) {
- eq_found := false;
- eq_token: Format_Token;
- eq_line: int;
- largest := 0;
+ eq_found := false
+ eq_token: Format_Token
+ eq_line: int
+ largest := 0
found_eq: for line, line_index in p.lines[index:] {
for format_token in line.format_tokens {
- largest += len(format_token.text) + format_token.spaces_before;
+ largest += len(format_token.text) + format_token.spaces_before
if format_token.kind == .Eq {
- eq_token = format_token;
- eq_line = line_index + index;
- eq_found = true;
- break found_eq;
+ eq_token = format_token
+ eq_line = line_index + index
+ eq_found = true
+ break found_eq
}
}
}
if !eq_found {
- return;
+ return
}
- align_next := false;
+ align_next := false
//check to see if there is a binary operator in the last token(this is guaranteed by the ast visit), otherwise it's not multilined
for line, line_index in p.lines[eq_line:] {
if len(line.format_tokens) == 0 {
- break;
+ break
}
if align_next {
- line.format_tokens[0].spaces_before = largest + 1;
- align_next = false;
+ line.format_tokens[0].spaces_before = largest + 1
+ align_next = false
}
- kind := find_last_token(line.format_tokens).kind;
+ kind := find_last_token(line.format_tokens).kind
if tokenizer.Token_Kind.B_Operator_Begin < kind && kind <= tokenizer.Token_Kind.Cmp_Or {
- align_next = true;
+ align_next = true
}
if !align_next {
- break;
+ break
}
}
}
@@ -265,11 +265,11 @@ find_last_token :: proc(format_tokens: [dynamic]Format_Token) -> Format_Token { for i := len(format_tokens) - 1; i >= 0; i -= 1 {
if format_tokens[i].kind != .Comment {
- return format_tokens[i];
+ return format_tokens[i]
}
}
- panic("not possible");
+ panic("not possible")
}
format_assignment :: proc(p: ^Printer, index: int) {
@@ -277,226 +277,226 @@ format_assignment :: proc(p: ^Printer, index: int) { format_call :: proc(p: ^Printer, line_index: int, format_index: int) {
- paren_found := false;
- paren_token: Format_Token;
- paren_line: int;
- paren_token_index: int;
- largest := 0;
+ paren_found := false
+ paren_token: Format_Token
+ paren_line: int
+ paren_token_index: int
+ largest := 0
found_paren: for line, i in p.lines[line_index:] {
for format_token, j in line.format_tokens {
- largest += len(format_token.text) + format_token.spaces_before;
+ largest += len(format_token.text) + format_token.spaces_before
if i == 0 && j < format_index {
- continue;
+ continue
}
if format_token.kind == .Open_Paren && format_token.type == .Call {
- paren_token = format_token;
- paren_line = line_index + i;
- paren_found = true;
- paren_token_index = j;
- break found_paren;
+ paren_token = format_token
+ paren_line = line_index + i
+ paren_found = true
+ paren_token_index = j
+ break found_paren
}
}
}
if !paren_found {
- panic("Should not be possible");
+ panic("Should not be possible")
}
- paren_count := 1;
- done := false;
+ paren_count := 1
+ done := false
for line, line_index in p.lines[paren_line:] {
if len(line.format_tokens) == 0 {
- continue;
+ continue
}
for format_token, i in line.format_tokens {
if format_token.kind == .Comment {
- continue;
+ continue
}
if line_index == 0 && i <= paren_token_index {
- continue;
+ continue
}
if format_token.kind == .Open_Paren {
- paren_count += 1;
+ paren_count += 1
} else if format_token.kind == .Close_Paren {
- paren_count -= 1;
+ paren_count -= 1
}
if paren_count == 0 {
- done = true;
+ done = true
}
}
if line_index != 0 {
- line.format_tokens[0].spaces_before = largest;
+ line.format_tokens[0].spaces_before = largest
}
if done {
- return;
+ return
}
}
}
format_keyword_to_brace :: proc(p: ^Printer, line_index: int, format_index: int, keyword: tokenizer.Token_Kind) {
- keyword_found := false;
- keyword_token: Format_Token;
- keyword_line: int;
+ keyword_found := false
+ keyword_token: Format_Token
+ keyword_line: int
- largest := 0;
- brace_count := 0;
- done := false;
+ largest := 0
+ brace_count := 0
+ done := false
found_keyword: for line, i in p.lines[line_index:] {
for format_token in line.format_tokens {
- largest += len(format_token.text) + format_token.spaces_before;
+ largest += len(format_token.text) + format_token.spaces_before
if format_token.kind == keyword {
- keyword_token = format_token;
- keyword_line = line_index + i;
- keyword_found = true;
- break found_keyword;
+ keyword_token = format_token
+ keyword_line = line_index + i
+ keyword_found = true
+ break found_keyword
}
}
}
if !keyword_found {
- panic("Should not be possible");
+ panic("Should not be possible")
}
for line, line_index in p.lines[keyword_line:] {
if len(line.format_tokens) == 0 {
- continue;
+ continue
}
for format_token, i in line.format_tokens {
if format_token.kind == .Comment {
- break;
+ break
} else if format_token.kind == .Undef {
- return;
+ return
}
if line_index == 0 && i <= format_index {
- continue;
+ continue
}
if format_token.kind == .Open_Brace {
- brace_count += 1;
+ brace_count += 1
} else if format_token.kind == .Close_Brace {
- brace_count -= 1;
+ brace_count -= 1
}
if brace_count == 1 {
- done = true;
+ done = true
}
}
if line_index != 0 {
- line.format_tokens[0].spaces_before = largest + 1;
+ line.format_tokens[0].spaces_before = largest + 1
}
if done {
- return;
+ return
}
}
}
format_generic :: proc(p: ^Printer) {
- next_struct_line := 0;
+ next_struct_line := 0
for line, line_index in p.lines {
if len(line.format_tokens) <= 0 {
- continue;
+ continue
}
for format_token, token_index in line.format_tokens {
#partial switch format_token.kind {
case .For, .If, .When, .Switch:
- format_keyword_to_brace(p, line_index, token_index, format_token.kind);
+ format_keyword_to_brace(p, line_index, token_index, format_token.kind)
case .Proc:
if format_token.type == .Proc_Lit {
- format_keyword_to_brace(p, line_index, token_index, format_token.kind);
+ format_keyword_to_brace(p, line_index, token_index, format_token.kind)
}
case:
if format_token.type == .Call {
- format_call(p, line_index, token_index);
+ format_call(p, line_index, token_index)
}
}
}
if .Switch_Stmt in line.types && p.config.align_switch {
- align_switch_stmt(p, line_index);
+ align_switch_stmt(p, line_index)
}
if .Enum in line.types && p.config.align_enums {
- align_enum(p, line_index);
+ align_enum(p, line_index)
}
if .Struct in line.types && p.config.align_structs && next_struct_line <= 0 {
- next_struct_line = align_struct(p, line_index);
+ next_struct_line = align_struct(p, line_index)
}
if .Value_Decl in line.types {
- format_value_decl(p, line_index);
+ format_value_decl(p, line_index)
}
if .Assign in line.types {
- format_assignment(p, line_index);
+ format_assignment(p, line_index)
}
- next_struct_line -= 1;
+ next_struct_line -= 1
}
}
align_var_decls :: proc(p: ^Printer) {
- current_line: int;
- current_typed: bool;
- current_not_mutable: bool;
+ current_line: int
+ current_typed: bool
+ current_not_mutable: bool
- largest_lhs := 0;
- largest_rhs := 0;
+ largest_lhs := 0
+ largest_rhs := 0
TokenAndLength :: struct {
format_token: ^Format_Token,
length: int,
- };
+ }
- colon_tokens := make([dynamic]TokenAndLength, 0, 10, context.temp_allocator);
- type_tokens := make([dynamic]TokenAndLength, 0, 10, context.temp_allocator);
- equal_tokens := make([dynamic]TokenAndLength, 0, 10, context.temp_allocator);
+ colon_tokens := make([dynamic]TokenAndLength, 0, 10, context.temp_allocator)
+ type_tokens := make([dynamic]TokenAndLength, 0, 10, context.temp_allocator)
+ equal_tokens := make([dynamic]TokenAndLength, 0, 10, context.temp_allocator)
for line, line_index in p.lines {
//It is only possible to align value decls that are one one line, otherwise just ignore them
if .Value_Decl not_in line.types {
- continue;
+ continue
}
- typed := true;
- not_mutable := false;
- continue_flag := false;
+ typed := true
+ not_mutable := false
+ continue_flag := false
for i := 0; i < len(line.format_tokens); i += 1 {
if line.format_tokens[i].kind == .Colon && line.format_tokens[min(i + 1, len(line.format_tokens) - 1)].kind == .Eq {
- typed = false;
+ typed = false
}
if line.format_tokens[i].kind == .Colon && line.format_tokens[min(i + 1, len(line.format_tokens) - 1)].kind == .Colon {
- not_mutable = true;
+ not_mutable = true
}
if line.format_tokens[i].kind == .Union ||
@@ -505,85 +505,85 @@ align_var_decls :: proc(p: ^Printer) { line.format_tokens[i].kind == .For ||
line.format_tokens[i].kind == .If ||
line.format_tokens[i].kind == .Comment {
- continue_flag = true;
+ continue_flag = true
}
//enforced undef is always on the last line, if it exists
if line.format_tokens[i].kind == .Proc && line.format_tokens[len(line.format_tokens)-1].kind != .Undef {
- continue_flag = true;
+ continue_flag = true
}
}
if continue_flag {
- continue;
+ continue
}
if line_index != current_line + 1 || typed != current_typed || not_mutable != current_not_mutable {
if p.config.align_style == .Align_On_Colon_And_Equals || !current_typed || current_not_mutable {
for colon_token in colon_tokens {
- colon_token.format_token.spaces_before = largest_lhs - colon_token.length + 1;
+ colon_token.format_token.spaces_before = largest_lhs - colon_token.length + 1
}
} else if p.config.align_style == .Align_On_Type_And_Equals {
for type_token in type_tokens {
- type_token.format_token.spaces_before = largest_lhs - type_token.length + 1;
+ type_token.format_token.spaces_before = largest_lhs - type_token.length + 1
}
}
if current_typed {
for equal_token in equal_tokens {
- equal_token.format_token.spaces_before = largest_rhs - equal_token.length + 1;
+ equal_token.format_token.spaces_before = largest_rhs - equal_token.length + 1
}
} else {
for equal_token in equal_tokens {
- equal_token.format_token.spaces_before = 0;
+ equal_token.format_token.spaces_before = 0
}
}
- clear(&colon_tokens);
- clear(&type_tokens);
- clear(&equal_tokens);
+ clear(&colon_tokens)
+ clear(&type_tokens)
+ clear(&equal_tokens)
- largest_rhs = 0;
- largest_lhs = 0;
- current_typed = typed;
- current_not_mutable = not_mutable;
+ largest_rhs = 0
+ largest_lhs = 0
+ current_typed = typed
+ current_not_mutable = not_mutable
}
- current_line = line_index;
+ current_line = line_index
- current_token_index := 0;
- lhs_length := 0;
- rhs_length := 0;
+ current_token_index := 0
+ lhs_length := 0
+ rhs_length := 0
//calcuate the length of lhs of a value decl i.e. `a, b:`
for; current_token_index < len(line.format_tokens); current_token_index += 1 {
- lhs_length += len(line.format_tokens[current_token_index].text) + line.format_tokens[current_token_index].spaces_before;
+ lhs_length += len(line.format_tokens[current_token_index].text) + line.format_tokens[current_token_index].spaces_before
if line.format_tokens[current_token_index].kind == .Colon {
- append(&colon_tokens, TokenAndLength {format_token = &line.format_tokens[current_token_index], length = lhs_length});
+ append(&colon_tokens, TokenAndLength {format_token = &line.format_tokens[current_token_index], length = lhs_length})
if len(line.format_tokens) > current_token_index && line.format_tokens[current_token_index + 1].kind != .Eq {
- append(&type_tokens, TokenAndLength {format_token = &line.format_tokens[current_token_index + 1], length = lhs_length});
+ append(&type_tokens, TokenAndLength {format_token = &line.format_tokens[current_token_index + 1], length = lhs_length})
}
- current_token_index += 1;
- largest_lhs = max(largest_lhs, lhs_length);
- break;
+ current_token_index += 1
+ largest_lhs = max(largest_lhs, lhs_length)
+ break
}
}
//calcuate the length of the rhs i.e. `[dynamic]int = 123123`
for; current_token_index < len(line.format_tokens); current_token_index += 1 {
- rhs_length += len(line.format_tokens[current_token_index].text) + line.format_tokens[current_token_index].spaces_before;
+ rhs_length += len(line.format_tokens[current_token_index].text) + line.format_tokens[current_token_index].spaces_before
if line.format_tokens[current_token_index].kind == .Eq {
- append(&equal_tokens, TokenAndLength {format_token = &line.format_tokens[current_token_index], length = rhs_length});
- largest_rhs = max(largest_rhs, rhs_length);
- break;
+ append(&equal_tokens, TokenAndLength {format_token = &line.format_tokens[current_token_index], length = rhs_length})
+ largest_rhs = max(largest_rhs, rhs_length)
+ break
}
}
@@ -592,241 +592,241 @@ align_var_decls :: proc(p: ^Printer) { //repeating myself, move to sub procedure
if p.config.align_style == .Align_On_Colon_And_Equals || !current_typed || current_not_mutable {
for colon_token in colon_tokens {
- colon_token.format_token.spaces_before = largest_lhs - colon_token.length + 1;
+ colon_token.format_token.spaces_before = largest_lhs - colon_token.length + 1
}
} else if p.config.align_style == .Align_On_Type_And_Equals {
for type_token in type_tokens {
- type_token.format_token.spaces_before = largest_lhs - type_token.length + 1;
+ type_token.format_token.spaces_before = largest_lhs - type_token.length + 1
}
}
if current_typed {
for equal_token in equal_tokens {
- equal_token.format_token.spaces_before = largest_rhs - equal_token.length + 1;
+ equal_token.format_token.spaces_before = largest_rhs - equal_token.length + 1
}
} else {
for equal_token in equal_tokens {
- equal_token.format_token.spaces_before = 0;
+ equal_token.format_token.spaces_before = 0
}
}
}
align_switch_stmt :: proc(p: ^Printer, index: int) {
- switch_found := false;
- brace_token: Format_Token;
- brace_line: int;
+ switch_found := false
+ brace_token: Format_Token
+ brace_line: int
found_switch_brace: for line, line_index in p.lines[index:] {
for format_token in line.format_tokens {
if format_token.kind == .Open_Brace && switch_found {
- brace_token = format_token;
- brace_line = line_index + index;
- break found_switch_brace;
+ brace_token = format_token
+ brace_line = line_index + index
+ break found_switch_brace
} else if format_token.kind == .Open_Brace {
- break;
+ break
} else if format_token.kind == .Switch {
- switch_found = true;
+ switch_found = true
}
}
}
if !switch_found {
- return;
+ return
}
- largest := 0;
- case_count := 0;
+ largest := 0
+ case_count := 0
TokenAndLength :: struct {
format_token: ^Format_Token,
length: int,
- };
+ }
- format_tokens := make([dynamic]TokenAndLength, 0, brace_token.parameter_count, context.temp_allocator);
+ format_tokens := make([dynamic]TokenAndLength, 0, brace_token.parameter_count, context.temp_allocator)
//find all the switch cases that are one lined
for line, line_index in p.lines[brace_line + 1:] {
- case_found := false;
- colon_found := false;
- length := 0;
+ case_found := false
+ colon_found := false
+ length := 0
for format_token, i in line.format_tokens {
if format_token.kind == .Comment {
- break;
+ break
}
//this will only happen if the case is one lined
if case_found && colon_found {
- append(&format_tokens, TokenAndLength {format_token = &line.format_tokens[i], length = length});
- largest = max(length, largest);
- break;
+ append(&format_tokens, TokenAndLength {format_token = &line.format_tokens[i], length = length})
+ largest = max(length, largest)
+ break
}
if format_token.kind == .Case {
- case_found = true;
- case_count += 1;
+ case_found = true
+ case_count += 1
} else if format_token.kind == .Colon {
- colon_found = true;
+ colon_found = true
}
- length += len(format_token.text) + format_token.spaces_before;
+ length += len(format_token.text) + format_token.spaces_before
}
if case_count >= brace_token.parameter_count {
- break;
+ break
}
}
for token in format_tokens {
- token.format_token.spaces_before = largest - token.length + 1;
+ token.format_token.spaces_before = largest - token.length + 1
}
}
align_enum :: proc(p: ^Printer, index: int) {
- enum_found := false;
- brace_token: Format_Token;
- brace_line: int;
+ enum_found := false
+ brace_token: Format_Token
+ brace_line: int
found_enum_brace: for line, line_index in p.lines[index:] {
for format_token in line.format_tokens {
if format_token.kind == .Open_Brace && enum_found {
- brace_token = format_token;
- brace_line = line_index + index;
- break found_enum_brace;
+ brace_token = format_token
+ brace_line = line_index + index
+ break found_enum_brace
} else if format_token.kind == .Open_Brace {
- break;
+ break
} else if format_token.kind == .Enum {
- enum_found = true;
+ enum_found = true
}
}
}
if !enum_found {
- return;
+ return
}
- largest := 0;
- comma_count := 0;
+ largest := 0
+ comma_count := 0
TokenAndLength :: struct {
format_token: ^Format_Token,
length: int,
- };
+ }
- format_tokens := make([dynamic]TokenAndLength, 0, brace_token.parameter_count, context.temp_allocator);
+ format_tokens := make([dynamic]TokenAndLength, 0, brace_token.parameter_count, context.temp_allocator)
for line, line_index in p.lines[brace_line + 1:] {
- length := 0;
+ length := 0
for format_token, i in line.format_tokens {
if format_token.kind == .Comment {
- break;
+ break
}
if format_token.kind == .Eq {
- append(&format_tokens, TokenAndLength {format_token = &line.format_tokens[i], length = length});
- largest = max(length, largest);
- break;
+ append(&format_tokens, TokenAndLength {format_token = &line.format_tokens[i], length = length})
+ largest = max(length, largest)
+ break
} else if format_token.kind == .Comma {
- comma_count += 1;
+ comma_count += 1
}
- length += len(format_token.text) + format_token.spaces_before;
+ length += len(format_token.text) + format_token.spaces_before
}
if comma_count >= brace_token.parameter_count {
- break;
+ break
}
}
for token in format_tokens {
- token.format_token.spaces_before = largest - token.length + 1;
+ token.format_token.spaces_before = largest - token.length + 1
}
}
align_struct :: proc(p: ^Printer, index: int) -> int {
- struct_found := false;
- brace_token: Format_Token;
- brace_line: int;
+ struct_found := false
+ brace_token: Format_Token
+ brace_line: int
found_struct_brace: for line, line_index in p.lines[index:] {
for format_token in line.format_tokens {
if format_token.kind == .Open_Brace && struct_found {
- brace_token = format_token;
- brace_line = line_index + index;
- break found_struct_brace;
+ brace_token = format_token
+ brace_line = line_index + index
+ break found_struct_brace
} else if format_token.kind == .Open_Brace {
- break;
+ break
} else if format_token.kind == .Struct {
- struct_found = true;
+ struct_found = true
}
}
}
if !struct_found {
- return 0;
+ return 0
}
- largest := 0;
- colon_count := 0;
- nested := false;
- seen_brace := false;
+ largest := 0
+ colon_count := 0
+ nested := false
+ seen_brace := false
TokenAndLength :: struct {
format_token: ^Format_Token,
length: int,
- };
+ }
- format_tokens := make([]TokenAndLength, brace_token.parameter_count, context.temp_allocator);
+ format_tokens := make([]TokenAndLength, brace_token.parameter_count, context.temp_allocator)
if brace_token.parameter_count == 0 {
- return 0;
+ return 0
}
- end_line_index := 0;
+ end_line_index := 0
for line, line_index in p.lines[brace_line + 1:] {
- length := 0;
+ length := 0
for format_token, i in line.format_tokens {
//give up on nested structs
if format_token.kind == .Comment {
- break;
+ break
} else if format_token.kind == .Open_Paren {
- break;
+ break
} else if format_token.kind == .Open_Brace {
- seen_brace = true;
+ seen_brace = true
} else if format_token.kind == .Close_Brace {
- seen_brace = false;
+ seen_brace = false
} else if seen_brace {
- continue;
+ continue
}
if format_token.kind == .Colon {
- format_tokens[colon_count] = {format_token = &line.format_tokens[i + 1], length = length};
+ format_tokens[colon_count] = {format_token = &line.format_tokens[i + 1], length = length}
if format_tokens[colon_count].format_token.kind == .Struct {
- nested = true;
+ nested = true
}
- colon_count += 1;
- largest = max(length, largest);
+ colon_count += 1
+ largest = max(length, largest)
}
- length += len(format_token.text) + format_token.spaces_before;
+ length += len(format_token.text) + format_token.spaces_before
}
if nested {
- end_line_index = line_index + brace_line + 1;
+ end_line_index = line_index + brace_line + 1
}
if colon_count >= brace_token.parameter_count {
- break;
+ break
}
}
@@ -835,17 +835,17 @@ align_struct :: proc(p: ^Printer, index: int) -> int { for line, line_index in p.lines[end_line_index:] {
for format_token in line.format_tokens {
if format_token.kind == .Close_Brace {
- return end_line_index + line_index - index;
+ return end_line_index + line_index - index
}
}
}
}
for token in format_tokens {
- token.format_token.spaces_before = largest - token.length + 1;
+ token.format_token.spaces_before = largest - token.length + 1
}
- return 0;
+ return 0
}
align_comments :: proc(p: ^Printer) {
@@ -855,15 +855,15 @@ align_comments :: proc(p: ^Printer) { begin: int,
end: int,
depth: int,
- };
+ }
- comment_infos := make([dynamic]Comment_Align_Info, 0, context.temp_allocator);
+ comment_infos := make([dynamic]Comment_Align_Info, 0, context.temp_allocator)
- current_info: Comment_Align_Info;
+ current_info: Comment_Align_Info
for line, line_index in p.lines {
if len(line.format_tokens) <= 0 {
- continue;
+ continue
}
if .Line_Comment in line.types {
@@ -871,53 +871,53 @@ align_comments :: proc(p: ^Printer) { (current_info.begin == current_info.end && current_info.length == 0) {
if (current_info.begin != 0 && current_info.end != 0) || current_info.length > 0 {
- append(&comment_infos, current_info);
+ append(&comment_infos, current_info)
}
- current_info.begin = line_index;
- current_info.end = line_index;
- current_info.depth = line.depth;
- current_info.length = 0;
+ current_info.begin = line_index
+ current_info.end = line_index
+ current_info.depth = line.depth
+ current_info.length = 0
}
- length := 0;
+ length := 0
for format_token, i in line.format_tokens {
if format_token.kind == .Comment {
- current_info.length = max(current_info.length, length);
- current_info.end = line_index;
+ current_info.length = max(current_info.length, length)
+ current_info.end = line_index
}
- length += format_token.spaces_before + len(format_token.text);
+ length += format_token.spaces_before + len(format_token.text)
}
}
}
if (current_info.begin != 0 && current_info.end != 0) || current_info.length > 0 {
- append(&comment_infos, current_info);
+ append(&comment_infos, current_info)
}
for info in comment_infos {
if info.begin == info.end || info.length == 0 {
- continue;
+ continue
}
for i := info.begin; i <= info.end; i += 1 {
- l := p.lines[i];
+ l := p.lines[i]
- length := 0;
+ length := 0
for format_token, i in l.format_tokens {
if format_token.kind == .Comment {
if len(l.format_tokens) == 1 {
- l.format_tokens[i].spaces_before = info.length + 1;
+ l.format_tokens[i].spaces_before = info.length + 1
} else {
- l.format_tokens[i].spaces_before = info.length - length + 1;
+ l.format_tokens[i].spaces_before = info.length - length + 1
}
}
- length += format_token.spaces_before + len(format_token.text);
+ length += format_token.spaces_before + len(format_token.text)
}
}
}
diff --git a/core/odin/printer/visit.odin b/core/odin/printer/visit.odin index a6c3d9106..d9482e36f 100644 --- a/core/odin/printer/visit.odin +++ b/core/odin/printer/visit.odin @@ -15,40 +15,40 @@ sort_attribute :: proc(s: ^[dynamic]^ast.Attribute) -> sort.Interface { return sort.Interface {
collection = rawptr(s),
len = proc(it: sort.Interface) -> int {
- s := (^[dynamic]^ast.Attribute)(it.collection);
- return len(s^);
+ s := (^[dynamic]^ast.Attribute)(it.collection)
+ return len(s^)
},
less = proc(it: sort.Interface, i, j: int) -> bool {
- s := (^[dynamic]^ast.Attribute)(it.collection);
- return s[i].pos.offset < s[j].pos.offset;
+ s := (^[dynamic]^ast.Attribute)(it.collection)
+ return s[i].pos.offset < s[j].pos.offset
},
swap = proc(it: sort.Interface, i, j: int) {
- s := (^[dynamic]^ast.Attribute)(it.collection);
- s[i], s[j] = s[j], s[i];
+ s := (^[dynamic]^ast.Attribute)(it.collection)
+ s[i], s[j] = s[j], s[i]
},
- };
+ }
}
@(private)
comment_before_position :: proc(p: ^Printer, pos: tokenizer.Pos) -> bool {
if len(p.comments) <= p.latest_comment_index {
- return false;
+ return false
}
- comment := p.comments[p.latest_comment_index];
+ comment := p.comments[p.latest_comment_index]
- return comment.pos.offset < pos.offset;
+ return comment.pos.offset < pos.offset
}
@(private)
next_comment_group :: proc(p: ^Printer) {
- p.latest_comment_index += 1;
+ p.latest_comment_index += 1
}
@(private)
push_comment :: proc(p: ^Printer, comment: tokenizer.Token) -> int {
if len(comment.text) == 0 {
- return 0;
+ return 0
}
if comment.text[:2] != "/*" {
@@ -56,65 +56,65 @@ push_comment :: proc(p: ^Printer, comment: tokenizer.Token) -> int { spaces_before = 1,
kind = .Comment,
text = comment.text,
- };
+ }
if len(p.current_line.format_tokens) == 0 {
- format_token.spaces_before = 0;
+ format_token.spaces_before = 0
}
if !p.current_line.used {
- p.current_line.used = true;
- p.current_line.depth = p.depth;
+ p.current_line.used = true
+ p.current_line.depth = p.depth
}
- append(&p.current_line.format_tokens, format_token);
- p.last_token = &p.current_line.format_tokens[len(p.current_line.format_tokens) - 1];
+ append(&p.current_line.format_tokens, format_token)
+ p.last_token = &p.current_line.format_tokens[len(p.current_line.format_tokens) - 1]
- hint_current_line(p, {.Line_Comment});
+ hint_current_line(p, {.Line_Comment})
- return 0;
+ return 0
} else {
- builder := strings.make_builder(context.temp_allocator);
+ builder := strings.make_builder(context.temp_allocator)
- c_len := len(comment.text);
- trim_space := true;
+ c_len := len(comment.text)
+ trim_space := true
- multilines: [dynamic]string;
+ multilines: [dynamic]string
for i := 0; i < len(comment.text); i += 1 {
- c := comment.text[i];
+ c := comment.text[i]
if c != ' ' && c != '\t' {
- trim_space = false;
+ trim_space = false
}
switch {
case (c == ' ' || c == '\t' || c == '\n') && trim_space:
- continue;
+ continue
case c == '\r' && comment.text[min(c_len - 1, i + 1)] == '\n':
- append(&multilines, strings.to_string(builder));
- builder = strings.make_builder(context.temp_allocator);
- trim_space = true;
- i += 1;
+ append(&multilines, strings.to_string(builder))
+ builder = strings.make_builder(context.temp_allocator)
+ trim_space = true
+ i += 1
case c == '\n':
- append(&multilines, strings.to_string(builder));
- builder = strings.make_builder(context.temp_allocator);
- trim_space = true;
+ append(&multilines, strings.to_string(builder))
+ builder = strings.make_builder(context.temp_allocator)
+ trim_space = true
case c == '/' && comment.text[min(c_len - 1, i + 1)] == '*':
- strings.write_string(&builder, "/*");
- trim_space = true;
- i += 1;
+ strings.write_string(&builder, "/*")
+ trim_space = true
+ i += 1
case c == '*' && comment.text[min(c_len - 1, i + 1)] == '/':
- trim_space = true;
- strings.write_string(&builder, "*/");
- i += 1;
+ trim_space = true
+ strings.write_string(&builder, "*/")
+ i += 1
case:
- strings.write_byte(&builder, c);
+ strings.write_byte(&builder, c)
}
}
if strings.builder_len(builder) > 0 {
- append(&multilines, strings.to_string(builder));
+ append(&multilines, strings.to_string(builder))
}
for line in multilines {
@@ -122,106 +122,106 @@ push_comment :: proc(p: ^Printer, comment: tokenizer.Token) -> int { spaces_before = 1,
kind = .Comment,
text = line,
- };
+ }
if len(p.current_line.format_tokens) == 0 {
- format_token.spaces_before = 0;
+ format_token.spaces_before = 0
}
if strings.contains(line, "*/") {
- unindent(p);
+ unindent(p)
}
if !p.current_line.used {
- p.current_line.used = true;
- p.current_line.depth = p.depth;
+ p.current_line.used = true
+ p.current_line.depth = p.depth
}
- append(&p.current_line.format_tokens, format_token);
- p.last_token = &p.current_line.format_tokens[len(p.current_line.format_tokens) - 1];
+ append(&p.current_line.format_tokens, format_token)
+ p.last_token = &p.current_line.format_tokens[len(p.current_line.format_tokens) - 1]
if strings.contains(line, "/*") {
- indent(p);
+ indent(p)
}
- newline_position(p, 1);
+ newline_position(p, 1)
}
- return len(multilines);
+ return len(multilines)
}
}
@(private)
push_comments :: proc(p: ^Printer, pos: tokenizer.Pos) {
- prev_comment: ^tokenizer.Token;
- prev_comment_lines: int;
+ prev_comment: ^tokenizer.Token
+ prev_comment_lines: int
for comment_before_position(p, pos) {
- comment_group := p.comments[p.latest_comment_index];
+ comment_group := p.comments[p.latest_comment_index]
if prev_comment == nil {
- lines := comment_group.pos.line - p.last_source_position.line;
- set_line(p, p.last_line_index + min(p.config.newline_limit+1, lines));
+ lines := comment_group.pos.line - p.last_source_position.line
+ set_line(p, p.last_line_index + min(p.config.newline_limit+1, lines))
}
for comment, i in comment_group.list {
if prev_comment != nil && p.last_source_position.line != comment.pos.line {
- newline_position(p, min(p.config.newline_limit+1, comment.pos.line - prev_comment.pos.line - prev_comment_lines));
+ newline_position(p, min(p.config.newline_limit+1, comment.pos.line - prev_comment.pos.line - prev_comment_lines))
}
- prev_comment_lines = push_comment(p, comment);
- prev_comment = &comment_group.list[i];
+ prev_comment_lines = push_comment(p, comment)
+ prev_comment = &comment_group.list[i]
}
- next_comment_group(p);
+ next_comment_group(p)
}
if prev_comment != nil {
- newline_position(p, min(p.config.newline_limit+1, p.source_position.line - prev_comment.pos.line - prev_comment_lines));
+ newline_position(p, min(p.config.newline_limit+1, p.source_position.line - prev_comment.pos.line - prev_comment_lines))
}
}
@(private)
append_format_token :: proc(p: ^Printer, format_token: Format_Token) -> ^Format_Token {
- format_token := format_token;
+ format_token := format_token
if p.last_token != nil && (
p.last_token.kind == .Ellipsis ||
p.last_token.kind == .Range_Half || p.last_token.kind == .Range_Full ||
p.last_token.kind == .Open_Paren || p.last_token.kind == .Period ||
p.last_token.kind == .Open_Brace || p.last_token.kind == .Open_Bracket) {
- format_token.spaces_before = 0;
+ format_token.spaces_before = 0
} else if p.merge_next_token {
- format_token.spaces_before = 0;
- p.merge_next_token = false;
+ format_token.spaces_before = 0
+ p.merge_next_token = false
} else if p.space_next_token {
- format_token.spaces_before = 1;
- p.space_next_token = false;
+ format_token.spaces_before = 1
+ p.space_next_token = false
}
- push_comments(p, p.source_position);
+ push_comments(p, p.source_position)
- unwrapped_line := p.current_line;
+ unwrapped_line := p.current_line
if !unwrapped_line.used {
- unwrapped_line.used = true;
- unwrapped_line.depth = p.depth;
+ unwrapped_line.used = true
+ unwrapped_line.depth = p.depth
}
if len(unwrapped_line.format_tokens) == 0 && format_token.spaces_before == 1 {
- format_token.spaces_before = 0;
+ format_token.spaces_before = 0
}
- p.last_source_position = p.source_position;
- p.last_line_index = p.current_line_index;
+ p.last_source_position = p.source_position
+ p.last_line_index = p.current_line_index
- append(&unwrapped_line.format_tokens, format_token);
- return &unwrapped_line.format_tokens[len(unwrapped_line.format_tokens) - 1];
+ append(&unwrapped_line.format_tokens, format_token)
+ return &unwrapped_line.format_tokens[len(unwrapped_line.format_tokens) - 1]
}
@(private)
push_format_token :: proc(p: ^Printer, format_token: Format_Token) {
- p.last_token = append_format_token(p, format_token);
+ p.last_token = append_format_token(p, format_token)
}
@(private)
@@ -230,13 +230,13 @@ push_generic_token :: proc(p: ^Printer, kind: tokenizer.Token_Kind, spaces_befor spaces_before = spaces_before,
kind = kind,
text = tokenizer.tokens[kind],
- };
+ }
if value != "" {
- format_token.text = value;
+ format_token.text = value
}
- p.last_token = append_format_token(p, format_token);
+ p.last_token = append_format_token(p, format_token)
}
@(private)
@@ -245,9 +245,9 @@ push_string_token :: proc(p: ^Printer, text: string, spaces_before: int) { spaces_before = spaces_before,
kind = .String,
text = text,
- };
+ }
- p.last_token = append_format_token(p, format_token);
+ p.last_token = append_format_token(p, format_token)
}
@(private)
@@ -256,886 +256,886 @@ push_ident_token :: proc(p: ^Printer, text: string, spaces_before: int) { spaces_before = spaces_before,
kind = .Ident,
text = text,
- };
+ }
- p.last_token = append_format_token(p, format_token);
+ p.last_token = append_format_token(p, format_token)
}
@(private)
set_source_position :: proc(p: ^Printer, pos: tokenizer.Pos) {
- p.source_position = pos;
+ p.source_position = pos
}
@(private)
move_line :: proc(p: ^Printer, pos: tokenizer.Pos) {
- move_line_limit(p, pos, p.config.newline_limit+1);
+ move_line_limit(p, pos, p.config.newline_limit+1)
}
@(private)
move_line_limit :: proc(p: ^Printer, pos: tokenizer.Pos, limit: int) -> bool {
- lines := min(pos.line - p.source_position.line, limit);
+ lines := min(pos.line - p.source_position.line, limit)
if lines < 0 {
- return false;
+ return false
}
- p.source_position = pos;
- p.current_line_index += lines;
- set_line(p, p.current_line_index);
- return lines > 0;
+ p.source_position = pos
+ p.current_line_index += lines
+ set_line(p, p.current_line_index)
+ return lines > 0
}
@(private)
set_line :: proc(p: ^Printer, line: int) -> ^Line {
- unwrapped_line: ^Line;
+ unwrapped_line: ^Line
if line >= len(p.lines) {
for i := len(p.lines); i <= line; i += 1 {
- new_line: Line;
- new_line.format_tokens = make([dynamic]Format_Token, 0, 50, p.allocator);
- append(&p.lines, new_line);
+ new_line: Line
+ new_line.format_tokens = make([dynamic]Format_Token, 0, 50, p.allocator)
+ append(&p.lines, new_line)
}
- unwrapped_line = &p.lines[line];
+ unwrapped_line = &p.lines[line]
} else {
- unwrapped_line = &p.lines[line];
+ unwrapped_line = &p.lines[line]
}
- p.current_line = unwrapped_line;
- p.current_line_index = line;
+ p.current_line = unwrapped_line
+ p.current_line_index = line
- return unwrapped_line;
+ return unwrapped_line
}
@(private)
newline_position :: proc(p: ^Printer, count: int) {
- p.current_line_index += count;
- set_line(p, p.current_line_index);
+ p.current_line_index += count
+ set_line(p, p.current_line_index)
}
@(private)
indent :: proc(p: ^Printer) {
- p.depth += 1;
+ p.depth += 1
}
@(private)
unindent :: proc(p: ^Printer) {
- p.depth -= 1;
+ p.depth -= 1
}
@(private)
merge_next_token :: proc(p: ^Printer) {
- p.merge_next_token = true;
+ p.merge_next_token = true
}
@(private)
space_next_token :: proc(p: ^Printer) {
- p.space_next_token = true;
+ p.space_next_token = true
}
@(private)
hint_current_line :: proc(p: ^Printer, hint: Line_Type) {
- p.current_line.types |= hint;
+ p.current_line.types |= hint
}
@(private)
visit_decl :: proc(p: ^Printer, decl: ^ast.Decl, called_in_stmt := false) {
- using ast;
+ using ast
if decl == nil {
- return;
+ return
}
switch v in &decl.derived {
case Expr_Stmt:
- move_line(p, decl.pos);
- visit_expr(p, v.expr);
+ move_line(p, decl.pos)
+ visit_expr(p, v.expr)
if p.config.semicolons {
- push_generic_token(p, .Semicolon, 0);
+ push_generic_token(p, .Semicolon, 0)
}
case When_Stmt:
- visit_stmt(p, cast(^Stmt)decl);
+ visit_stmt(p, cast(^Stmt)decl)
case Foreign_Import_Decl:
if len(v.attributes) > 0 {
- sort.sort(sort_attribute(&v.attributes));
- move_line(p, v.attributes[0].pos);
- visit_attributes(p, v.attributes);
+ sort.sort(sort_attribute(&v.attributes))
+ move_line(p, v.attributes[0].pos)
+ visit_attributes(p, v.attributes)
}
- move_line(p, decl.pos);
+ move_line(p, decl.pos)
- push_generic_token(p, v.foreign_tok.kind, 0);
- push_generic_token(p, v.import_tok.kind, 1);
+ push_generic_token(p, v.foreign_tok.kind, 0)
+ push_generic_token(p, v.import_tok.kind, 1)
if v.name != nil {
- push_ident_token(p, v.name.name, 1);
+ push_ident_token(p, v.name.name, 1)
}
for path in v.fullpaths {
- push_ident_token(p, path, 0);
+ push_ident_token(p, path, 0)
}
case Foreign_Block_Decl:
if len(v.attributes) > 0 {
- sort.sort(sort_attribute(&v.attributes));
- move_line(p, v.attributes[0].pos);
- visit_attributes(p, v.attributes);
+ sort.sort(sort_attribute(&v.attributes))
+ move_line(p, v.attributes[0].pos)
+ visit_attributes(p, v.attributes)
}
- move_line(p, decl.pos);
+ move_line(p, decl.pos)
- push_generic_token(p, .Foreign, 0);
+ push_generic_token(p, .Foreign, 0)
- visit_expr(p, v.foreign_library);
- visit_stmt(p, v.body);
+ visit_expr(p, v.foreign_library)
+ visit_stmt(p, v.body)
case Import_Decl:
- move_line(p, decl.pos);
+ move_line(p, decl.pos)
if v.name.text != "" {
- push_generic_token(p, v.import_tok.kind, 1);
- push_generic_token(p, v.name.kind, 1, v.name.text);
- push_ident_token(p, v.fullpath, 1);
+ push_generic_token(p, v.import_tok.kind, 1)
+ push_generic_token(p, v.name.kind, 1, v.name.text)
+ push_ident_token(p, v.fullpath, 1)
} else {
- push_generic_token(p, v.import_tok.kind, 1);
- push_ident_token(p, v.fullpath, 1);
+ push_generic_token(p, v.import_tok.kind, 1)
+ push_ident_token(p, v.fullpath, 1)
}
case Value_Decl:
if len(v.attributes) > 0 {
- sort.sort(sort_attribute(&v.attributes));
- move_line(p, v.attributes[0].pos);
- visit_attributes(p, v.attributes);
+ sort.sort(sort_attribute(&v.attributes))
+ move_line(p, v.attributes[0].pos)
+ visit_attributes(p, v.attributes)
}
- move_line(p, decl.pos);
+ move_line(p, decl.pos)
if v.is_using {
- push_generic_token(p, .Using, 0);
+ push_generic_token(p, .Using, 0)
}
- visit_exprs(p, v.names, {.Add_Comma});
+ visit_exprs(p, v.names, {.Add_Comma})
- hint_current_line(p, {.Value_Decl});
+ hint_current_line(p, {.Value_Decl})
if v.type != nil {
if !v.is_mutable {
- push_generic_token(p, .Colon, 0);
+ push_generic_token(p, .Colon, 0)
} else {
- push_generic_token(p, .Colon, 0);
+ push_generic_token(p, .Colon, 0)
}
- visit_expr(p, v.type);
+ visit_expr(p, v.type)
} else {
if !v.is_mutable {
- push_generic_token(p, .Colon, 1);
- push_generic_token(p, .Colon, 0);
+ push_generic_token(p, .Colon, 1)
+ push_generic_token(p, .Colon, 0)
} else {
- push_generic_token(p, .Colon, 1);
+ push_generic_token(p, .Colon, 1)
}
}
if v.is_mutable && v.type != nil && len(v.values) != 0 {
- push_generic_token(p, .Eq, 1);
+ push_generic_token(p, .Eq, 1)
} else if v.is_mutable && v.type == nil && len(v.values) != 0 {
- push_generic_token(p, .Eq, 0);
+ push_generic_token(p, .Eq, 0)
} else if !v.is_mutable && v.type != nil {
- push_generic_token(p, .Colon, 0);
+ push_generic_token(p, .Colon, 0)
}
if len(v.values) == 1 {
- visit_expr(p, v.values[0]); //this is too ensure that one value are never newlined(procs, structs, etc.)
+ visit_expr(p, v.values[0]) //this is too ensure that one value are never newlined(procs, structs, etc.)
} else {
- visit_exprs(p, v.values, {.Add_Comma});
+ visit_exprs(p, v.values, {.Add_Comma})
}
- add_semicolon := true;
+ add_semicolon := true
for value in v.values {
switch a in value.derived {
case Union_Type, Enum_Type, Struct_Type:
- add_semicolon = false || called_in_stmt;
+ add_semicolon = false || called_in_stmt
case Proc_Lit:
- add_semicolon = false;
+ add_semicolon = false
}
}
if add_semicolon && p.config.semicolons && !p.skip_semicolon {
- push_generic_token(p, .Semicolon, 0);
+ push_generic_token(p, .Semicolon, 0)
}
case:
- panic(fmt.aprint(decl.derived));
+ panic(fmt.aprint(decl.derived))
}
}
@(private)
visit_exprs :: proc(p: ^Printer, list: []^ast.Expr, options := List_Options{}) {
if len(list) == 0 {
- return;
+ return
}
// we have to newline the expressions to respect the source
for expr, i in list {
// Don't move the first expression, it looks bad
if i != 0 && .Enforce_Newline in options {
- newline_position(p, 1);
+ newline_position(p, 1)
} else if i != 0 {
- move_line_limit(p, expr.pos, 1);
+ move_line_limit(p, expr.pos, 1)
}
- visit_expr(p, expr, options);
+ visit_expr(p, expr, options)
if (i != len(list) - 1 || .Trailing in options) && .Add_Comma in options {
- push_generic_token(p, .Comma, 0);
+ push_generic_token(p, .Comma, 0)
}
}
if len(list) > 1 && .Enforce_Newline in options {
- newline_position(p, 1);
+ newline_position(p, 1)
}
}
@(private)
visit_attributes :: proc(p: ^Printer, attributes: [dynamic]^ast.Attribute) {
if len(attributes) == 0 {
- return;
+ return
}
for attribute, i in attributes {
- move_line_limit(p, attribute.pos, 1);
+ move_line_limit(p, attribute.pos, 1)
- push_generic_token(p, .At, 0);
- push_generic_token(p, .Open_Paren, 0);
+ push_generic_token(p, .At, 0)
+ push_generic_token(p, .Open_Paren, 0)
- visit_exprs(p, attribute.elems, {.Add_Comma});
+ visit_exprs(p, attribute.elems, {.Add_Comma})
- push_generic_token(p, .Close_Paren, 0);
+ push_generic_token(p, .Close_Paren, 0)
}
}
@(private)
visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Generic, empty_block := false, block_stmt := false) {
- using ast;
+ using ast
if stmt == nil {
- return;
+ return
}
switch v in stmt.derived {
case Import_Decl:
- visit_decl(p, cast(^Decl)stmt, true);
- return;
+ visit_decl(p, cast(^Decl)stmt, true)
+ return
case Value_Decl:
- visit_decl(p, cast(^Decl)stmt, true);
- return;
+ visit_decl(p, cast(^Decl)stmt, true)
+ return
case Foreign_Import_Decl:
- visit_decl(p, cast(^Decl)stmt, true);
- return;
+ visit_decl(p, cast(^Decl)stmt, true)
+ return
case Foreign_Block_Decl:
- visit_decl(p, cast(^Decl)stmt, true);
- return;
+ visit_decl(p, cast(^Decl)stmt, true)
+ return
}
switch v in stmt.derived {
case Using_Stmt:
- move_line(p, v.pos);
+ move_line(p, v.pos)
- push_generic_token(p, .Using, 1);
+ push_generic_token(p, .Using, 1)
- visit_exprs(p, v.list, {.Add_Comma});
+ visit_exprs(p, v.list, {.Add_Comma})
if p.config.semicolons {
- push_generic_token(p, .Semicolon, 0);
+ push_generic_token(p, .Semicolon, 0)
}
case Block_Stmt:
- move_line(p, v.pos);
+ move_line(p, v.pos)
if v.pos.line == v.end.line {
if !empty_block {
- push_generic_token(p, .Open_Brace, 1);
+ push_generic_token(p, .Open_Brace, 1)
}
- set_source_position(p, v.pos);
+ set_source_position(p, v.pos)
- visit_block_stmts(p, v.stmts, len(v.stmts) > 1 && p.config.split_multiple_stmts);
+ visit_block_stmts(p, v.stmts, len(v.stmts) > 1 && p.config.split_multiple_stmts)
- set_source_position(p, v.end);
+ set_source_position(p, v.end)
if !empty_block {
- push_generic_token(p, .Close_Brace, 0);
+ push_generic_token(p, .Close_Brace, 0)
}
} else {
if !empty_block {
- visit_begin_brace(p, v.pos, block_type, len(v.stmts));
+ visit_begin_brace(p, v.pos, block_type, len(v.stmts))
}
- set_source_position(p, v.pos);
+ set_source_position(p, v.pos)
- visit_block_stmts(p, v.stmts, len(v.stmts) > 1 && p.config.split_multiple_stmts);
+ visit_block_stmts(p, v.stmts, len(v.stmts) > 1 && p.config.split_multiple_stmts)
if !empty_block {
- visit_end_brace(p, v.end);
+ visit_end_brace(p, v.end)
}
}
case If_Stmt:
- move_line(p, v.pos);
+ move_line(p, v.pos)
if v.label != nil {
- visit_expr(p, v.label);
- push_generic_token(p, .Colon, 0);
+ visit_expr(p, v.label)
+ push_generic_token(p, .Colon, 0)
}
- push_generic_token(p, .If, 1);
+ push_generic_token(p, .If, 1)
- hint_current_line(p, {.If});
+ hint_current_line(p, {.If})
if v.init != nil {
- p.skip_semicolon = true;
- visit_stmt(p, v.init);
- p.skip_semicolon = false;
- push_generic_token(p, .Semicolon, 0);
+ p.skip_semicolon = true
+ visit_stmt(p, v.init)
+ p.skip_semicolon = false
+ push_generic_token(p, .Semicolon, 0)
}
- visit_expr(p, v.cond);
+ visit_expr(p, v.cond)
- uses_do := false;
+ uses_do := false
if check_stmt, ok := v.body.derived.(Block_Stmt); ok && check_stmt.uses_do {
- uses_do = true;
+ uses_do = true
}
if uses_do && !p.config.convert_do {
- push_generic_token(p, .Do, 1);
- visit_stmt(p, v.body, .If_Stmt, true);
+ push_generic_token(p, .Do, 1)
+ visit_stmt(p, v.body, .If_Stmt, true)
} else {
if uses_do {
- newline_position(p, 1);
+ newline_position(p, 1)
}
- set_source_position(p, v.body.pos);
+ set_source_position(p, v.body.pos)
- visit_stmt(p, v.body, .If_Stmt);
+ visit_stmt(p, v.body, .If_Stmt)
- set_source_position(p, v.body.end);
+ set_source_position(p, v.body.end)
}
if v.else_stmt != nil {
if p.config.brace_style == .Allman || p.config.brace_style == .Stroustrup {
- newline_position(p, 1);
+ newline_position(p, 1)
}
- push_generic_token(p, .Else, 1);
+ push_generic_token(p, .Else, 1)
- set_source_position(p, v.else_stmt.pos);
+ set_source_position(p, v.else_stmt.pos)
- visit_stmt(p, v.else_stmt);
+ visit_stmt(p, v.else_stmt)
}
case Switch_Stmt:
- move_line(p, v.pos);
+ move_line(p, v.pos)
if v.label != nil {
- visit_expr(p, v.label);
- push_generic_token(p, .Colon, 0);
+ visit_expr(p, v.label)
+ push_generic_token(p, .Colon, 0)
}
if v.partial {
- push_ident_token(p, "#partial", 1);
+ push_ident_token(p, "#partial", 1)
}
- push_generic_token(p, .Switch, 1);
+ push_generic_token(p, .Switch, 1)
- hint_current_line(p, {.Switch_Stmt});
+ hint_current_line(p, {.Switch_Stmt})
if v.init != nil {
- p.skip_semicolon = true;
- visit_stmt(p, v.init);
- p.skip_semicolon = false;
+ p.skip_semicolon = true
+ visit_stmt(p, v.init)
+ p.skip_semicolon = false
}
if v.init != nil && v.cond != nil {
- push_generic_token(p, .Semicolon, 0);
+ push_generic_token(p, .Semicolon, 0)
}
- visit_expr(p, v.cond);
- visit_stmt(p, v.body);
+ visit_expr(p, v.cond)
+ visit_stmt(p, v.body)
case Case_Clause:
- move_line(p, v.pos);
+ move_line(p, v.pos)
if !p.config.indent_cases {
- unindent(p);
+ unindent(p)
}
- push_generic_token(p, .Case, 0);
+ push_generic_token(p, .Case, 0)
if v.list != nil {
- visit_exprs(p, v.list, {.Add_Comma});
+ visit_exprs(p, v.list, {.Add_Comma})
}
- push_generic_token(p, v.terminator.kind, 0);
+ push_generic_token(p, v.terminator.kind, 0)
- indent(p);
+ indent(p)
- visit_block_stmts(p, v.body);
+ visit_block_stmts(p, v.body)
- unindent(p);
+ unindent(p)
if !p.config.indent_cases {
- indent(p);
+ indent(p)
}
case Type_Switch_Stmt:
- move_line(p, v.pos);
+ move_line(p, v.pos)
- hint_current_line(p, {.Switch_Stmt});
+ hint_current_line(p, {.Switch_Stmt})
if v.label != nil {
- visit_expr(p, v.label);
- push_generic_token(p, .Colon, 0);
+ visit_expr(p, v.label)
+ push_generic_token(p, .Colon, 0)
}
if v.partial {
- push_ident_token(p, "#partial", 1);
+ push_ident_token(p, "#partial", 1)
}
- push_generic_token(p, .Switch, 1);
+ push_generic_token(p, .Switch, 1)
- visit_stmt(p, v.tag);
- visit_stmt(p, v.body);
+ visit_stmt(p, v.tag)
+ visit_stmt(p, v.body)
case Assign_Stmt:
- move_line(p, v.pos);
+ move_line(p, v.pos)
- hint_current_line(p, {.Assign});
+ hint_current_line(p, {.Assign})
- visit_exprs(p, v.lhs, {.Add_Comma});
+ visit_exprs(p, v.lhs, {.Add_Comma})
- push_generic_token(p, v.op.kind, 1);
+ push_generic_token(p, v.op.kind, 1)
- visit_exprs(p, v.rhs, {.Add_Comma});
+ visit_exprs(p, v.rhs, {.Add_Comma})
if block_stmt && p.config.semicolons {
- push_generic_token(p, .Semicolon, 0);
+ push_generic_token(p, .Semicolon, 0)
}
case Expr_Stmt:
- move_line(p, v.pos);
- visit_expr(p, v.expr);
+ move_line(p, v.pos)
+ visit_expr(p, v.expr)
if block_stmt && p.config.semicolons {
- push_generic_token(p, .Semicolon, 0);
+ push_generic_token(p, .Semicolon, 0)
}
case For_Stmt:
// this should be simplified
- move_line(p, v.pos);
+ move_line(p, v.pos)
if v.label != nil {
- visit_expr(p, v.label);
- push_generic_token(p, .Colon, 0);
+ visit_expr(p, v.label)
+ push_generic_token(p, .Colon, 0)
}
- push_generic_token(p, .For, 1);
+ push_generic_token(p, .For, 1)
- hint_current_line(p, {.For});
+ hint_current_line(p, {.For})
if v.init != nil {
- p.skip_semicolon = true;
- visit_stmt(p, v.init);
- p.skip_semicolon = false;
- push_generic_token(p, .Semicolon, 0);
+ p.skip_semicolon = true
+ visit_stmt(p, v.init)
+ p.skip_semicolon = false
+ push_generic_token(p, .Semicolon, 0)
} else if v.post != nil {
- push_generic_token(p, .Semicolon, 0);
+ push_generic_token(p, .Semicolon, 0)
}
if v.cond != nil {
- move_line(p, v.cond.pos);
- visit_expr(p, v.cond);
+ move_line(p, v.cond.pos)
+ visit_expr(p, v.cond)
}
if v.post != nil {
- push_generic_token(p, .Semicolon, 0);
- move_line(p, v.post.pos);
- visit_stmt(p, v.post);
+ push_generic_token(p, .Semicolon, 0)
+ move_line(p, v.post.pos)
+ visit_stmt(p, v.post)
} else if v.post == nil && v.cond != nil && v.init != nil {
- push_generic_token(p, .Semicolon, 0);
+ push_generic_token(p, .Semicolon, 0)
}
- visit_stmt(p, v.body);
+ visit_stmt(p, v.body)
case Inline_Range_Stmt:
- move_line(p, v.pos);
+ move_line(p, v.pos)
if v.label != nil {
- visit_expr(p, v.label);
- push_generic_token(p, .Colon, 0);
+ visit_expr(p, v.label)
+ push_generic_token(p, .Colon, 0)
}
- push_ident_token(p, "#unroll", 0);
+ push_ident_token(p, "#unroll", 0)
- push_generic_token(p, .For, 1);
+ push_generic_token(p, .For, 1)
- hint_current_line(p, {.For});
+ hint_current_line(p, {.For})
- visit_expr(p, v.val0);
+ visit_expr(p, v.val0)
if v.val1 != nil {
- push_generic_token(p, .Comma, 0);
- visit_expr(p, v.val1);
+ push_generic_token(p, .Comma, 0)
+ visit_expr(p, v.val1)
}
- push_generic_token(p, .In, 1);
+ push_generic_token(p, .In, 1)
- visit_expr(p, v.expr);
- visit_stmt(p, v.body);
+ visit_expr(p, v.expr)
+ visit_stmt(p, v.body)
case Range_Stmt:
- move_line(p, v.pos);
+ move_line(p, v.pos)
if v.label != nil {
- visit_expr(p, v.label);
- push_generic_token(p, .Colon, 0);
+ visit_expr(p, v.label)
+ push_generic_token(p, .Colon, 0)
}
- push_generic_token(p, .For, 1);
+ push_generic_token(p, .For, 1)
- hint_current_line(p, {.For});
+ hint_current_line(p, {.For})
if len(v.vals) >= 1 {
- visit_expr(p, v.vals[0]);
+ visit_expr(p, v.vals[0])
}
if len(v.vals) >= 2 {
- push_generic_token(p, .Comma, 0);
- visit_expr(p, v.vals[1]);
+ push_generic_token(p, .Comma, 0)
+ visit_expr(p, v.vals[1])
}
- push_generic_token(p, .In, 1);
+ push_generic_token(p, .In, 1)
- visit_expr(p, v.expr);
+ visit_expr(p, v.expr)
- visit_stmt(p, v.body);
+ visit_stmt(p, v.body)
case Return_Stmt:
- move_line(p, v.pos);
+ move_line(p, v.pos)
- push_generic_token(p, .Return, 1);
+ push_generic_token(p, .Return, 1)
if v.results != nil {
- visit_exprs(p, v.results, {.Add_Comma});
+ visit_exprs(p, v.results, {.Add_Comma})
}
if block_stmt && p.config.semicolons {
- push_generic_token(p, .Semicolon, 0);
+ push_generic_token(p, .Semicolon, 0)
}
case Defer_Stmt:
- move_line(p, v.pos);
- push_generic_token(p, .Defer, 0);
+ move_line(p, v.pos)
+ push_generic_token(p, .Defer, 0)
- visit_stmt(p, v.stmt);
+ visit_stmt(p, v.stmt)
if p.config.semicolons {
- push_generic_token(p, .Semicolon, 0);
+ push_generic_token(p, .Semicolon, 0)
}
case When_Stmt:
- move_line(p, v.pos);
- push_generic_token(p, .When, 1);
- visit_expr(p, v.cond);
+ move_line(p, v.pos)
+ push_generic_token(p, .When, 1)
+ visit_expr(p, v.cond)
- visit_stmt(p, v.body);
+ visit_stmt(p, v.body)
if v.else_stmt != nil {
if p.config.brace_style == .Allman {
- newline_position(p, 1);
+ newline_position(p, 1)
}
- push_generic_token(p, .Else, 1);
+ push_generic_token(p, .Else, 1)
- set_source_position(p, v.else_stmt.pos);
+ set_source_position(p, v.else_stmt.pos)
- visit_stmt(p, v.else_stmt);
+ visit_stmt(p, v.else_stmt)
}
case Branch_Stmt:
- move_line(p, v.pos);
+ move_line(p, v.pos)
- push_generic_token(p, v.tok.kind, 0);
+ push_generic_token(p, v.tok.kind, 0)
if v.label != nil {
- visit_expr(p, v.label);
+ visit_expr(p, v.label)
}
if p.config.semicolons {
- push_generic_token(p, .Semicolon, 0);
+ push_generic_token(p, .Semicolon, 0)
}
case:
- panic(fmt.aprint(stmt.derived));
+ panic(fmt.aprint(stmt.derived))
}
- set_source_position(p, stmt.end);
+ set_source_position(p, stmt.end)
}
@(private)
push_where_clauses :: proc(p: ^Printer, clauses: []^ast.Expr) {
if len(clauses) == 0 {
- return;
+ return
}
// TODO(bill): This is not outputting correctly at all
- move_line(p, clauses[0].pos);
- push_generic_token(p, .Where, 1);
+ move_line(p, clauses[0].pos)
+ push_generic_token(p, .Where, 1)
- force_newline := false;
+ force_newline := false
for expr, i in clauses {
// Don't move the first expression, it looks bad
if i != 0 && i != len(clauses)-1 && force_newline {
- newline_position(p, 1);
+ newline_position(p, 1)
} else if i != 0 {
- move_line_limit(p, expr.pos, 1);
+ move_line_limit(p, expr.pos, 1)
}
- visit_expr(p, expr);
+ visit_expr(p, expr)
if i != len(clauses) - 1 {
- push_generic_token(p, .Comma, 0);
+ push_generic_token(p, .Comma, 0)
}
}
if len(clauses) > 1 && force_newline {
- newline_position(p, 1);
+ newline_position(p, 1)
}
}
@(private)
push_poly_params :: proc(p: ^Printer, poly_params: ^ast.Field_List) {
if poly_params != nil {
- push_generic_token(p, .Open_Paren, 0);
- visit_field_list(p, poly_params, {.Add_Comma, .Enforce_Poly_Names});
- push_generic_token(p, .Close_Paren, 0);
+ push_generic_token(p, .Open_Paren, 0)
+ visit_field_list(p, poly_params, {.Add_Comma, .Enforce_Poly_Names})
+ push_generic_token(p, .Close_Paren, 0)
}
}
@(private)
visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, options := List_Options{}) {
- using ast;
+ using ast
if expr == nil {
- return;
+ return
}
- set_source_position(p, expr.pos);
+ set_source_position(p, expr.pos)
switch v in expr.derived {
case Inline_Asm_Expr:
- push_generic_token(p, v.tok.kind, 1, v.tok.text);
+ push_generic_token(p, v.tok.kind, 1, v.tok.text)
- push_generic_token(p, .Open_Paren, 1);
- visit_exprs(p, v.param_types, {.Add_Comma});
- push_generic_token(p, .Close_Paren, 0);
+ push_generic_token(p, .Open_Paren, 1)
+ visit_exprs(p, v.param_types, {.Add_Comma})
+ push_generic_token(p, .Close_Paren, 0)
- push_generic_token(p, .Sub, 1);
- push_generic_token(p, .Gt, 0);
+ push_generic_token(p, .Sub, 1)
+ push_generic_token(p, .Gt, 0)
- visit_expr(p, v.return_type);
+ visit_expr(p, v.return_type)
- push_generic_token(p, .Open_Brace, 1);
- visit_expr(p, v.asm_string);
- push_generic_token(p, .Comma, 0);
- visit_expr(p, v.constraints_string);
- push_generic_token(p, .Close_Brace, 0);
+ push_generic_token(p, .Open_Brace, 1)
+ visit_expr(p, v.asm_string)
+ push_generic_token(p, .Comma, 0)
+ visit_expr(p, v.constraints_string)
+ push_generic_token(p, .Close_Brace, 0)
case Undef:
- push_generic_token(p, .Undef, 1);
+ push_generic_token(p, .Undef, 1)
case Auto_Cast:
- push_generic_token(p, v.op.kind, 1);
- visit_expr(p, v.expr);
+ push_generic_token(p, v.op.kind, 1)
+ visit_expr(p, v.expr)
case Ternary_If_Expr:
- visit_expr(p, v.x);
- push_generic_token(p, v.op1.kind, 1);
- visit_expr(p, v.cond);
- push_generic_token(p, v.op2.kind, 1);
- visit_expr(p, v.y);
+ visit_expr(p, v.x)
+ push_generic_token(p, v.op1.kind, 1)
+ visit_expr(p, v.cond)
+ push_generic_token(p, v.op2.kind, 1)
+ visit_expr(p, v.y)
case Ternary_When_Expr:
- visit_expr(p, v.x);
- push_generic_token(p, v.op1.kind, 1);
- visit_expr(p, v.cond);
- push_generic_token(p, v.op2.kind, 1);
- visit_expr(p, v.y);
+ visit_expr(p, v.x)
+ push_generic_token(p, v.op1.kind, 1)
+ visit_expr(p, v.cond)
+ push_generic_token(p, v.op2.kind, 1)
+ visit_expr(p, v.y)
case Or_Else_Expr:
- visit_expr(p, v.x);
- push_generic_token(p, v.token.kind, 1);
- visit_expr(p, v.y);
+ visit_expr(p, v.x)
+ push_generic_token(p, v.token.kind, 1)
+ visit_expr(p, v.y)
case Or_Return_Expr:
- visit_expr(p, v.expr);
- push_generic_token(p, v.token.kind, 1);
+ visit_expr(p, v.expr)
+ push_generic_token(p, v.token.kind, 1)
case Selector_Call_Expr:
- visit_expr(p, v.call.expr);
- push_generic_token(p, .Open_Paren, 1);
- visit_exprs(p, v.call.args, {.Add_Comma});
- push_generic_token(p, .Close_Paren, 0);
+ visit_expr(p, v.call.expr)
+ push_generic_token(p, .Open_Paren, 1)
+ visit_exprs(p, v.call.args, {.Add_Comma})
+ push_generic_token(p, .Close_Paren, 0)
case Ellipsis:
- push_generic_token(p, .Ellipsis, 1);
- visit_expr(p, v.expr);
+ push_generic_token(p, .Ellipsis, 1)
+ visit_expr(p, v.expr)
case Relative_Type:
- visit_expr(p, v.tag);
- visit_expr(p, v.type);
+ visit_expr(p, v.tag)
+ visit_expr(p, v.type)
case Slice_Expr:
- visit_expr(p, v.expr);
- push_generic_token(p, .Open_Bracket, 0);
- visit_expr(p, v.low);
- push_generic_token(p, v.interval.kind, 0);
+ visit_expr(p, v.expr)
+ push_generic_token(p, .Open_Bracket, 0)
+ visit_expr(p, v.low)
+ push_generic_token(p, v.interval.kind, 0)
if v.high != nil {
- merge_next_token(p);
- visit_expr(p, v.high);
+ merge_next_token(p)
+ visit_expr(p, v.high)
}
- push_generic_token(p, .Close_Bracket, 0);
+ push_generic_token(p, .Close_Bracket, 0)
case Ident:
if .Enforce_Poly_Names in options {
- push_generic_token(p, .Dollar, 1);
- push_ident_token(p, v.name, 0);
+ push_generic_token(p, .Dollar, 1)
+ push_ident_token(p, v.name, 0)
} else {
- push_ident_token(p, v.name, 1);
+ push_ident_token(p, v.name, 1)
}
case Deref_Expr:
- visit_expr(p, v.expr);
- push_generic_token(p, v.op.kind, 0);
+ visit_expr(p, v.expr)
+ push_generic_token(p, v.op.kind, 0)
case Type_Cast:
- push_generic_token(p, v.tok.kind, 1);
- push_generic_token(p, .Open_Paren, 0);
- visit_expr(p, v.type);
- push_generic_token(p, .Close_Paren, 0);
- merge_next_token(p);
- visit_expr(p, v.expr);
+ push_generic_token(p, v.tok.kind, 1)
+ push_generic_token(p, .Open_Paren, 0)
+ visit_expr(p, v.type)
+ push_generic_token(p, .Close_Paren, 0)
+ merge_next_token(p)
+ visit_expr(p, v.expr)
case Basic_Directive:
- push_generic_token(p, v.tok.kind, 1);
- push_ident_token(p, v.name, 0);
+ push_generic_token(p, v.tok.kind, 1)
+ push_ident_token(p, v.name, 0)
case Distinct_Type:
- push_generic_token(p, .Distinct, 1);
- visit_expr(p, v.type);
+ push_generic_token(p, .Distinct, 1)
+ visit_expr(p, v.type)
case Dynamic_Array_Type:
- visit_expr(p, v.tag);
- push_generic_token(p, .Open_Bracket, 1);
- push_generic_token(p, .Dynamic, 0);
- push_generic_token(p, .Close_Bracket, 0);
- merge_next_token(p);
- visit_expr(p, v.elem);
+ visit_expr(p, v.tag)
+ push_generic_token(p, .Open_Bracket, 1)
+ push_generic_token(p, .Dynamic, 0)
+ push_generic_token(p, .Close_Bracket, 0)
+ merge_next_token(p)
+ visit_expr(p, v.elem)
case Bit_Set_Type:
- push_generic_token(p, .Bit_Set, 1);
- push_generic_token(p, .Open_Bracket, 0);
+ push_generic_token(p, .Bit_Set, 1)
+ push_generic_token(p, .Open_Bracket, 0)
- visit_expr(p, v.elem);
+ visit_expr(p, v.elem)
if v.underlying != nil {
- push_generic_token(p, .Semicolon, 0);
- visit_expr(p, v.underlying);
+ push_generic_token(p, .Semicolon, 0)
+ visit_expr(p, v.underlying)
}
- push_generic_token(p, .Close_Bracket, 0);
+ push_generic_token(p, .Close_Bracket, 0)
case Union_Type:
- push_generic_token(p, .Union, 1);
+ push_generic_token(p, .Union, 1)
- push_poly_params(p, v.poly_params);
+ push_poly_params(p, v.poly_params)
if v.is_maybe {
- push_ident_token(p, "#maybe", 1);
+ push_ident_token(p, "#maybe", 1)
}
- push_where_clauses(p, v.where_clauses);
+ push_where_clauses(p, v.where_clauses)
if v.variants != nil && (len(v.variants) == 0 || v.pos.line == v.end.line) {
- push_generic_token(p, .Open_Brace, 1);
- visit_exprs(p, v.variants, {.Add_Comma});
- push_generic_token(p, .Close_Brace, 0);
+ push_generic_token(p, .Open_Brace, 1)
+ visit_exprs(p, v.variants, {.Add_Comma})
+ push_generic_token(p, .Close_Brace, 0)
} else {
- visit_begin_brace(p, v.pos, .Generic);
- newline_position(p, 1);
- set_source_position(p, v.variants[0].pos);
- visit_exprs(p, v.variants, {.Add_Comma, .Trailing});
- visit_end_brace(p, v.end);
+ visit_begin_brace(p, v.pos, .Generic)
+ newline_position(p, 1)
+ set_source_position(p, v.variants[0].pos)
+ visit_exprs(p, v.variants, {.Add_Comma, .Trailing})
+ visit_end_brace(p, v.end)
}
case Enum_Type:
- push_generic_token(p, .Enum, 1);
+ push_generic_token(p, .Enum, 1)
- hint_current_line(p, {.Enum});
+ hint_current_line(p, {.Enum})
if v.base_type != nil {
- visit_expr(p, v.base_type);
+ visit_expr(p, v.base_type)
}
if v.fields != nil && (len(v.fields) == 0 || v.pos.line == v.end.line) {
- push_generic_token(p, .Open_Brace, 1);
- visit_exprs(p, v.fields, {.Add_Comma});
- push_generic_token(p, .Close_Brace, 0);
+ push_generic_token(p, .Open_Brace, 1)
+ visit_exprs(p, v.fields, {.Add_Comma})
+ push_generic_token(p, .Close_Brace, 0)
} else {
- visit_begin_brace(p, v.pos, .Generic, len(v.fields));
- newline_position(p, 1);
- set_source_position(p, v.fields[0].pos);
- visit_exprs(p, v.fields, {.Add_Comma, .Trailing, .Enforce_Newline});
- set_source_position(p, v.end);
- visit_end_brace(p, v.end);
+ visit_begin_brace(p, v.pos, .Generic, len(v.fields))
+ newline_position(p, 1)
+ set_source_position(p, v.fields[0].pos)
+ visit_exprs(p, v.fields, {.Add_Comma, .Trailing, .Enforce_Newline})
+ set_source_position(p, v.end)
+ visit_end_brace(p, v.end)
}
- set_source_position(p, v.end);
+ set_source_position(p, v.end)
case Struct_Type:
- push_generic_token(p, .Struct, 1);
+ push_generic_token(p, .Struct, 1)
- hint_current_line(p, {.Struct});
+ hint_current_line(p, {.Struct})
- push_poly_params(p, v.poly_params);
+ push_poly_params(p, v.poly_params)
if v.is_packed {
- push_ident_token(p, "#packed", 1);
+ push_ident_token(p, "#packed", 1)
}
if v.is_raw_union {
- push_ident_token(p, "#raw_union", 1);
+ push_ident_token(p, "#raw_union", 1)
}
if v.align != nil {
- push_ident_token(p, "#align", 1);
- visit_expr(p, v.align);
+ push_ident_token(p, "#align", 1)
+ visit_expr(p, v.align)
}
- push_where_clauses(p, v.where_clauses);
+ push_where_clauses(p, v.where_clauses)
if v.fields != nil && (len(v.fields.list) == 0 || v.pos.line == v.end.line) {
- push_generic_token(p, .Open_Brace, 1);
- set_source_position(p, v.fields.pos);
- visit_field_list(p, v.fields, {.Add_Comma});
- push_generic_token(p, .Close_Brace, 0);
+ push_generic_token(p, .Open_Brace, 1)
+ set_source_position(p, v.fields.pos)
+ visit_field_list(p, v.fields, {.Add_Comma})
+ push_generic_token(p, .Close_Brace, 0)
} else if v.fields != nil {
- visit_begin_brace(p, v.pos, .Generic, len(v.fields.list));
- set_source_position(p, v.fields.pos);
- visit_field_list(p, v.fields, {.Add_Comma, .Trailing, .Enforce_Newline});
- visit_end_brace(p, v.end);
+ visit_begin_brace(p, v.pos, .Generic, len(v.fields.list))
+ set_source_position(p, v.fields.pos)
+ visit_field_list(p, v.fields, {.Add_Comma, .Trailing, .Enforce_Newline})
+ visit_end_brace(p, v.end)
}
- set_source_position(p, v.end);
+ set_source_position(p, v.end)
case Proc_Lit:
switch v.inlining {
case .None:
case .Inline:
- push_ident_token(p, "#force_inline", 0);
+ push_ident_token(p, "#force_inline", 0)
case .No_Inline:
- push_ident_token(p, "#force_no_inline", 0);
+ push_ident_token(p, "#force_no_inline", 0)
}
- visit_proc_type(p, v.type^, true);
+ visit_proc_type(p, v.type^, true)
- push_where_clauses(p, v.where_clauses);
+ push_where_clauses(p, v.where_clauses)
if v.body != nil {
- set_source_position(p, v.body.pos);
- visit_stmt(p, v.body, .Proc);
+ set_source_position(p, v.body.pos)
+ visit_stmt(p, v.body, .Proc)
} else {
- push_generic_token(p, .Undef, 1);
+ push_generic_token(p, .Undef, 1)
}
case Proc_Type:
- visit_proc_type(p, v);
+ visit_proc_type(p, v)
case Basic_Lit:
- push_generic_token(p, v.tok.kind, 1, v.tok.text);
+ push_generic_token(p, v.tok.kind, 1, v.tok.text)
case Binary_Expr:
- visit_binary_expr(p, v);
+ visit_binary_expr(p, v)
case Implicit_Selector_Expr:
- push_generic_token(p, .Period, 1);
- push_ident_token(p, v.field.name, 0);
+ push_generic_token(p, .Period, 1)
+ push_ident_token(p, v.field.name, 0)
case Call_Expr:
- visit_expr(p, v.expr);
+ visit_expr(p, v.expr)
push_format_token(p,
Format_Token {
@@ -1143,159 +1143,159 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, options := List_Options{}) { type = .Call,
text = "(",
},
- );
+ )
- hint_current_line(p, {.Call});
+ hint_current_line(p, {.Call})
- visit_call_exprs(p, v.args, v.ellipsis.kind == .Ellipsis);
- push_generic_token(p, .Close_Paren, 0);
+ visit_call_exprs(p, v.args, v.ellipsis.kind == .Ellipsis)
+ push_generic_token(p, .Close_Paren, 0)
case Typeid_Type:
- push_generic_token(p, .Typeid, 1);
+ push_generic_token(p, .Typeid, 1)
if v.specialization != nil {
- push_generic_token(p, .Quo, 0);
- visit_expr(p, v.specialization);
+ push_generic_token(p, .Quo, 0)
+ visit_expr(p, v.specialization)
}
case Selector_Expr:
- visit_expr(p, v.expr);
- push_generic_token(p, v.op.kind, 0);
- visit_expr(p, v.field);
+ visit_expr(p, v.expr)
+ push_generic_token(p, v.op.kind, 0)
+ visit_expr(p, v.field)
case Paren_Expr:
- push_generic_token(p, .Open_Paren, 1);
- visit_expr(p, v.expr);
- push_generic_token(p, .Close_Paren, 0);
+ push_generic_token(p, .Open_Paren, 1)
+ visit_expr(p, v.expr)
+ push_generic_token(p, .Close_Paren, 0)
case Index_Expr:
- visit_expr(p, v.expr);
- push_generic_token(p, .Open_Bracket, 0);
- visit_expr(p, v.index);
- push_generic_token(p, .Close_Bracket, 0);
+ visit_expr(p, v.expr)
+ push_generic_token(p, .Open_Bracket, 0)
+ visit_expr(p, v.index)
+ push_generic_token(p, .Close_Bracket, 0)
case Proc_Group:
- push_generic_token(p, v.tok.kind, 1);
+ push_generic_token(p, v.tok.kind, 1)
if len(v.args) != 0 && v.pos.line != v.args[len(v.args) - 1].pos.line {
- visit_begin_brace(p, v.pos, .Generic);
- newline_position(p, 1);
- set_source_position(p, v.args[0].pos);
- visit_exprs(p, v.args, {.Add_Comma, .Trailing});
- visit_end_brace(p, v.end);
+ visit_begin_brace(p, v.pos, .Generic)
+ newline_position(p, 1)
+ set_source_position(p, v.args[0].pos)
+ visit_exprs(p, v.args, {.Add_Comma, .Trailing})
+ visit_end_brace(p, v.end)
} else {
- push_generic_token(p, .Open_Brace, 0);
- visit_exprs(p, v.args, {.Add_Comma});
- push_generic_token(p, .Close_Brace, 0);
+ push_generic_token(p, .Open_Brace, 0)
+ visit_exprs(p, v.args, {.Add_Comma})
+ push_generic_token(p, .Close_Brace, 0)
}
case Comp_Lit:
if v.type != nil {
- visit_expr(p, v.type);
+ visit_expr(p, v.type)
}
if len(v.elems) != 0 && v.pos.line != v.elems[len(v.elems) - 1].pos.line {
- visit_begin_brace(p, v.pos, .Comp_Lit, 0);
- newline_position(p, 1);
- set_source_position(p, v.elems[0].pos);
- visit_exprs(p, v.elems, {.Add_Comma, .Trailing});
- visit_end_brace(p, v.end);
+ visit_begin_brace(p, v.pos, .Comp_Lit, 0)
+ newline_position(p, 1)
+ set_source_position(p, v.elems[0].pos)
+ visit_exprs(p, v.elems, {.Add_Comma, .Trailing})
+ visit_end_brace(p, v.end)
} else {
- push_generic_token(p, .Open_Brace, 0 if v.type != nil else 1);
- visit_exprs(p, v.elems, {.Add_Comma});
- push_generic_token(p, .Close_Brace, 0);
+ push_generic_token(p, .Open_Brace, 0 if v.type != nil else 1)
+ visit_exprs(p, v.elems, {.Add_Comma})
+ push_generic_token(p, .Close_Brace, 0)
}
case Unary_Expr:
- push_generic_token(p, v.op.kind, 1);
- merge_next_token(p);
- visit_expr(p, v.expr);
+ push_generic_token(p, v.op.kind, 1)
+ merge_next_token(p)
+ visit_expr(p, v.expr)
case Field_Value:
- visit_expr(p, v.field);
- push_generic_token(p, .Eq, 1);
- visit_expr(p, v.value);
+ visit_expr(p, v.field)
+ push_generic_token(p, .Eq, 1)
+ visit_expr(p, v.value)
case Type_Assertion:
- visit_expr(p, v.expr);
+ visit_expr(p, v.expr)
if unary, ok := v.type.derived.(Unary_Expr); ok && unary.op.text == "?" {
- push_generic_token(p, .Period, 0);
- visit_expr(p, v.type);
+ push_generic_token(p, .Period, 0)
+ visit_expr(p, v.type)
} else {
- push_generic_token(p, .Period, 0);
- push_generic_token(p, .Open_Paren, 0);
- visit_expr(p, v.type);
- push_generic_token(p, .Close_Paren, 0);
+ push_generic_token(p, .Period, 0)
+ push_generic_token(p, .Open_Paren, 0)
+ visit_expr(p, v.type)
+ push_generic_token(p, .Close_Paren, 0)
}
case Pointer_Type:
- push_generic_token(p, .Pointer, 1);
- merge_next_token(p);
- visit_expr(p, v.elem);
+ push_generic_token(p, .Pointer, 1)
+ merge_next_token(p)
+ visit_expr(p, v.elem)
case Implicit:
- push_generic_token(p, v.tok.kind, 1);
+ push_generic_token(p, v.tok.kind, 1)
case Poly_Type:
- push_generic_token(p, .Dollar, 1);
- merge_next_token(p);
- visit_expr(p, v.type);
+ push_generic_token(p, .Dollar, 1)
+ merge_next_token(p)
+ visit_expr(p, v.type)
if v.specialization != nil {
- push_generic_token(p, .Quo, 0);
- merge_next_token(p);
- visit_expr(p, v.specialization);
+ push_generic_token(p, .Quo, 0)
+ merge_next_token(p)
+ visit_expr(p, v.specialization)
}
case Array_Type:
- visit_expr(p, v.tag);
- push_generic_token(p, .Open_Bracket, 1);
- visit_expr(p, v.len);
- push_generic_token(p, .Close_Bracket, 0);
- merge_next_token(p);
- visit_expr(p, v.elem);
+ visit_expr(p, v.tag)
+ push_generic_token(p, .Open_Bracket, 1)
+ visit_expr(p, v.len)
+ push_generic_token(p, .Close_Bracket, 0)
+ merge_next_token(p)
+ visit_expr(p, v.elem)
case Map_Type:
- push_generic_token(p, .Map, 1);
- push_generic_token(p, .Open_Bracket, 0);
- visit_expr(p, v.key);
- push_generic_token(p, .Close_Bracket, 0);
- merge_next_token(p);
- visit_expr(p, v.value);
+ push_generic_token(p, .Map, 1)
+ push_generic_token(p, .Open_Bracket, 0)
+ visit_expr(p, v.key)
+ push_generic_token(p, .Close_Bracket, 0)
+ merge_next_token(p)
+ visit_expr(p, v.value)
case Helper_Type:
- visit_expr(p, v.type);
+ visit_expr(p, v.type)
case:
- panic(fmt.aprint(expr.derived));
+ panic(fmt.aprint(expr.derived))
}
}
visit_begin_brace :: proc(p: ^Printer, begin: tokenizer.Pos, type: Block_Type, count := 0, same_line_spaces_before := 1) {
- set_source_position(p, begin);
+ set_source_position(p, begin)
- newline_braced := p.config.brace_style == .Allman;
- newline_braced |= p.config.brace_style == .K_And_R && type == .Proc;
- newline_braced &= p.config.brace_style != ._1TBS;
+ newline_braced := p.config.brace_style == .Allman
+ newline_braced |= p.config.brace_style == .K_And_R && type == .Proc
+ newline_braced &= p.config.brace_style != ._1TBS
format_token := Format_Token {
kind = .Open_Brace,
parameter_count = count,
text = "{",
- };
+ }
if newline_braced {
- newline_position(p, 1);
- push_format_token(p, format_token);
- indent(p);
+ newline_position(p, 1)
+ push_format_token(p, format_token)
+ indent(p)
} else {
- format_token.spaces_before = same_line_spaces_before;
- push_format_token(p, format_token);
- indent(p);
+ format_token.spaces_before = same_line_spaces_before
+ push_format_token(p, format_token)
+ indent(p)
}
}
visit_end_brace :: proc(p: ^Printer, end: tokenizer.Pos) {
- move_line(p, end);
- push_generic_token(p, .Close_Brace, 0);
- unindent(p);
- p.current_line.depth = p.depth;
+ move_line(p, end)
+ push_generic_token(p, .Close_Brace, 0)
+ unindent(p)
+ p.current_line.depth = p.depth
}
visit_block_stmts :: proc(p: ^Printer, stmts: []^ast.Stmt, split := false) {
for stmt, i in stmts {
- visit_stmt(p, stmt, .Generic, false, true);
+ visit_stmt(p, stmt, .Generic, false, true)
if split && i != len(stmts) - 1 && stmt.pos.line == stmts[i + 1].pos.line {
- newline_position(p, 1);
+ newline_position(p, 1)
}
}
}
@@ -1307,46 +1307,46 @@ List_Option :: enum u8 { Enforce_Poly_Names,
}
-List_Options :: distinct bit_set[List_Option];
+List_Options :: distinct bit_set[List_Option]
visit_field_list :: proc(p: ^Printer, list: ^ast.Field_List, options := List_Options{}) {
if list.list == nil {
- return;
+ return
}
for field, i in list.list {
if !move_line_limit(p, field.pos, 1) && .Enforce_Newline in options {
- newline_position(p, 1);
+ newline_position(p, 1)
}
if .Using in field.flags {
- push_generic_token(p, .Using, 1);
+ push_generic_token(p, .Using, 1)
}
- name_options := List_Options{.Add_Comma};
+ name_options := List_Options{.Add_Comma}
if .Enforce_Poly_Names in options {
- name_options += {.Enforce_Poly_Names};
+ name_options += {.Enforce_Poly_Names}
}
- visit_exprs(p, field.names, name_options);
+ visit_exprs(p, field.names, name_options)
if field.type != nil {
if len(field.names) != 0 {
- push_generic_token(p, .Colon, 0);
+ push_generic_token(p, .Colon, 0)
}
- visit_expr(p, field.type);
+ visit_expr(p, field.type)
} else {
- push_generic_token(p, .Colon, 1);
- push_generic_token(p, .Eq, 0);
- visit_expr(p, field.default_value);
+ push_generic_token(p, .Colon, 1)
+ push_generic_token(p, .Eq, 0)
+ visit_expr(p, field.default_value)
}
if field.tag.text != "" {
- push_generic_token(p, field.tag.kind, 1, field.tag.text);
+ push_generic_token(p, field.tag.kind, 1, field.tag.text)
}
if (i != len(list.list) - 1 || .Trailing in options) && .Add_Comma in options {
- push_generic_token(p, .Comma, 0);
+ push_generic_token(p, .Comma, 0)
}
}
}
@@ -1358,129 +1358,129 @@ visit_proc_type :: proc(p: ^Printer, proc_type: ast.Proc_Type, is_proc_lit := fa type = .Proc_Lit,
text = "proc",
spaces_before = 1,
- });
+ })
} else {
push_format_token(p, Format_Token {
kind = .Proc,
text = "proc",
spaces_before = 1,
- });
+ })
}
- explicit_calling := false;
+ explicit_calling := false
if v, ok := proc_type.calling_convention.(string); ok {
- explicit_calling = true;
- push_string_token(p, v, 1);
+ explicit_calling = true
+ push_string_token(p, v, 1)
}
if explicit_calling {
- push_generic_token(p, .Open_Paren, 1);
+ push_generic_token(p, .Open_Paren, 1)
} else {
- push_generic_token(p, .Open_Paren, 0);
+ push_generic_token(p, .Open_Paren, 0)
}
- visit_signature_list(p, proc_type.params, false);
+ visit_signature_list(p, proc_type.params, false)
- push_generic_token(p, .Close_Paren, 0);
+ push_generic_token(p, .Close_Paren, 0)
if proc_type.results != nil {
- push_generic_token(p, .Sub, 1);
- push_generic_token(p, .Gt, 0);
+ push_generic_token(p, .Sub, 1)
+ push_generic_token(p, .Gt, 0)
- use_parens := false;
- use_named := false;
+ use_parens := false
+ use_named := false
if len(proc_type.results.list) > 1 {
- use_parens = true;
+ use_parens = true
} else if len(proc_type.results.list) == 1 {
for name in proc_type.results.list[0].names {
if ident, ok := name.derived.(ast.Ident); ok {
if ident.name != "_" {
- use_parens = true;
+ use_parens = true
}
}
}
}
if use_parens {
- push_generic_token(p, .Open_Paren, 1);
- visit_signature_list(p, proc_type.results);
- push_generic_token(p, .Close_Paren, 0);
+ push_generic_token(p, .Open_Paren, 1)
+ visit_signature_list(p, proc_type.results)
+ push_generic_token(p, .Close_Paren, 0)
} else {
- visit_signature_list(p, proc_type.results);
+ visit_signature_list(p, proc_type.results)
}
}
}
visit_binary_expr :: proc(p: ^Printer, binary: ast.Binary_Expr) {
- move_line(p, binary.left.pos);
+ move_line(p, binary.left.pos)
if v, ok := binary.left.derived.(ast.Binary_Expr); ok {
- visit_binary_expr(p, v);
+ visit_binary_expr(p, v)
} else {
- visit_expr(p, binary.left);
+ visit_expr(p, binary.left)
}
- either_implicit_selector := false;
+ either_implicit_selector := false
if _, ok := binary.left.derived.(ast.Implicit_Selector_Expr); ok {
- either_implicit_selector = true;
+ either_implicit_selector = true
} else if _, ok := binary.right.derived.(ast.Implicit_Selector_Expr); ok {
- either_implicit_selector = true;
+ either_implicit_selector = true
}
#partial switch binary.op.kind {
case .Ellipsis:
push_generic_token(p, binary.op.kind, 1 if either_implicit_selector else 0,
- tokenizer.tokens[tokenizer.Token_Kind.Range_Full]);
+ tokenizer.tokens[tokenizer.Token_Kind.Range_Full])
case .Range_Half, .Range_Full:
- push_generic_token(p, binary.op.kind, 1 if either_implicit_selector else 0);
+ push_generic_token(p, binary.op.kind, 1 if either_implicit_selector else 0)
case:
- push_generic_token(p, binary.op.kind, 1);
+ push_generic_token(p, binary.op.kind, 1)
}
- move_line(p, binary.right.pos);
+ move_line(p, binary.right.pos)
if v, ok := binary.right.derived.(ast.Binary_Expr); ok {
- visit_binary_expr(p, v);
+ visit_binary_expr(p, v)
} else {
- visit_expr(p, binary.right);
+ visit_expr(p, binary.right)
}
}
visit_call_exprs :: proc(p: ^Printer, list: []^ast.Expr, ellipsis := false) {
if len(list) == 0 {
- return;
+ return
}
// all the expression are on the line
if list[0].pos.line == list[len(list) - 1].pos.line {
for expr, i in list {
if i == len(list) - 1 && ellipsis {
- push_generic_token(p, .Ellipsis, 0);
+ push_generic_token(p, .Ellipsis, 0)
}
- visit_expr(p, expr);
+ visit_expr(p, expr)
if i != len(list) - 1 {
- push_generic_token(p, .Comma, 0);
+ push_generic_token(p, .Comma, 0)
}
}
} else {
for expr, i in list {
// we have to newline the expressions to respect the source
- move_line_limit(p, expr.pos, 1);
+ move_line_limit(p, expr.pos, 1)
if i == len(list) - 1 && ellipsis {
- push_generic_token(p, .Ellipsis, 0);
+ push_generic_token(p, .Ellipsis, 0)
}
- visit_expr(p, expr);
+ visit_expr(p, expr)
if i != len(list) - 1 {
- push_generic_token(p, .Comma, 0);
+ push_generic_token(p, .Comma, 0)
}
}
}
@@ -1488,54 +1488,54 @@ visit_call_exprs :: proc(p: ^Printer, list: []^ast.Expr, ellipsis := false) { visit_signature_list :: proc(p: ^Printer, list: ^ast.Field_List, remove_blank := true) {
if list.list == nil {
- return;
+ return
}
for field, i in list.list {
if i != 0 {
- move_line_limit(p, field.pos, 1);
+ move_line_limit(p, field.pos, 1)
}
if .Using in field.flags {
- push_generic_token(p, .Using, 0);
+ push_generic_token(p, .Using, 0)
}
- named := false;
+ named := false
for name in field.names {
if ident, ok := name.derived.(ast.Ident); ok {
//for some reason the parser uses _ to mean empty
if ident.name != "_" || !remove_blank {
- named = true;
+ named = true
}
} else {
//alternative is poly names
- named = true;
+ named = true
}
}
if named {
- visit_exprs(p, field.names, {.Add_Comma});
+ visit_exprs(p, field.names, {.Add_Comma})
if len(field.names) != 0 && field.type != nil {
- push_generic_token(p, .Colon, 0);
+ push_generic_token(p, .Colon, 0)
}
}
if field.type != nil && field.default_value != nil {
- visit_expr(p, field.type);
- push_generic_token(p, .Eq, 1);
- visit_expr(p, field.default_value);
+ visit_expr(p, field.type)
+ push_generic_token(p, .Eq, 1)
+ visit_expr(p, field.default_value)
} else if field.type != nil {
- visit_expr(p, field.type);
+ visit_expr(p, field.type)
} else {
- push_generic_token(p, .Colon, 1);
- push_generic_token(p, .Eq, 0);
- visit_expr(p, field.default_value);
+ push_generic_token(p, .Colon, 1)
+ push_generic_token(p, .Eq, 0)
+ visit_expr(p, field.default_value)
}
if i != len(list.list) - 1 {
- push_generic_token(p, .Comma, 0);
+ push_generic_token(p, .Comma, 0)
}
}
}
diff --git a/core/odin/tokenizer/token.odin b/core/odin/tokenizer/token.odin index 5283ab590..13ac0e177 100644 --- a/core/odin/tokenizer/token.odin +++ b/core/odin/tokenizer/token.odin @@ -17,15 +17,15 @@ Pos :: struct { pos_compare :: proc(lhs, rhs: Pos) -> int { if lhs.offset != rhs.offset { - return -1 if (lhs.offset < rhs.offset) else +1; + return -1 if (lhs.offset < rhs.offset) else +1 } if lhs.line != rhs.line { - return -1 if (lhs.line < rhs.line) else +1; + return -1 if (lhs.line < rhs.line) else +1 } if lhs.column != rhs.column { - return -1 if (lhs.column < rhs.column) else +1; + return -1 if (lhs.column < rhs.column) else +1 } - return strings.compare(lhs.file, rhs.file); + return strings.compare(lhs.file, rhs.file) } Token_Kind :: enum u32 { @@ -156,7 +156,7 @@ Token_Kind :: enum u32 { B_Custom_Keyword_Begin = COUNT+1, // ... Custom keywords -}; +} tokens := [Token_Kind.COUNT]string { "Invalid", @@ -281,60 +281,60 @@ tokens := [Token_Kind.COUNT]string { "inline", "no_inline", "", -}; +} -custom_keyword_tokens: []string; +custom_keyword_tokens: []string is_newline :: proc(tok: Token) -> bool { - return tok.kind == .Semicolon && tok.text == "\n"; + return tok.kind == .Semicolon && tok.text == "\n" } token_to_string :: proc(tok: Token) -> string { if is_newline(tok) { - return "newline"; + return "newline" } - return to_string(tok.kind); + return to_string(tok.kind) } to_string :: proc(kind: Token_Kind) -> string { if Token_Kind.Invalid <= kind && kind < Token_Kind.COUNT { - return tokens[kind]; + return tokens[kind] } if Token_Kind.B_Custom_Keyword_Begin < kind { - n := int(u16(kind)-u16(Token_Kind.B_Custom_Keyword_Begin)); + n := int(u16(kind)-u16(Token_Kind.B_Custom_Keyword_Begin)) if n < len(custom_keyword_tokens) { - return custom_keyword_tokens[n]; + return custom_keyword_tokens[n] } } - return "Invalid"; + return "Invalid" } is_literal :: proc(kind: Token_Kind) -> bool { - return Token_Kind.B_Literal_Begin < kind && kind < Token_Kind.B_Literal_End; + return Token_Kind.B_Literal_Begin < kind && kind < Token_Kind.B_Literal_End } is_operator :: proc(kind: Token_Kind) -> bool { #partial switch kind { case .B_Operator_Begin .. .B_Operator_End: - return true; + return true case .In, .Not_In: - return true; + return true case .If: - return true; + return true } - return false; + return false } is_assignment_operator :: proc(kind: Token_Kind) -> bool { - return Token_Kind.B_Assign_Op_Begin < kind && kind < Token_Kind.B_Assign_Op_End || kind == Token_Kind.Eq; + return Token_Kind.B_Assign_Op_Begin < kind && kind < Token_Kind.B_Assign_Op_End || kind == Token_Kind.Eq } is_keyword :: proc(kind: Token_Kind) -> bool { switch { case Token_Kind.B_Keyword_Begin < kind && kind < Token_Kind.B_Keyword_End: - return true; + return true case Token_Kind.B_Custom_Keyword_Begin < kind: - return true; + return true } - return false; + return false } diff --git a/core/odin/tokenizer/tokenizer.odin b/core/odin/tokenizer/tokenizer.odin index 5d69cf3a9..dde59ff30 100644 --- a/core/odin/tokenizer/tokenizer.odin +++ b/core/odin/tokenizer/tokenizer.odin @@ -4,12 +4,12 @@ import "core:fmt" import "core:unicode" import "core:unicode/utf8" -Error_Handler :: #type proc(pos: Pos, fmt: string, args: ..any); +Error_Handler :: #type proc(pos: Pos, fmt: string, args: ..any) Flag :: enum { Insert_Semicolon, } -Flags :: distinct bit_set[Flag; u32]; +Flags :: distinct bit_set[Flag; u32] Tokenizer :: struct { // Immutable data @@ -32,85 +32,85 @@ Tokenizer :: struct { } init :: proc(t: ^Tokenizer, src: string, path: string, err: Error_Handler = default_error_handler) { - t.src = src; - t.err = err; - t.ch = ' '; - t.offset = 0; - t.read_offset = 0; - t.line_offset = 0; - t.line_count = len(src) > 0 ? 1 : 0; - t.error_count = 0; - t.path = path; - - advance_rune(t); + t.src = src + t.err = err + t.ch = ' ' + t.offset = 0 + t.read_offset = 0 + t.line_offset = 0 + t.line_count = len(src) > 0 ? 1 : 0 + t.error_count = 0 + t.path = path + + advance_rune(t) if t.ch == utf8.RUNE_BOM { - advance_rune(t); + advance_rune(t) } } @(private) offset_to_pos :: proc(t: ^Tokenizer, offset: int) -> Pos { - line := t.line_count; - column := offset - t.line_offset + 1; + line := t.line_count + column := offset - t.line_offset + 1 return Pos { file = t.path, offset = offset, line = line, column = column, - }; + } } default_error_handler :: proc(pos: Pos, msg: string, args: ..any) { - fmt.eprintf("%s(%d:%d) ", pos.file, pos.line, pos.column); - fmt.eprintf(msg, ..args); - fmt.eprintf("\n"); + fmt.eprintf("%s(%d:%d) ", pos.file, pos.line, pos.column) + fmt.eprintf(msg, ..args) + fmt.eprintf("\n") } error :: proc(t: ^Tokenizer, offset: int, msg: string, args: ..any) { - pos := offset_to_pos(t, offset); + pos := offset_to_pos(t, offset) if t.err != nil { - t.err(pos, msg, ..args); + t.err(pos, msg, ..args) } - t.error_count += 1; + t.error_count += 1 } advance_rune :: proc(using t: ^Tokenizer) { if read_offset < len(src) { - offset = read_offset; + offset = read_offset if ch == '\n' { - line_offset = offset; - line_count += 1; + line_offset = offset + line_count += 1 } - r, w := rune(src[read_offset]), 1; + r, w := rune(src[read_offset]), 1 switch { case r == 0: - error(t, t.offset, "illegal character NUL"); + error(t, t.offset, "illegal character NUL") case r >= utf8.RUNE_SELF: - r, w = utf8.decode_rune_in_string(src[read_offset:]); + r, w = utf8.decode_rune_in_string(src[read_offset:]) if r == utf8.RUNE_ERROR && w == 1 { - error(t, t.offset, "illegal UTF-8 encoding"); + error(t, t.offset, "illegal UTF-8 encoding") } else if r == utf8.RUNE_BOM && offset > 0 { - error(t, t.offset, "illegal byte order mark"); + error(t, t.offset, "illegal byte order mark") } } - read_offset += w; - ch = r; + read_offset += w + ch = r } else { - offset = len(src); + offset = len(src) if ch == '\n' { - line_offset = offset; - line_count += 1; + line_offset = offset + line_count += 1 } - ch = -1; + ch = -1 } } peek_byte :: proc(t: ^Tokenizer, offset := 0) -> byte { if t.read_offset+offset < len(t.src) { - return t.src[t.read_offset+offset]; + return t.src[t.read_offset+offset] } - return 0; + return 0 } skip_whitespace :: proc(t: ^Tokenizer) { @@ -118,18 +118,18 @@ skip_whitespace :: proc(t: ^Tokenizer) { for { switch t.ch { case ' ', '\t', '\r': - advance_rune(t); + advance_rune(t) case: - return; + return } } } else { for { switch t.ch { case ' ', '\t', '\r', '\n': - advance_rune(t); + advance_rune(t) case: - return; + return } } } @@ -139,581 +139,581 @@ is_letter :: proc(r: rune) -> bool { if r < utf8.RUNE_SELF { switch r { case '_': - return true; + return true case 'A'..='Z', 'a'..='z': - return true; + return true } } - return unicode.is_letter(r); + return unicode.is_letter(r) } is_digit :: proc(r: rune) -> bool { if '0' <= r && r <= '9' { - return true; + return true } - return unicode.is_digit(r); + return unicode.is_digit(r) } scan_comment :: proc(t: ^Tokenizer) -> string { - offset := t.offset-1; - next := -1; + offset := t.offset-1 + next := -1 general: { if t.ch == '/' || t.ch == '!' { // // #! comments - advance_rune(t); + advance_rune(t) for t.ch != '\n' && t.ch >= 0 { - advance_rune(t); + advance_rune(t) } - next = t.offset; + next = t.offset if t.ch == '\n' { - next += 1; + next += 1 } - break general; + break general } /* style comment */ - advance_rune(t); - nest := 1; + advance_rune(t) + nest := 1 for t.ch >= 0 && nest > 0 { - ch := t.ch; - advance_rune(t); + ch := t.ch + advance_rune(t) if ch == '/' && t.ch == '*' { - nest += 1; + nest += 1 } if ch == '*' && t.ch == '/' { - nest -= 1; - advance_rune(t); - next = t.offset; + nest -= 1 + advance_rune(t) + next = t.offset if nest == 0 { - break general; + break general } } } - error(t, offset, "comment not terminated"); + error(t, offset, "comment not terminated") } - lit := t.src[offset : t.offset]; + lit := t.src[offset : t.offset] // NOTE(bill): Strip CR for line comments for len(lit) > 2 && lit[1] == '/' && lit[len(lit)-1] == '\r' { - lit = lit[:len(lit)-1]; + lit = lit[:len(lit)-1] } - return string(lit); + return string(lit) } scan_identifier :: proc(t: ^Tokenizer) -> string { - offset := t.offset; + offset := t.offset for is_letter(t.ch) || is_digit(t.ch) { - advance_rune(t); + advance_rune(t) } - return string(t.src[offset : t.offset]); + return string(t.src[offset : t.offset]) } scan_string :: proc(t: ^Tokenizer) -> string { - offset := t.offset-1; + offset := t.offset-1 for { - ch := t.ch; + ch := t.ch if ch == '\n' || ch < 0 { - error(t, offset, "string literal was not terminated"); - break; + error(t, offset, "string literal was not terminated") + break } - advance_rune(t); + advance_rune(t) if ch == '"' { - break; + break } if ch == '\\' { - scan_escape(t); + scan_escape(t) } } - return string(t.src[offset : t.offset]); + return string(t.src[offset : t.offset]) } scan_raw_string :: proc(t: ^Tokenizer) -> string { - offset := t.offset-1; + offset := t.offset-1 for { - ch := t.ch; + ch := t.ch if ch == utf8.RUNE_EOF { - error(t, offset, "raw string literal was not terminated"); - break; + error(t, offset, "raw string literal was not terminated") + break } - advance_rune(t); + advance_rune(t) if ch == '`' { - break; + break } } - return string(t.src[offset : t.offset]); + return string(t.src[offset : t.offset]) } digit_val :: proc(r: rune) -> int { switch r { case '0'..='9': - return int(r-'0'); + return int(r-'0') case 'A'..='F': - return int(r-'A' + 10); + return int(r-'A' + 10) case 'a'..='f': - return int(r-'a' + 10); + return int(r-'a' + 10) } - return 16; + return 16 } scan_escape :: proc(t: ^Tokenizer) -> bool { - offset := t.offset; + offset := t.offset - n: int; - base, max: u32; + n: int + base, max: u32 switch t.ch { case 'a', 'b', 'e', 'f', 'n', 't', 'v', 'r', '\\', '\'', '\"': - advance_rune(t); - return true; + advance_rune(t) + return true case '0'..='7': - n, base, max = 3, 8, 255; + n, base, max = 3, 8, 255 case 'x': - advance_rune(t); - n, base, max = 2, 16, 255; + advance_rune(t) + n, base, max = 2, 16, 255 case 'u': - advance_rune(t); - n, base, max = 4, 16, utf8.MAX_RUNE; + advance_rune(t) + n, base, max = 4, 16, utf8.MAX_RUNE case 'U': - advance_rune(t); - n, base, max = 8, 16, utf8.MAX_RUNE; + advance_rune(t) + n, base, max = 8, 16, utf8.MAX_RUNE case: if t.ch < 0 { - error(t, offset, "escape sequence was not terminated"); + error(t, offset, "escape sequence was not terminated") } else { - error(t, offset, "unknown escape sequence"); + error(t, offset, "unknown escape sequence") } - return false; + return false } - x: u32; + x: u32 for n > 0 { - d := u32(digit_val(t.ch)); + d := u32(digit_val(t.ch)) for d >= base { if t.ch < 0 { - error(t, t.offset, "escape sequence was not terminated"); + error(t, t.offset, "escape sequence was not terminated") } else { - error(t, t.offset, "illegal character %d in escape sequence", t.ch); + error(t, t.offset, "illegal character %d in escape sequence", t.ch) } - return false; + return false } - x = x*base + d; - advance_rune(t); - n -= 1; + x = x*base + d + advance_rune(t) + n -= 1 } if x > max || 0xd800 <= x && x <= 0xe000 { - error(t, offset, "escape sequence is an invalid Unicode code point"); - return false; + error(t, offset, "escape sequence is an invalid Unicode code point") + return false } - return true; + return true } scan_rune :: proc(t: ^Tokenizer) -> string { - offset := t.offset-1; - valid := true; - n := 0; + offset := t.offset-1 + valid := true + n := 0 for { - ch := t.ch; + ch := t.ch if ch == '\n' || ch < 0 { if valid { - error(t, offset, "rune literal not terminated"); - valid = false; + error(t, offset, "rune literal not terminated") + valid = false } - break; + break } - advance_rune(t); + advance_rune(t) if ch == '\'' { - break; + break } - n += 1; + n += 1 if ch == '\\' { if !scan_escape(t) { - valid = false; + valid = false } } } if valid && n != 1 { - error(t, offset, "illegal rune literal"); + error(t, offset, "illegal rune literal") } - return string(t.src[offset : t.offset]); + return string(t.src[offset : t.offset]) } scan_number :: proc(t: ^Tokenizer, seen_decimal_point: bool) -> (Token_Kind, string) { scan_mantissa :: proc(t: ^Tokenizer, base: int) { for digit_val(t.ch) < base || t.ch == '_' { - advance_rune(t); + advance_rune(t) } } scan_exponent :: proc(t: ^Tokenizer, kind: ^Token_Kind) { if t.ch == 'e' || t.ch == 'E' { - kind^ = .Float; - advance_rune(t); + kind^ = .Float + advance_rune(t) if t.ch == '-' || t.ch == '+' { - advance_rune(t); + advance_rune(t) } if digit_val(t.ch) < 10 { - scan_mantissa(t, 10); + scan_mantissa(t, 10) } else { - error(t, t.offset, "illegal floating-point exponent"); + error(t, t.offset, "illegal floating-point exponent") } } // NOTE(bill): This needs to be here for sanity's sake switch t.ch { case 'i', 'j', 'k': - kind^ = .Imag; - advance_rune(t); + kind^ = .Imag + advance_rune(t) } } scan_fraction :: proc(t: ^Tokenizer, kind: ^Token_Kind) -> (early_exit: bool) { if t.ch == '.' && peek_byte(t) == '.' { - return true; + return true } if t.ch == '.' { - kind^ = .Float; - advance_rune(t); - scan_mantissa(t, 10); + kind^ = .Float + advance_rune(t) + scan_mantissa(t, 10) } - return false; + return false } - offset := t.offset; - kind := Token_Kind.Integer; - seen_point := seen_decimal_point; + offset := t.offset + kind := Token_Kind.Integer + seen_point := seen_decimal_point if seen_point { - offset -= 1; - kind = .Float; - scan_mantissa(t, 10); - scan_exponent(t, &kind); + offset -= 1 + kind = .Float + scan_mantissa(t, 10) + scan_exponent(t, &kind) } else { if t.ch == '0' { int_base :: proc(t: ^Tokenizer, kind: ^Token_Kind, base: int, msg: string) { - prev := t.offset; - advance_rune(t); - scan_mantissa(t, base); + prev := t.offset + advance_rune(t) + scan_mantissa(t, base) if t.offset - prev <= 1 { - kind^ = .Invalid; - error(t, t.offset, msg); + kind^ = .Invalid + error(t, t.offset, msg) } } - advance_rune(t); + advance_rune(t) switch t.ch { - case 'b': int_base(t, &kind, 2, "illegal binary integer"); - case 'o': int_base(t, &kind, 8, "illegal octal integer"); - case 'd': int_base(t, &kind, 10, "illegal decimal integer"); - case 'z': int_base(t, &kind, 12, "illegal dozenal integer"); - case 'x': int_base(t, &kind, 16, "illegal hexadecimal integer"); + case 'b': int_base(t, &kind, 2, "illegal binary integer") + case 'o': int_base(t, &kind, 8, "illegal octal integer") + case 'd': int_base(t, &kind, 10, "illegal decimal integer") + case 'z': int_base(t, &kind, 12, "illegal dozenal integer") + case 'x': int_base(t, &kind, 16, "illegal hexadecimal integer") case 'h': - prev := t.offset; - advance_rune(t); - scan_mantissa(t, 16); + prev := t.offset + advance_rune(t) + scan_mantissa(t, 16) if t.offset - prev <= 1 { - kind = .Invalid; - error(t, t.offset, "illegal hexadecimal floating-point number"); + kind = .Invalid + error(t, t.offset, "illegal hexadecimal floating-point number") } else { - sub := t.src[prev+1 : t.offset]; - digit_count := 0; + sub := t.src[prev+1 : t.offset] + digit_count := 0 for d in sub { if d != '_' { - digit_count += 1; + digit_count += 1 } } switch digit_count { - case 4, 8, 16: break; + case 4, 8, 16: break case: - error(t, t.offset, "invalid hexadecimal floating-point number, expected 4, 8, or 16 digits, got %d", digit_count); + error(t, t.offset, "invalid hexadecimal floating-point number, expected 4, 8, or 16 digits, got %d", digit_count) } } case: - seen_point = false; - scan_mantissa(t, 10); + seen_point = false + scan_mantissa(t, 10) if t.ch == '.' { - seen_point = true; + seen_point = true if scan_fraction(t, &kind) { - return kind, string(t.src[offset : t.offset]); + return kind, string(t.src[offset : t.offset]) } } - scan_exponent(t, &kind); - return kind, string(t.src[offset : t.offset]); + scan_exponent(t, &kind) + return kind, string(t.src[offset : t.offset]) } } } - scan_mantissa(t, 10); + scan_mantissa(t, 10) if scan_fraction(t, &kind) { - return kind, string(t.src[offset : t.offset]); + return kind, string(t.src[offset : t.offset]) } - scan_exponent(t, &kind); + scan_exponent(t, &kind) - return kind, string(t.src[offset : t.offset]); + return kind, string(t.src[offset : t.offset]) } scan :: proc(t: ^Tokenizer) -> Token { - skip_whitespace(t); + skip_whitespace(t) - offset := t.offset; + offset := t.offset - kind: Token_Kind; - lit: string; - pos := offset_to_pos(t, offset); + kind: Token_Kind + lit: string + pos := offset_to_pos(t, offset) switch ch := t.ch; true { case is_letter(ch): - lit = scan_identifier(t); - kind = .Ident; + lit = scan_identifier(t) + kind = .Ident check_keyword: if len(lit) > 1 { // TODO(bill): Maybe have a hash table lookup rather than this linear search for i in Token_Kind.B_Keyword_Begin ..= Token_Kind.B_Keyword_End { if lit == tokens[i] { - kind = Token_Kind(i); - break check_keyword; + kind = Token_Kind(i) + break check_keyword } } for keyword, i in custom_keyword_tokens { if lit == keyword { - kind = Token_Kind(i+1) + .B_Custom_Keyword_Begin; - break check_keyword; + kind = Token_Kind(i+1) + .B_Custom_Keyword_Begin + break check_keyword } } - break check_keyword; + break check_keyword } case '0' <= ch && ch <= '9': - kind, lit = scan_number(t, false); + kind, lit = scan_number(t, false) case: - advance_rune(t); + advance_rune(t) switch ch { case -1: - kind = .EOF; + kind = .EOF if t.insert_semicolon { - t.insert_semicolon = false; - kind = .Semicolon; - lit = "\n"; - return Token{kind, lit, pos}; + t.insert_semicolon = false + kind = .Semicolon + lit = "\n" + return Token{kind, lit, pos} } case '\n': - t.insert_semicolon = false; - kind = .Semicolon; - lit = "\n"; + t.insert_semicolon = false + kind = .Semicolon + lit = "\n" case '\\': if .Insert_Semicolon in t.flags { - t.insert_semicolon = false; + t.insert_semicolon = false } - token := scan(t); + token := scan(t) if token.pos.line == pos.line { - error(t, token.pos.offset, "expected a newline after \\"); + error(t, token.pos.offset, "expected a newline after \\") } - return token; + return token case '\'': - kind = .Rune; - lit = scan_rune(t); + kind = .Rune + lit = scan_rune(t) case '"': - kind = .String; - lit = scan_string(t); + kind = .String + lit = scan_string(t) case '`': - kind = .String; - lit = scan_raw_string(t); + kind = .String + lit = scan_raw_string(t) case '.': - kind = .Period; + kind = .Period switch t.ch { case '0'..='9': - kind, lit = scan_number(t, true); + kind, lit = scan_number(t, true) case '.': - advance_rune(t); - kind = .Ellipsis; + advance_rune(t) + kind = .Ellipsis switch t.ch { case '<': - advance_rune(t); - kind = .Range_Half; + advance_rune(t) + kind = .Range_Half case '=': - advance_rune(t); - kind = .Range_Full; + advance_rune(t) + kind = .Range_Full } } - case '@': kind = .At; - case '$': kind = .Dollar; - case '?': kind = .Question; - case '^': kind = .Pointer; - case ';': kind = .Semicolon; - case ',': kind = .Comma; - case ':': kind = .Colon; - case '(': kind = .Open_Paren; - case ')': kind = .Close_Paren; - case '[': kind = .Open_Bracket; - case ']': kind = .Close_Bracket; - case '{': kind = .Open_Brace; - case '}': kind = .Close_Brace; + case '@': kind = .At + case '$': kind = .Dollar + case '?': kind = .Question + case '^': kind = .Pointer + case ';': kind = .Semicolon + case ',': kind = .Comma + case ':': kind = .Colon + case '(': kind = .Open_Paren + case ')': kind = .Close_Paren + case '[': kind = .Open_Bracket + case ']': kind = .Close_Bracket + case '{': kind = .Open_Brace + case '}': kind = .Close_Brace case '%': - kind = .Mod; + kind = .Mod switch t.ch { case '=': - advance_rune(t); - kind = .Mod_Eq; + advance_rune(t) + kind = .Mod_Eq case '%': - advance_rune(t); - kind = .Mod_Mod; + advance_rune(t) + kind = .Mod_Mod if t.ch == '=' { - advance_rune(t); - kind = .Mod_Mod_Eq; + advance_rune(t) + kind = .Mod_Mod_Eq } } case '*': - kind = .Mul; + kind = .Mul if t.ch == '=' { - advance_rune(t); - kind = .Mul_Eq; + advance_rune(t) + kind = .Mul_Eq } case '=': - kind = .Eq; + kind = .Eq if t.ch == '=' { - advance_rune(t); - kind = .Cmp_Eq; + advance_rune(t) + kind = .Cmp_Eq } case '~': - kind = .Xor; + kind = .Xor if t.ch == '=' { - advance_rune(t); - kind = .Xor_Eq; + advance_rune(t) + kind = .Xor_Eq } case '!': - kind = .Not; + kind = .Not if t.ch == '=' { - advance_rune(t); - kind = .Not_Eq; + advance_rune(t) + kind = .Not_Eq } case '+': - kind = .Add; + kind = .Add switch t.ch { case '=': - advance_rune(t); - kind = .Add_Eq; + advance_rune(t) + kind = .Add_Eq case '+': - advance_rune(t); - kind = .Increment; + advance_rune(t) + kind = .Increment } case '-': - kind = .Sub; + kind = .Sub switch t.ch { case '-': - advance_rune(t); - kind = .Decrement; + advance_rune(t) + kind = .Decrement if t.ch == '-' { - advance_rune(t); - kind = .Undef; + advance_rune(t) + kind = .Undef } case '>': - advance_rune(t); - kind = .Arrow_Right; + advance_rune(t) + kind = .Arrow_Right case '=': - advance_rune(t); - kind = .Sub_Eq; + advance_rune(t) + kind = .Sub_Eq } case '#': - kind = .Hash; + kind = .Hash if t.ch == '!' { - kind = .Comment; - lit = scan_comment(t); + kind = .Comment + lit = scan_comment(t) } case '/': - kind = .Quo; + kind = .Quo switch t.ch { case '/', '*': - kind = .Comment; - lit = scan_comment(t); + kind = .Comment + lit = scan_comment(t) case '=': - advance_rune(t); - kind = .Quo_Eq; + advance_rune(t) + kind = .Quo_Eq } case '<': - kind = .Lt; + kind = .Lt switch t.ch { case '=': - advance_rune(t); - kind = .Lt_Eq; + advance_rune(t) + kind = .Lt_Eq case '<': - advance_rune(t); - kind = .Shl; + advance_rune(t) + kind = .Shl if t.ch == '=' { - advance_rune(t); - kind = .Shl_Eq; + advance_rune(t) + kind = .Shl_Eq } } case '>': - kind = .Gt; + kind = .Gt switch t.ch { case '=': - advance_rune(t); - kind = .Gt_Eq; + advance_rune(t) + kind = .Gt_Eq case '<': - advance_rune(t); - kind = .Shr; + advance_rune(t) + kind = .Shr if t.ch == '=' { - advance_rune(t); - kind = .Shr_Eq; + advance_rune(t) + kind = .Shr_Eq } } case '&': - kind = .And; + kind = .And switch t.ch { case '~': - advance_rune(t); - kind = .And_Not; + advance_rune(t) + kind = .And_Not if t.ch == '=' { - advance_rune(t); - kind = .And_Not_Eq; + advance_rune(t) + kind = .And_Not_Eq } case '=': - advance_rune(t); - kind = .And_Eq; + advance_rune(t) + kind = .And_Eq case '&': - advance_rune(t); - kind = .Cmp_And; + advance_rune(t) + kind = .Cmp_And if t.ch == '=' { - advance_rune(t); - kind = .Cmp_And_Eq; + advance_rune(t) + kind = .Cmp_And_Eq } } case '|': - kind = .Or; + kind = .Or switch t.ch { case '=': - advance_rune(t); - kind = .Or_Eq; + advance_rune(t) + kind = .Or_Eq case '|': - advance_rune(t); - kind = .Cmp_Or; + advance_rune(t) + kind = .Cmp_Or if t.ch == '=' { - advance_rune(t); - kind = .Cmp_Or_Eq; + advance_rune(t) + kind = .Cmp_Or_Eq } } case: if ch != utf8.RUNE_BOM { - error(t, t.offset, "illegal character '%r': %d", ch, ch); + error(t, t.offset, "illegal character '%r': %d", ch, ch) } - kind = .Invalid; + kind = .Invalid } } @@ -726,15 +726,15 @@ scan :: proc(t: ^Tokenizer) -> Token { .Question, .Pointer, .Close_Paren, .Close_Bracket, .Close_Brace, .Increment, .Decrement, .Or_Return: /*fallthrough*/ - t.insert_semicolon = true; + t.insert_semicolon = true case: - t.insert_semicolon = false; - break; + t.insert_semicolon = false + break } } if lit == "" { - lit = string(t.src[offset : t.offset]); + lit = string(t.src[offset : t.offset]) } - return Token{kind, lit, pos}; + return Token{kind, lit, pos} } diff --git a/core/os/dir_windows.odin b/core/os/dir_windows.odin index 5f952d258..ff7e53293 100644 --- a/core/os/dir_windows.odin +++ b/core/os/dir_windows.odin @@ -8,100 +8,100 @@ read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []F find_data_to_file_info :: proc(base_path: string, d: ^win32.WIN32_FIND_DATAW) -> (fi: File_Info) { // Ignore "." and ".." if d.cFileName[0] == '.' && d.cFileName[1] == 0 { - return; + return } if d.cFileName[0] == '.' && d.cFileName[1] == '.' && d.cFileName[2] == 0 { - return; + return } - path := strings.concatenate({base_path, `\`, win32.utf16_to_utf8(d.cFileName[:])}); - fi.fullpath = path; - fi.name = basename(path); - fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow); + path := strings.concatenate({base_path, `\`, win32.utf16_to_utf8(d.cFileName[:])}) + fi.fullpath = path + fi.name = basename(path) + fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow) if d.dwFileAttributes & win32.FILE_ATTRIBUTE_READONLY != 0 { - fi.mode |= 0o444; + fi.mode |= 0o444 } else { - fi.mode |= 0o666; + fi.mode |= 0o666 } - is_sym := false; + is_sym := false if d.dwFileAttributes & win32.FILE_ATTRIBUTE_REPARSE_Point == 0 { - is_sym = false; + is_sym = false } else { - is_sym = d.dwReserved0 == win32.IO_REPARSE_TAG_SYMLINK || d.dwReserved0 == win32.IO_REPARSE_TAG_MOUNT_POINT; + is_sym = d.dwReserved0 == win32.IO_REPARSE_TAG_SYMLINK || d.dwReserved0 == win32.IO_REPARSE_TAG_MOUNT_POINT } if is_sym { - fi.mode |= File_Mode_Sym_Link; + fi.mode |= File_Mode_Sym_Link } else { if d.dwFileAttributes & win32.FILE_ATTRIBUTE_DIRECTORY != 0 { - fi.mode |= 0o111 | File_Mode_Dir; + fi.mode |= 0o111 | File_Mode_Dir } // fi.mode |= file_type_mode(h); } - fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime)); - fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime)); - fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime)); + fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime)) + fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime)) + fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime)) - fi.is_dir = fi.mode & File_Mode_Dir != 0; - return; + fi.is_dir = fi.mode & File_Mode_Dir != 0 + return } if fd == 0 { - return nil, ERROR_INVALID_HANDLE; + return nil, ERROR_INVALID_HANDLE } - context.allocator = allocator; + context.allocator = allocator - h := win32.HANDLE(fd); + h := win32.HANDLE(fd) - dir_fi, _ := file_info_from_get_file_information_by_handle("", h); + dir_fi, _ := file_info_from_get_file_information_by_handle("", h) if !dir_fi.is_dir { - return nil, ERROR_FILE_IS_NOT_DIR; + return nil, ERROR_FILE_IS_NOT_DIR } - n := n; - size := n; + n := n + size := n if n <= 0 { - n = -1; - size = 100; + n = -1 + size = 100 } - dfi := make([dynamic]File_Info, 0, size); + dfi := make([dynamic]File_Info, 0, size) - wpath: []u16; - wpath, err = cleanpath_from_handle_u16(fd); + wpath: []u16 + wpath, err = cleanpath_from_handle_u16(fd) if len(wpath) == 0 || err != ERROR_NONE { - return; + return } - wpath_search := make([]u16, len(wpath)+3, context.temp_allocator); - copy(wpath_search, wpath); - wpath_search[len(wpath)+0] = '\\'; - wpath_search[len(wpath)+1] = '*'; - wpath_search[len(wpath)+2] = 0; + wpath_search := make([]u16, len(wpath)+3, context.temp_allocator) + copy(wpath_search, wpath) + wpath_search[len(wpath)+0] = '\\' + wpath_search[len(wpath)+1] = '*' + wpath_search[len(wpath)+2] = 0 - path := cleanpath_from_buf(wpath); + path := cleanpath_from_buf(wpath) - find_data := &win32.WIN32_FIND_DATAW{}; - find_handle := win32.FindFirstFileW(raw_data(wpath_search), find_data); - defer win32.FindClose(find_handle); + find_data := &win32.WIN32_FIND_DATAW{} + find_handle := win32.FindFirstFileW(raw_data(wpath_search), find_data) + defer win32.FindClose(find_handle) for n != 0 && find_handle != nil { - fi: File_Info; - fi = find_data_to_file_info(path, find_data); + fi: File_Info + fi = find_data_to_file_info(path, find_data) if fi.name != "" { - append(&dfi, fi); - n -= 1; + append(&dfi, fi) + n -= 1 } if !win32.FindNextFileW(find_handle, find_data) { - e := Errno(win32.GetLastError()); + e := Errno(win32.GetLastError()) if e == ERROR_NO_MORE_FILES { - break; + break } - return dfi[:], e; + return dfi[:], e } } - return dfi[:], ERROR_NONE; + return dfi[:], ERROR_NONE } diff --git a/core/os/env_windows.odin b/core/os/env_windows.odin index 107a82d06..74981bc6e 100644 --- a/core/os/env_windows.odin +++ b/core/os/env_windows.odin @@ -8,26 +8,26 @@ import win32 "core:sys/windows" // NOTE: the value will be allocated with the supplied allocator lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) { if key == "" { - return; + return } - wkey := win32.utf8_to_wstring(key); - b := make([dynamic]u16, 100, context.temp_allocator); + wkey := win32.utf8_to_wstring(key) + b := make([dynamic]u16, 100, context.temp_allocator) for { - n := win32.GetEnvironmentVariableW(wkey, raw_data(b), u32(len(b))); + n := win32.GetEnvironmentVariableW(wkey, raw_data(b), u32(len(b))) if n == 0 { - err := win32.GetLastError(); + err := win32.GetLastError() if err == u32(ERROR_ENVVAR_NOT_FOUND) { - return "", false; + return "", false } } if n <= u32(len(b)) { - value = win32.utf16_to_utf8(b[:n], allocator); - found = true; - return; + value = win32.utf16_to_utf8(b[:n], allocator) + found = true + return } - resize(&b, len(b)*2); + resize(&b, len(b)*2) } } @@ -37,62 +37,62 @@ lookup_env :: proc(key: string, allocator := context.allocator) -> (value: strin // To distinguish between an empty value and an unset value, use lookup_env // NOTE: the value will be allocated with the supplied allocator get_env :: proc(key: string, allocator := context.allocator) -> (value: string) { - value, _ = lookup_env(key, allocator); - return; + value, _ = lookup_env(key, allocator) + return } // set_env sets the value of the environment variable named by the key set_env :: proc(key, value: string) -> Errno { - k := win32.utf8_to_wstring(key); - v := win32.utf8_to_wstring(value); + k := win32.utf8_to_wstring(key) + v := win32.utf8_to_wstring(value) if !win32.SetEnvironmentVariableW(k, v) { - return Errno(win32.GetLastError()); + return Errno(win32.GetLastError()) } - return 0; + return 0 } // unset_env unsets a single environment variable unset_env :: proc(key: string) -> Errno { - k := win32.utf8_to_wstring(key); + k := win32.utf8_to_wstring(key) if !win32.SetEnvironmentVariableW(k, nil) { - return Errno(win32.GetLastError()); + return Errno(win32.GetLastError()) } - return 0; + return 0 } // environ returns a copy of strings representing the environment, in the form "key=value" // NOTE: the slice of strings and the strings with be allocated using the supplied allocator environ :: proc(allocator := context.allocator) -> []string { - envs := cast([^]win32.WCHAR)(win32.GetEnvironmentStringsW()); + envs := cast([^]win32.WCHAR)(win32.GetEnvironmentStringsW()) if envs == nil { - return nil; + return nil } - defer win32.FreeEnvironmentStringsW(envs); + defer win32.FreeEnvironmentStringsW(envs) - r := make([dynamic]string, 0, 50, allocator); + r := make([dynamic]string, 0, 50, allocator) for from, i := 0, 0; true; i += 1 { if c := envs[i]; c == 0 { if i <= from { - break; + break } - append(&r, win32.utf16_to_utf8(envs[from:i], allocator)); - from = i + 1; + append(&r, win32.utf16_to_utf8(envs[from:i], allocator)) + from = i + 1 } } - return r[:]; + return r[:] } // clear_env deletes all environment variables clear_env :: proc() { - envs := environ(context.temp_allocator); + envs := environ(context.temp_allocator) for env in envs { for j in 1..<len(env) { if env[j] == '=' { - unset_env(env[0:j]); - break; + unset_env(env[0:j]) + break } } } diff --git a/core/os/file_windows.odin b/core/os/file_windows.odin index fa61a64e4..4d740db7c 100644 --- a/core/os/file_windows.odin +++ b/core/os/file_windows.odin @@ -4,337 +4,337 @@ import win32 "core:sys/windows" import "core:intrinsics" is_path_separator :: proc(c: byte) -> bool { - return c == '/' || c == '\\'; + return c == '/' || c == '\\' } open :: proc(path: string, mode: int = O_RDONLY, perm: int = 0) -> (Handle, Errno) { if len(path) == 0 { - return INVALID_HANDLE, ERROR_FILE_NOT_FOUND; + return INVALID_HANDLE, ERROR_FILE_NOT_FOUND } - access: u32; + access: u32 switch mode & (O_RDONLY|O_WRONLY|O_RDWR) { - case O_RDONLY: access = win32.FILE_GENERIC_READ; - case O_WRONLY: access = win32.FILE_GENERIC_WRITE; - case O_RDWR: access = win32.FILE_GENERIC_READ | win32.FILE_GENERIC_WRITE; + case O_RDONLY: access = win32.FILE_GENERIC_READ + case O_WRONLY: access = win32.FILE_GENERIC_WRITE + case O_RDWR: access = win32.FILE_GENERIC_READ | win32.FILE_GENERIC_WRITE } if mode&O_APPEND != 0 { - access &~= win32.FILE_GENERIC_WRITE; - access |= win32.FILE_APPEND_DATA; + access &~= win32.FILE_GENERIC_WRITE + access |= win32.FILE_APPEND_DATA } if mode&O_CREATE != 0 { - access |= win32.FILE_GENERIC_WRITE; + access |= win32.FILE_GENERIC_WRITE } - share_mode := win32.FILE_SHARE_READ|win32.FILE_SHARE_WRITE; - sa: ^win32.SECURITY_ATTRIBUTES = nil; - sa_inherit := win32.SECURITY_ATTRIBUTES{nLength = size_of(win32.SECURITY_ATTRIBUTES), bInheritHandle = true}; + share_mode := win32.FILE_SHARE_READ|win32.FILE_SHARE_WRITE + sa: ^win32.SECURITY_ATTRIBUTES = nil + sa_inherit := win32.SECURITY_ATTRIBUTES{nLength = size_of(win32.SECURITY_ATTRIBUTES), bInheritHandle = true} if mode&O_CLOEXEC == 0 { - sa = &sa_inherit; + sa = &sa_inherit } - create_mode: u32; + create_mode: u32 switch { case mode&(O_CREATE|O_EXCL) == (O_CREATE | O_EXCL): - create_mode = win32.CREATE_NEW; + create_mode = win32.CREATE_NEW case mode&(O_CREATE|O_TRUNC) == (O_CREATE | O_TRUNC): - create_mode = win32.CREATE_ALWAYS; + create_mode = win32.CREATE_ALWAYS case mode&O_CREATE == O_CREATE: - create_mode = win32.OPEN_ALWAYS; + create_mode = win32.OPEN_ALWAYS case mode&O_TRUNC == O_TRUNC: - create_mode = win32.TRUNCATE_EXISTING; + create_mode = win32.TRUNCATE_EXISTING case: - create_mode = win32.OPEN_EXISTING; + create_mode = win32.OPEN_EXISTING } - wide_path := win32.utf8_to_wstring(path); - handle := Handle(win32.CreateFileW(wide_path, access, share_mode, sa, create_mode, win32.FILE_ATTRIBUTE_NORMAL|win32.FILE_FLAG_BACKUP_SEMANTICS, nil)); + wide_path := win32.utf8_to_wstring(path) + handle := Handle(win32.CreateFileW(wide_path, access, share_mode, sa, create_mode, win32.FILE_ATTRIBUTE_NORMAL|win32.FILE_FLAG_BACKUP_SEMANTICS, nil)) if handle != INVALID_HANDLE { - return handle, ERROR_NONE; + return handle, ERROR_NONE } - err := Errno(win32.GetLastError()); - return INVALID_HANDLE, err; + err := Errno(win32.GetLastError()) + return INVALID_HANDLE, err } close :: proc(fd: Handle) -> Errno { if !win32.CloseHandle(win32.HANDLE(fd)) { - return Errno(win32.GetLastError()); + return Errno(win32.GetLastError()) } - return ERROR_NONE; + return ERROR_NONE } flush :: proc(fd: Handle) -> (err: Errno) { if !win32.FlushFileBuffers(win32.HANDLE(fd)) { - err = Errno(win32.GetLastError()); + err = Errno(win32.GetLastError()) } - return; + return } write :: proc(fd: Handle, data: []byte) -> (int, Errno) { if len(data) == 0 { - return 0, ERROR_NONE; + return 0, ERROR_NONE } - single_write_length: win32.DWORD; - total_write: i64; - length := i64(len(data)); + single_write_length: win32.DWORD + total_write: i64 + length := i64(len(data)) for total_write < length { - remaining := length - total_write; - to_write := win32.DWORD(min(i32(remaining), MAX_RW)); + remaining := length - total_write + to_write := win32.DWORD(min(i32(remaining), MAX_RW)) - e := win32.WriteFile(win32.HANDLE(fd), &data[total_write], to_write, &single_write_length, nil); + e := win32.WriteFile(win32.HANDLE(fd), &data[total_write], to_write, &single_write_length, nil) if single_write_length <= 0 || !e { - err := Errno(win32.GetLastError()); - return int(total_write), err; + err := Errno(win32.GetLastError()) + return int(total_write), err } - total_write += i64(single_write_length); + total_write += i64(single_write_length) } - return int(total_write), ERROR_NONE; + return int(total_write), ERROR_NONE } read :: proc(fd: Handle, data: []byte) -> (int, Errno) { if len(data) == 0 { - return 0, ERROR_NONE; + return 0, ERROR_NONE } - single_read_length: win32.DWORD; - total_read: i64; - length := i64(len(data)); + single_read_length: win32.DWORD + total_read: i64 + length := i64(len(data)) for total_read < length { - remaining := length - total_read; - to_read := min(win32.DWORD(remaining), MAX_RW); + remaining := length - total_read + to_read := min(win32.DWORD(remaining), MAX_RW) - e := win32.ReadFile(win32.HANDLE(fd), &data[total_read], to_read, &single_read_length, nil); + e := win32.ReadFile(win32.HANDLE(fd), &data[total_read], to_read, &single_read_length, nil) if single_read_length <= 0 || !e { - err := Errno(win32.GetLastError()); - return int(total_read), err; + err := Errno(win32.GetLastError()) + return int(total_read), err } - total_read += i64(single_read_length); + total_read += i64(single_read_length) } - return int(total_read), ERROR_NONE; + return int(total_read), ERROR_NONE } seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) { - w: u32; + w: u32 switch whence { - case 0: w = win32.FILE_BEGIN; - case 1: w = win32.FILE_CURRENT; - case 2: w = win32.FILE_END; + case 0: w = win32.FILE_BEGIN + case 1: w = win32.FILE_CURRENT + case 2: w = win32.FILE_END } - hi := i32(offset>>32); - lo := i32(offset); - ft := win32.GetFileType(win32.HANDLE(fd)); + hi := i32(offset>>32) + lo := i32(offset) + ft := win32.GetFileType(win32.HANDLE(fd)) if ft == win32.FILE_TYPE_PIPE { - return 0, ERROR_FILE_IS_PIPE; + return 0, ERROR_FILE_IS_PIPE } - dw_ptr := win32.SetFilePointer(win32.HANDLE(fd), lo, &hi, w); + dw_ptr := win32.SetFilePointer(win32.HANDLE(fd), lo, &hi, w) if dw_ptr == win32.INVALID_SET_FILE_POINTER { - err := Errno(win32.GetLastError()); - return 0, err; + err := Errno(win32.GetLastError()) + return 0, err } - return i64(hi)<<32 + i64(dw_ptr), ERROR_NONE; + return i64(hi)<<32 + i64(dw_ptr), ERROR_NONE } file_size :: proc(fd: Handle) -> (i64, Errno) { - length: win32.LARGE_INTEGER; - err: Errno; + length: win32.LARGE_INTEGER + err: Errno if !win32.GetFileSizeEx(win32.HANDLE(fd), &length) { - err = Errno(win32.GetLastError()); + err = Errno(win32.GetLastError()) } - return i64(length), err; + return i64(length), err } @(private) -MAX_RW :: 1<<30; +MAX_RW :: 1<<30 @(private) pread :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) { - buf := data; + buf := data if len(buf) > MAX_RW { - buf = buf[:MAX_RW]; + buf = buf[:MAX_RW] } - curr_offset, e := seek(fd, offset, 1); + curr_offset, e := seek(fd, offset, 1) if e != 0 { - return 0, e; + return 0, e } - defer seek(fd, curr_offset, 0); + defer seek(fd, curr_offset, 0) o := win32.OVERLAPPED{ OffsetHigh = u32(offset>>32), Offset = u32(offset), - }; + } - h := win32.HANDLE(fd); - done: win32.DWORD; + h := win32.HANDLE(fd) + done: win32.DWORD if !win32.ReadFile(h, raw_data(buf), u32(len(buf)), &done, &o) { - e = Errno(win32.GetLastError()); - done = 0; + e = Errno(win32.GetLastError()) + done = 0 } - return int(done), e; + return int(done), e } @(private) pwrite :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) { - buf := data; + buf := data if len(buf) > MAX_RW { - buf = buf[:MAX_RW]; + buf = buf[:MAX_RW] } - curr_offset, e := seek(fd, offset, 1); + curr_offset, e := seek(fd, offset, 1) if e != 0 { - return 0, e; + return 0, e } - defer seek(fd, curr_offset, 0); + defer seek(fd, curr_offset, 0) o := win32.OVERLAPPED{ OffsetHigh = u32(offset>>32), Offset = u32(offset), - }; + } - h := win32.HANDLE(fd); - done: win32.DWORD; + h := win32.HANDLE(fd) + done: win32.DWORD if !win32.WriteFile(h, raw_data(buf), u32(len(buf)), &done, &o) { - e = Errno(win32.GetLastError()); - done = 0; + e = Errno(win32.GetLastError()) + done = 0 } - return int(done), e; + return int(done), e } read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Errno) { if offset < 0 { - return 0, ERROR_NEGATIVE_OFFSET; + return 0, ERROR_NEGATIVE_OFFSET } - b, offset := data, offset; + b, offset := data, offset for len(b) > 0 { - m, e := pread(fd, b, offset); + m, e := pread(fd, b, offset) if e != 0 { - err = e; - break; + err = e + break } - n += m; - b = b[m:]; - offset += i64(m); + n += m + b = b[m:] + offset += i64(m) } - return; + return } write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Errno) { if offset < 0 { - return 0, ERROR_NEGATIVE_OFFSET; + return 0, ERROR_NEGATIVE_OFFSET } - b, offset := data, offset; + b, offset := data, offset for len(b) > 0 { - m, e := pwrite(fd, b, offset); + m, e := pwrite(fd, b, offset) if e != 0 { - err = e; - break; + err = e + break } - n += m; - b = b[m:]; - offset += i64(m); + n += m + b = b[m:] + offset += i64(m) } - return; + return } // NOTE(bill): Uses startup to initialize it -stdin := get_std_handle(uint(win32.STD_INPUT_HANDLE)); -stdout := get_std_handle(uint(win32.STD_OUTPUT_HANDLE)); -stderr := get_std_handle(uint(win32.STD_ERROR_HANDLE)); +stdin := get_std_handle(uint(win32.STD_INPUT_HANDLE)) +stdout := get_std_handle(uint(win32.STD_OUTPUT_HANDLE)) +stderr := get_std_handle(uint(win32.STD_ERROR_HANDLE)) get_std_handle :: proc "contextless" (h: uint) -> Handle { - fd := win32.GetStdHandle(win32.DWORD(h)); + fd := win32.GetStdHandle(win32.DWORD(h)) when size_of(uintptr) == 8 { - win32.SetHandleInformation(fd, win32.HANDLE_FLAG_INHERIT, 0); + win32.SetHandleInformation(fd, win32.HANDLE_FLAG_INHERIT, 0) } - return Handle(fd); + return Handle(fd) } exists :: proc(path: string) -> bool { - wpath := win32.utf8_to_wstring(path, context.temp_allocator); - attribs := win32.GetFileAttributesW(wpath); + wpath := win32.utf8_to_wstring(path, context.temp_allocator) + attribs := win32.GetFileAttributesW(wpath) - return i32(attribs) != win32.INVALID_FILE_ATTRIBUTES; + return i32(attribs) != win32.INVALID_FILE_ATTRIBUTES } is_file :: proc(path: string) -> bool { - wpath := win32.utf8_to_wstring(path, context.temp_allocator); - attribs := win32.GetFileAttributesW(wpath); + wpath := win32.utf8_to_wstring(path, context.temp_allocator) + attribs := win32.GetFileAttributesW(wpath) if i32(attribs) != win32.INVALID_FILE_ATTRIBUTES { - return attribs & win32.FILE_ATTRIBUTE_DIRECTORY == 0; + return attribs & win32.FILE_ATTRIBUTE_DIRECTORY == 0 } - return false; + return false } is_dir :: proc(path: string) -> bool { - wpath := win32.utf8_to_wstring(path, context.temp_allocator); - attribs := win32.GetFileAttributesW(wpath); + wpath := win32.utf8_to_wstring(path, context.temp_allocator) + attribs := win32.GetFileAttributesW(wpath) if i32(attribs) != win32.INVALID_FILE_ATTRIBUTES { - return attribs & win32.FILE_ATTRIBUTE_DIRECTORY != 0; + return attribs & win32.FILE_ATTRIBUTE_DIRECTORY != 0 } - return false; + return false } // NOTE(tetra): GetCurrentDirectory is not thread safe with SetCurrentDirectory and GetFullPathName -@private cwd_lock := win32.SRWLOCK{}; // zero is initialized +@private cwd_lock := win32.SRWLOCK{} // zero is initialized get_current_directory :: proc(allocator := context.allocator) -> string { - win32.AcquireSRWLockExclusive(&cwd_lock); + win32.AcquireSRWLockExclusive(&cwd_lock) - sz_utf16 := win32.GetCurrentDirectoryW(0, nil); - dir_buf_wstr := make([]u16, sz_utf16, context.temp_allocator); // the first time, it _includes_ the NUL. + sz_utf16 := win32.GetCurrentDirectoryW(0, nil) + dir_buf_wstr := make([]u16, sz_utf16, context.temp_allocator) // the first time, it _includes_ the NUL. - sz_utf16 = win32.GetCurrentDirectoryW(win32.DWORD(len(dir_buf_wstr)), raw_data(dir_buf_wstr)); - assert(int(sz_utf16)+1 == len(dir_buf_wstr)); // the second time, it _excludes_ the NUL. + sz_utf16 = win32.GetCurrentDirectoryW(win32.DWORD(len(dir_buf_wstr)), raw_data(dir_buf_wstr)) + assert(int(sz_utf16)+1 == len(dir_buf_wstr)) // the second time, it _excludes_ the NUL. - win32.ReleaseSRWLockExclusive(&cwd_lock); + win32.ReleaseSRWLockExclusive(&cwd_lock) - return win32.utf16_to_utf8(dir_buf_wstr, allocator); + return win32.utf16_to_utf8(dir_buf_wstr, allocator) } set_current_directory :: proc(path: string) -> (err: Errno) { - wstr := win32.utf8_to_wstring(path); + wstr := win32.utf8_to_wstring(path) - win32.AcquireSRWLockExclusive(&cwd_lock); + win32.AcquireSRWLockExclusive(&cwd_lock) if !win32.SetCurrentDirectoryW(wstr) { - err = Errno(win32.GetLastError()); + err = Errno(win32.GetLastError()) } - win32.ReleaseSRWLockExclusive(&cwd_lock); + win32.ReleaseSRWLockExclusive(&cwd_lock) - return; + return } change_directory :: proc(path: string) -> Errno { - wpath := win32.utf8_to_wstring(path, context.temp_allocator); - return Errno(win32.SetCurrentDirectoryW(wpath)); + wpath := win32.utf8_to_wstring(path, context.temp_allocator) + return Errno(win32.SetCurrentDirectoryW(wpath)) } make_directory :: proc(path: string, mode: u32) -> Errno { - wpath := win32.utf8_to_wstring(path, context.temp_allocator); - return Errno(win32.CreateDirectoryW(wpath, nil)); + wpath := win32.utf8_to_wstring(path, context.temp_allocator) + return Errno(win32.CreateDirectoryW(wpath, nil)) } remove_directory :: proc(path: string) -> Errno { - wpath := win32.utf8_to_wstring(path, context.temp_allocator); - return Errno(win32.RemoveDirectoryW(wpath)); + wpath := win32.utf8_to_wstring(path, context.temp_allocator) + return Errno(win32.RemoveDirectoryW(wpath)) } @@ -342,158 +342,158 @@ remove_directory :: proc(path: string) -> Errno { @(private) is_abs :: proc(path: string) -> bool { if len(path) > 0 && path[0] == '/' { - return true; + return true } when ODIN_OS == "windows" { if len(path) > 2 { switch path[0] { case 'A'..='Z', 'a'..='z': - return path[1] == ':' && is_path_separator(path[2]); + return path[1] == ':' && is_path_separator(path[2]) } } } - return false; + return false } @(private) fix_long_path :: proc(path: string) -> string { if len(path) < 248 { - return path; + return path } if len(path) >= 2 && path[:2] == `\\` { - return path; + return path } if !is_abs(path) { - return path; + return path } - prefix :: `\\?`; + prefix :: `\\?` - path_buf := make([]byte, len(prefix)+len(path)+len(`\`), context.temp_allocator); - copy(path_buf, prefix); - n := len(path); - r, w := 0, len(prefix); + path_buf := make([]byte, len(prefix)+len(path)+len(`\`), context.temp_allocator) + copy(path_buf, prefix) + n := len(path) + r, w := 0, len(prefix) for r < n { switch { case is_path_separator(path[r]): - r += 1; + r += 1 case path[r] == '.' && (r+1 == n || is_path_separator(path[r+1])): - r += 1; + r += 1 case r+1 < n && path[r] == '.' && path[r+1] == '.' && (r+2 == n || is_path_separator(path[r+2])): - return path; + return path case: - path_buf[w] = '\\'; - w += 1; + path_buf[w] = '\\' + w += 1 for ; r < n && !is_path_separator(path[r]); r += 1 { - path_buf[w] = path[r]; - w += 1; + path_buf[w] = path[r] + w += 1 } } } if w == len(`\\?\c:`) { - path_buf[w] = '\\'; - w += 1; + path_buf[w] = '\\' + w += 1 } - return string(path_buf[:w]); + return string(path_buf[:w]) } link :: proc(old_name, new_name: string) -> Errno { - n := win32.utf8_to_wstring(fix_long_path(new_name)); - o := win32.utf8_to_wstring(fix_long_path(old_name)); - return Errno(win32.CreateHardLinkW(n, o, nil)); + n := win32.utf8_to_wstring(fix_long_path(new_name)) + o := win32.utf8_to_wstring(fix_long_path(old_name)) + return Errno(win32.CreateHardLinkW(n, o, nil)) } unlink :: proc(path: string) -> Errno { - wpath := win32.utf8_to_wstring(path, context.temp_allocator); - return Errno(win32.DeleteFileW(wpath)); + wpath := win32.utf8_to_wstring(path, context.temp_allocator) + return Errno(win32.DeleteFileW(wpath)) } rename :: proc(old_path, new_path: string) -> Errno { - from := win32.utf8_to_wstring(old_path, context.temp_allocator); - to := win32.utf8_to_wstring(new_path, context.temp_allocator); - return Errno(win32.MoveFileExW(from, to, win32.MOVEFILE_REPLACE_EXISTING)); + from := win32.utf8_to_wstring(old_path, context.temp_allocator) + to := win32.utf8_to_wstring(new_path, context.temp_allocator) + return Errno(win32.MoveFileExW(from, to, win32.MOVEFILE_REPLACE_EXISTING)) } ftruncate :: proc(fd: Handle, length: i64) -> (err: Errno) { - curr_off, e := seek(fd, 0, 1); + curr_off, e := seek(fd, 0, 1) if e != 0 { - return e; + return e } - defer seek(fd, curr_off, 0); - _, e = seek(fd, length, 0); + defer seek(fd, curr_off, 0) + _, e = seek(fd, length, 0) if e != 0 { - return e; + return e } - ok := win32.SetEndOfFile(win32.HANDLE(fd)); + ok := win32.SetEndOfFile(win32.HANDLE(fd)) if !ok { - return Errno(win32.GetLastError()); + return Errno(win32.GetLastError()) } - return ERROR_NONE; + return ERROR_NONE } truncate :: proc(path: string, length: i64) -> (err: Errno) { - fd: Handle; - fd, err = open(path, O_WRONLY|O_CREATE, 0o666); + fd: Handle + fd, err = open(path, O_WRONLY|O_CREATE, 0o666) if err != 0 { - return; + return } - defer close(fd); - err = ftruncate(fd, length); - return; + defer close(fd) + err = ftruncate(fd, length) + return } remove :: proc(name: string) -> Errno { - p := win32.utf8_to_wstring(fix_long_path(name)); - err, err1: win32.DWORD; + p := win32.utf8_to_wstring(fix_long_path(name)) + err, err1: win32.DWORD if !win32.DeleteFileW(p) { - err = win32.GetLastError(); + err = win32.GetLastError() } if err == 0 { - return 0; + return 0 } if !win32.RemoveDirectoryW(p) { - err1 = win32.GetLastError(); + err1 = win32.GetLastError() } if err1 == 0 { - return 0; + return 0 } if err != err1 { - a := win32.GetFileAttributesW(p); + a := win32.GetFileAttributesW(p) if a == ~u32(0) { - err = win32.GetLastError(); + err = win32.GetLastError() } else { if a & win32.FILE_ATTRIBUTE_DIRECTORY != 0 { - err = err1; + err = err1 } else if a & win32.FILE_ATTRIBUTE_READONLY != 0 { if win32.SetFileAttributesW(p, a &~ win32.FILE_ATTRIBUTE_READONLY) { - err = 0; + err = 0 if !win32.DeleteFileW(p) { - err = win32.GetLastError(); + err = win32.GetLastError() } } } } } - return Errno(err); + return Errno(err) } pipe :: proc() -> (r, w: Handle, err: Errno) { - sa: win32.SECURITY_ATTRIBUTES; - sa.nLength = size_of(win32.SECURITY_ATTRIBUTES); - sa.bInheritHandle = true; + sa: win32.SECURITY_ATTRIBUTES + sa.nLength = size_of(win32.SECURITY_ATTRIBUTES) + sa.bInheritHandle = true if !win32.CreatePipe((^win32.HANDLE)(&r), (^win32.HANDLE)(&w), &sa, 0) { - err = Errno(win32.GetLastError()); + err = Errno(win32.GetLastError()) } - return; + return } diff --git a/core/os/os.odin b/core/os/os.odin index c9aa18eb0..8b1f7e2b5 100644 --- a/core/os/os.odin +++ b/core/os/os.odin @@ -5,130 +5,130 @@ import "core:strconv" import "core:unicode/utf8" -OS :: ODIN_OS; -ARCH :: ODIN_ARCH; -ENDIAN :: ODIN_ENDIAN; +OS :: ODIN_OS +ARCH :: ODIN_ARCH +ENDIAN :: ODIN_ENDIAN write_string :: proc(fd: Handle, str: string) -> (int, Errno) { - return write(fd, transmute([]byte)str); + return write(fd, transmute([]byte)str) } write_byte :: proc(fd: Handle, b: byte) -> (int, Errno) { - return write(fd, []byte{b}); + return write(fd, []byte{b}) } write_rune :: proc(fd: Handle, r: rune) -> (int, Errno) { if r < utf8.RUNE_SELF { - return write_byte(fd, byte(r)); + return write_byte(fd, byte(r)) } - b, n := utf8.encode_rune(r); - return write(fd, b[:n]); + b, n := utf8.encode_rune(r) + return write(fd, b[:n]) } write_encoded_rune :: proc(fd: Handle, r: rune) { - write_byte(fd, '\''); + write_byte(fd, '\'') switch r { - case '\a': write_string(fd, "\\a"); - case '\b': write_string(fd, "\\b"); - case '\e': write_string(fd, "\\e"); - case '\f': write_string(fd, "\\f"); - case '\n': write_string(fd, "\\n"); - case '\r': write_string(fd, "\\r"); - case '\t': write_string(fd, "\\t"); - case '\v': write_string(fd, "\\v"); + case '\a': write_string(fd, "\\a") + case '\b': write_string(fd, "\\b") + case '\e': write_string(fd, "\\e") + case '\f': write_string(fd, "\\f") + case '\n': write_string(fd, "\\n") + case '\r': write_string(fd, "\\r") + case '\t': write_string(fd, "\\t") + case '\v': write_string(fd, "\\v") case: if r < 32 { - write_string(fd, "\\x"); - b: [2]byte; - s := strconv.append_bits(b[:], u64(r), 16, true, 64, strconv.digits, nil); + write_string(fd, "\\x") + b: [2]byte + s := strconv.append_bits(b[:], u64(r), 16, true, 64, strconv.digits, nil) switch len(s) { - case 0: write_string(fd, "00"); - case 1: write_rune(fd, '0'); - case 2: write_string(fd, s); + case 0: write_string(fd, "00") + case 1: write_rune(fd, '0') + case 2: write_string(fd, s) } } else { - write_rune(fd, r); + write_rune(fd, r) } } - write_byte(fd, '\''); + write_byte(fd, '\'') } file_size_from_path :: proc(path: string) -> i64 { - fd, err := open(path, O_RDONLY, 0); + fd, err := open(path, O_RDONLY, 0) if err != 0 { - return -1; + return -1 } - defer close(fd); + defer close(fd) - length: i64; + length: i64 if length, err = file_size(fd); err != 0 { - return -1; + return -1 } - return length; + return length } read_entire_file :: proc(name: string, allocator := context.allocator) -> (data: []byte, success: bool) { - fd, err := open(name, O_RDONLY, 0); + fd, err := open(name, O_RDONLY, 0) if err != 0 { - return nil, false; + return nil, false } - defer close(fd); + defer close(fd) - length: i64; + length: i64 if length, err = file_size(fd); err != 0 { - return nil, false; + return nil, false } if length <= 0 { - return nil, true; + return nil, true } - data = make([]byte, int(length), allocator); + data = make([]byte, int(length), allocator) if data == nil { - return nil, false; + return nil, false } - bytes_read, read_err := read(fd, data); + bytes_read, read_err := read(fd, data) if read_err != ERROR_NONE { - delete(data); - return nil, false; + delete(data) + return nil, false } - return data[:bytes_read], true; + return data[:bytes_read], true } write_entire_file :: proc(name: string, data: []byte, truncate := true) -> (success: bool) { - flags: int = O_WRONLY|O_CREATE; + flags: int = O_WRONLY|O_CREATE if truncate { - flags |= O_TRUNC; + flags |= O_TRUNC } - mode: int = 0; + mode: int = 0 when OS == "linux" || OS == "darwin" { // NOTE(justasd): 644 (owner read, write; group read; others read) - mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; + mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH } - fd, err := open(name, flags, mode); + fd, err := open(name, flags, mode) if err != 0 { - return false; + return false } - defer close(fd); + defer close(fd) - _, write_err := write(fd, data); - return write_err == 0; + _, write_err := write(fd, data) + return write_err == 0 } write_ptr :: proc(fd: Handle, data: rawptr, len: int) -> (int, Errno) { - s := transmute([]byte)mem.Raw_Slice{data, len}; - return write(fd, s); + s := transmute([]byte)mem.Raw_Slice{data, len} + return write(fd, s) } read_ptr :: proc(fd: Handle, data: rawptr, len: int) -> (int, Errno) { - s := transmute([]byte)mem.Raw_Slice{data, len}; - return read(fd, s); + s := transmute([]byte)mem.Raw_Slice{data, len} + return read(fd, s) } heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, @@ -142,77 +142,77 @@ heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, // aligned_alloc :: proc(size, alignment: int, old_ptr: rawptr = nil) -> ([]byte, mem.Allocator_Error) { - a := max(alignment, align_of(rawptr)); - space := size + a - 1; + a := max(alignment, align_of(rawptr)) + space := size + a - 1 - allocated_mem: rawptr; + allocated_mem: rawptr if old_ptr != nil { - original_old_ptr := mem.ptr_offset((^rawptr)(old_ptr), -1)^; - allocated_mem = heap_resize(original_old_ptr, space+size_of(rawptr)); + original_old_ptr := mem.ptr_offset((^rawptr)(old_ptr), -1)^ + allocated_mem = heap_resize(original_old_ptr, space+size_of(rawptr)) } else { - allocated_mem = heap_alloc(space+size_of(rawptr)); + allocated_mem = heap_alloc(space+size_of(rawptr)) } - aligned_mem := rawptr(mem.ptr_offset((^u8)(allocated_mem), size_of(rawptr))); + aligned_mem := rawptr(mem.ptr_offset((^u8)(allocated_mem), size_of(rawptr))) - ptr := uintptr(aligned_mem); - aligned_ptr := (ptr - 1 + uintptr(a)) & -uintptr(a); - diff := int(aligned_ptr - ptr); + ptr := uintptr(aligned_mem) + aligned_ptr := (ptr - 1 + uintptr(a)) & -uintptr(a) + diff := int(aligned_ptr - ptr) if (size + diff) > space { - return nil, .Out_Of_Memory; + return nil, .Out_Of_Memory } - aligned_mem = rawptr(aligned_ptr); - mem.ptr_offset((^rawptr)(aligned_mem), -1)^ = allocated_mem; + aligned_mem = rawptr(aligned_ptr) + mem.ptr_offset((^rawptr)(aligned_mem), -1)^ = allocated_mem - return mem.byte_slice(aligned_mem, size), nil; + return mem.byte_slice(aligned_mem, size), nil } aligned_free :: proc(p: rawptr) { if p != nil { - heap_free(mem.ptr_offset((^rawptr)(p), -1)^); + heap_free(mem.ptr_offset((^rawptr)(p), -1)^) } } aligned_resize :: proc(p: rawptr, old_size: int, new_size: int, new_alignment: int) -> ([]byte, mem.Allocator_Error) { if p == nil { - return nil, nil; + return nil, nil } - return aligned_alloc(new_size, new_alignment, p); + return aligned_alloc(new_size, new_alignment, p) } switch mode { case .Alloc: - return aligned_alloc(size, alignment); + return aligned_alloc(size, alignment) case .Free: - aligned_free(old_memory); + aligned_free(old_memory) case .Free_All: - return nil, .Mode_Not_Implemented; + return nil, .Mode_Not_Implemented case .Resize: if old_memory == nil { - return aligned_alloc(size, alignment); + return aligned_alloc(size, alignment) } - return aligned_resize(old_memory, old_size, size, alignment); + return aligned_resize(old_memory, old_size, size, alignment) case .Query_Features: - set := (^mem.Allocator_Mode_Set)(old_memory); + set := (^mem.Allocator_Mode_Set)(old_memory) if set != nil { - set^ = {.Alloc, .Free, .Resize, .Query_Features}; + set^ = {.Alloc, .Free, .Resize, .Query_Features} } - return nil, nil; + return nil, nil case .Query_Info: - return nil, .Mode_Not_Implemented; + return nil, .Mode_Not_Implemented } - return nil, nil; + return nil, nil } heap_allocator :: proc() -> mem.Allocator { return mem.Allocator{ procedure = heap_allocator_proc, data = nil, - }; + } } diff --git a/core/os/os_windows.odin b/core/os/os_windows.odin index edba74504..e6efb89df 100644 --- a/core/os/os_windows.odin +++ b/core/os/os_windows.odin @@ -3,161 +3,161 @@ package os import win32 "core:sys/windows" -Handle :: distinct uintptr; -File_Time :: distinct u64; -Errno :: distinct int; - - -INVALID_HANDLE :: ~Handle(0); - - - -O_RDONLY :: 0x00000; -O_WRONLY :: 0x00001; -O_RDWR :: 0x00002; -O_CREATE :: 0x00040; -O_EXCL :: 0x00080; -O_NOCTTY :: 0x00100; -O_TRUNC :: 0x00200; -O_NONBLOCK :: 0x00800; -O_APPEND :: 0x00400; -O_SYNC :: 0x01000; -O_ASYNC :: 0x02000; -O_CLOEXEC :: 0x80000; - - -ERROR_NONE: Errno : 0; -ERROR_FILE_NOT_FOUND: Errno : 2; -ERROR_PATH_NOT_FOUND: Errno : 3; -ERROR_ACCESS_DENIED: Errno : 5; -ERROR_INVALID_HANDLE: Errno : 6; -ERROR_NOT_ENOUGH_MEMORY: Errno : 8; -ERROR_NO_MORE_FILES: Errno : 18; -ERROR_HANDLE_EOF: Errno : 38; -ERROR_NETNAME_DELETED: Errno : 64; -ERROR_FILE_EXISTS: Errno : 80; -ERROR_INVALID_PARAMETER: Errno : 87; -ERROR_BROKEN_PIPE: Errno : 109; -ERROR_BUFFER_OVERFLOW: Errno : 111; -ERROR_INSUFFICIENT_BUFFER: Errno : 122; -ERROR_MOD_NOT_FOUND: Errno : 126; -ERROR_PROC_NOT_FOUND: Errno : 127; -ERROR_DIR_NOT_EMPTY: Errno : 145; -ERROR_ALREADY_EXISTS: Errno : 183; -ERROR_ENVVAR_NOT_FOUND: Errno : 203; -ERROR_MORE_DATA: Errno : 234; -ERROR_OPERATION_ABORTED: Errno : 995; -ERROR_IO_PENDING: Errno : 997; -ERROR_NOT_FOUND: Errno : 1168; -ERROR_PRIVILEGE_NOT_HELD: Errno : 1314; -WSAEACCES: Errno : 10013; -WSAECONNRESET: Errno : 10054; +Handle :: distinct uintptr +File_Time :: distinct u64 +Errno :: distinct int + + +INVALID_HANDLE :: ~Handle(0) + + + +O_RDONLY :: 0x00000 +O_WRONLY :: 0x00001 +O_RDWR :: 0x00002 +O_CREATE :: 0x00040 +O_EXCL :: 0x00080 +O_NOCTTY :: 0x00100 +O_TRUNC :: 0x00200 +O_NONBLOCK :: 0x00800 +O_APPEND :: 0x00400 +O_SYNC :: 0x01000 +O_ASYNC :: 0x02000 +O_CLOEXEC :: 0x80000 + + +ERROR_NONE: Errno : 0 +ERROR_FILE_NOT_FOUND: Errno : 2 +ERROR_PATH_NOT_FOUND: Errno : 3 +ERROR_ACCESS_DENIED: Errno : 5 +ERROR_INVALID_HANDLE: Errno : 6 +ERROR_NOT_ENOUGH_MEMORY: Errno : 8 +ERROR_NO_MORE_FILES: Errno : 18 +ERROR_HANDLE_EOF: Errno : 38 +ERROR_NETNAME_DELETED: Errno : 64 +ERROR_FILE_EXISTS: Errno : 80 +ERROR_INVALID_PARAMETER: Errno : 87 +ERROR_BROKEN_PIPE: Errno : 109 +ERROR_BUFFER_OVERFLOW: Errno : 111 +ERROR_INSUFFICIENT_BUFFER: Errno : 122 +ERROR_MOD_NOT_FOUND: Errno : 126 +ERROR_PROC_NOT_FOUND: Errno : 127 +ERROR_DIR_NOT_EMPTY: Errno : 145 +ERROR_ALREADY_EXISTS: Errno : 183 +ERROR_ENVVAR_NOT_FOUND: Errno : 203 +ERROR_MORE_DATA: Errno : 234 +ERROR_OPERATION_ABORTED: Errno : 995 +ERROR_IO_PENDING: Errno : 997 +ERROR_NOT_FOUND: Errno : 1168 +ERROR_PRIVILEGE_NOT_HELD: Errno : 1314 +WSAEACCES: Errno : 10013 +WSAECONNRESET: Errno : 10054 // Windows reserves errors >= 1<<29 for application use -ERROR_FILE_IS_PIPE: Errno : 1<<29 + 0; -ERROR_FILE_IS_NOT_DIR: Errno : 1<<29 + 1; -ERROR_NEGATIVE_OFFSET: Errno : 1<<29 + 2; +ERROR_FILE_IS_PIPE: Errno : 1<<29 + 0 +ERROR_FILE_IS_NOT_DIR: Errno : 1<<29 + 1 +ERROR_NEGATIVE_OFFSET: Errno : 1<<29 + 2 // "Argv" arguments converted to Odin strings -args := _alloc_command_line_arguments(); +args := _alloc_command_line_arguments() last_write_time :: proc(fd: Handle) -> (File_Time, Errno) { - file_info: win32.BY_HANDLE_FILE_INFORMATION; + file_info: win32.BY_HANDLE_FILE_INFORMATION if !win32.GetFileInformationByHandle(win32.HANDLE(fd), &file_info) { - return 0, Errno(win32.GetLastError()); + return 0, Errno(win32.GetLastError()) } - lo := File_Time(file_info.ftLastWriteTime.dwLowDateTime); - hi := File_Time(file_info.ftLastWriteTime.dwHighDateTime); - return lo | hi << 32, ERROR_NONE; + lo := File_Time(file_info.ftLastWriteTime.dwLowDateTime) + hi := File_Time(file_info.ftLastWriteTime.dwHighDateTime) + return lo | hi << 32, ERROR_NONE } last_write_time_by_name :: proc(name: string) -> (File_Time, Errno) { - data: win32.WIN32_FILE_ATTRIBUTE_DATA; + data: win32.WIN32_FILE_ATTRIBUTE_DATA - wide_path := win32.utf8_to_wstring(name); + wide_path := win32.utf8_to_wstring(name) if !win32.GetFileAttributesExW(wide_path, win32.GetFileExInfoStandard, &data) { - return 0, Errno(win32.GetLastError()); + return 0, Errno(win32.GetLastError()) } - l := File_Time(data.ftLastWriteTime.dwLowDateTime); - h := File_Time(data.ftLastWriteTime.dwHighDateTime); - return l | h << 32, ERROR_NONE; + l := File_Time(data.ftLastWriteTime.dwLowDateTime) + h := File_Time(data.ftLastWriteTime.dwHighDateTime) + return l | h << 32, ERROR_NONE } heap_alloc :: proc(size: int) -> rawptr { - return win32.HeapAlloc(win32.GetProcessHeap(), win32.HEAP_ZERO_MEMORY, uint(size)); + return win32.HeapAlloc(win32.GetProcessHeap(), win32.HEAP_ZERO_MEMORY, uint(size)) } heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr { if new_size == 0 { - heap_free(ptr); - return nil; + heap_free(ptr) + return nil } if ptr == nil { - return heap_alloc(new_size); + return heap_alloc(new_size) } - return win32.HeapReAlloc(win32.GetProcessHeap(), win32.HEAP_ZERO_MEMORY, ptr, uint(new_size)); + return win32.HeapReAlloc(win32.GetProcessHeap(), win32.HEAP_ZERO_MEMORY, ptr, uint(new_size)) } heap_free :: proc(ptr: rawptr) { if ptr == nil { - return; + return } - win32.HeapFree(win32.GetProcessHeap(), 0, ptr); + win32.HeapFree(win32.GetProcessHeap(), 0, ptr) } get_page_size :: proc() -> int { // NOTE(tetra): The page size never changes, so why do anything complicated // if we don't have to. - @static page_size := -1; + @static page_size := -1 if page_size != -1 { - return page_size; + return page_size } - info: win32.SYSTEM_INFO; - win32.GetSystemInfo(&info); - page_size = int(info.dwPageSize); - return page_size; + info: win32.SYSTEM_INFO + win32.GetSystemInfo(&info) + page_size = int(info.dwPageSize) + return page_size } exit :: proc "contextless" (code: int) -> ! { - win32.ExitProcess(win32.DWORD(code)); + win32.ExitProcess(win32.DWORD(code)) } current_thread_id :: proc "contextless" () -> int { - return int(win32.GetCurrentThreadId()); + return int(win32.GetCurrentThreadId()) } _alloc_command_line_arguments :: proc() -> []string { - arg_count: i32; - arg_list_ptr := win32.CommandLineToArgvW(win32.GetCommandLineW(), &arg_count); - arg_list := make([]string, int(arg_count)); + arg_count: i32 + arg_list_ptr := win32.CommandLineToArgvW(win32.GetCommandLineW(), &arg_count) + arg_list := make([]string, int(arg_count)) for _, i in arg_list { - wc_str := (^win32.wstring)(uintptr(arg_list_ptr) + size_of(win32.wstring)*uintptr(i))^; + wc_str := (^win32.wstring)(uintptr(arg_list_ptr) + size_of(win32.wstring)*uintptr(i))^ olen := win32.WideCharToMultiByte(win32.CP_UTF8, 0, wc_str, -1, - nil, 0, nil, nil); + nil, 0, nil, nil) - buf := make([]byte, int(olen)); + buf := make([]byte, int(olen)) n := win32.WideCharToMultiByte(win32.CP_UTF8, 0, wc_str, -1, - raw_data(buf), olen, nil, nil); + raw_data(buf), olen, nil, nil) if n > 0 { - n -= 1; + n -= 1 } - arg_list[i] = string(buf[:n]); + arg_list[i] = string(buf[:n]) } - return arg_list; + return arg_list } /* @@ -170,46 +170,46 @@ _alloc_command_line_arguments :: proc() -> []string { TODO: Narrow down this range once Win 11 is published and the last Win 10 builds become available. */ -WINDOWS_11_BUILD_CUTOFF :: 22_000; +WINDOWS_11_BUILD_CUTOFF :: 22_000 get_windows_version_w :: proc() -> win32.OSVERSIONINFOEXW { - osvi : win32.OSVERSIONINFOEXW; - osvi.dwOSVersionInfoSize = size_of(win32.OSVERSIONINFOEXW); - win32.RtlGetVersion(&osvi); - return osvi; + osvi : win32.OSVERSIONINFOEXW + osvi.dwOSVersionInfoSize = size_of(win32.OSVERSIONINFOEXW) + win32.RtlGetVersion(&osvi) + return osvi } is_windows_xp :: proc() -> bool { - osvi := get_windows_version_w(); - return (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1); + osvi := get_windows_version_w() + return (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) } is_windows_vista :: proc() -> bool { - osvi := get_windows_version_w(); - return (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0); + osvi := get_windows_version_w() + return (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0) } is_windows_7 :: proc() -> bool { - osvi := get_windows_version_w(); - return (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 1); + osvi := get_windows_version_w() + return (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 1) } is_windows_8 :: proc() -> bool { - osvi := get_windows_version_w(); - return (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 2); + osvi := get_windows_version_w() + return (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 2) } is_windows_8_1 :: proc() -> bool { - osvi := get_windows_version_w(); - return (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 3); + osvi := get_windows_version_w() + return (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 3) } is_windows_10 :: proc() -> bool { - osvi := get_windows_version_w(); - return (osvi.dwMajorVersion == 10 && osvi.dwMinorVersion == 0 && osvi.dwBuildNumber < WINDOWS_11_BUILD_CUTOFF); + osvi := get_windows_version_w() + return (osvi.dwMajorVersion == 10 && osvi.dwMinorVersion == 0 && osvi.dwBuildNumber < WINDOWS_11_BUILD_CUTOFF) } is_windows_11 :: proc() -> bool { - osvi := get_windows_version_w(); - return (osvi.dwMajorVersion == 10 && osvi.dwMinorVersion == 0 && osvi.dwBuildNumber >= WINDOWS_11_BUILD_CUTOFF); + osvi := get_windows_version_w() + return (osvi.dwMajorVersion == 10 && osvi.dwMinorVersion == 0 && osvi.dwBuildNumber >= WINDOWS_11_BUILD_CUTOFF) }
\ No newline at end of file diff --git a/core/os/stat.odin b/core/os/stat.odin index 7d766e2e8..6f4c8b0ef 100644 --- a/core/os/stat.odin +++ b/core/os/stat.odin @@ -16,19 +16,19 @@ File_Info :: struct { file_info_slice_delete :: proc(infos: []File_Info, allocator := context.allocator) { for i := len(infos)-1; i >= 0; i -= 1 { - file_info_delete(infos[i], allocator); + file_info_delete(infos[i], allocator) } - delete(infos, allocator); + delete(infos, allocator) } file_info_delete :: proc(fi: File_Info, allocator := context.allocator) { - delete(fi.fullpath, allocator); + delete(fi.fullpath, allocator) } -File_Mode :: distinct u32; +File_Mode :: distinct u32 -File_Mode_Dir :: File_Mode(1<<16); -File_Mode_Named_Pipe :: File_Mode(1<<17); -File_Mode_Device :: File_Mode(1<<18); -File_Mode_Char_Device :: File_Mode(1<<19); -File_Mode_Sym_Link :: File_Mode(1<<20); +File_Mode_Dir :: File_Mode(1<<16) +File_Mode_Named_Pipe :: File_Mode(1<<17) +File_Mode_Device :: File_Mode(1<<18) +File_Mode_Char_Device :: File_Mode(1<<19) +File_Mode_Sym_Link :: File_Mode(1<<20) diff --git a/core/os/stat_windows.odin b/core/os/stat_windows.odin index f76efa60f..d7181f089 100644 --- a/core/os/stat_windows.odin +++ b/core/os/stat_windows.odin @@ -5,312 +5,312 @@ import win32 "core:sys/windows" @(private) full_path_from_name :: proc(name: string, allocator := context.allocator) -> (path: string, err: Errno) { - name := name; + name := name if name == "" { - name = "."; + name = "." } - p := win32.utf8_to_utf16(name, context.temp_allocator); - buf := make([dynamic]u16, 100, allocator); - defer delete(buf); + p := win32.utf8_to_utf16(name, context.temp_allocator) + buf := make([dynamic]u16, 100, allocator) + defer delete(buf) for { - n := win32.GetFullPathNameW(raw_data(p), u32(len(buf)), raw_data(buf), nil); + n := win32.GetFullPathNameW(raw_data(p), u32(len(buf)), raw_data(buf), nil) if n == 0 { - return "", Errno(win32.GetLastError()); + return "", Errno(win32.GetLastError()) } if n <= u32(len(buf)) { - return win32.utf16_to_utf8(buf[:n], allocator), ERROR_NONE; + return win32.utf16_to_utf8(buf[:n], allocator), ERROR_NONE } - resize(&buf, len(buf)*2); + resize(&buf, len(buf)*2) } - return; + return } @(private) _stat :: proc(name: string, create_file_attributes: u32, allocator := context.allocator) -> (fi: File_Info, e: Errno) { if len(name) == 0 { - return {}, ERROR_PATH_NOT_FOUND; + return {}, ERROR_PATH_NOT_FOUND } - context.allocator = allocator; + context.allocator = allocator - wname := win32.utf8_to_wstring(fix_long_path(name), context.temp_allocator); - fa: win32.WIN32_FILE_ATTRIBUTE_DATA; - ok := win32.GetFileAttributesExW(wname, win32.GetFileExInfoStandard, &fa); + wname := win32.utf8_to_wstring(fix_long_path(name), context.temp_allocator) + fa: win32.WIN32_FILE_ATTRIBUTE_DATA + ok := win32.GetFileAttributesExW(wname, win32.GetFileExInfoStandard, &fa) if ok && fa.dwFileAttributes & win32.FILE_ATTRIBUTE_REPARSE_POINT == 0 { // Not a symlink - return file_info_from_win32_file_attribute_data(&fa, name); + return file_info_from_win32_file_attribute_data(&fa, name) } - err := 0 if ok else win32.GetLastError(); + err := 0 if ok else win32.GetLastError() if err == win32.ERROR_SHARING_VIOLATION { - fd: win32.WIN32_FIND_DATAW; - sh := win32.FindFirstFileW(wname, &fd); + fd: win32.WIN32_FIND_DATAW + sh := win32.FindFirstFileW(wname, &fd) if sh == win32.INVALID_HANDLE_VALUE { - e = Errno(win32.GetLastError()); - return; + e = Errno(win32.GetLastError()) + return } - win32.FindClose(sh); + win32.FindClose(sh) - return file_info_from_win32_find_data(&fd, name); + return file_info_from_win32_find_data(&fd, name) } - h := win32.CreateFileW(wname, 0, 0, nil, win32.OPEN_EXISTING, create_file_attributes, nil); + h := win32.CreateFileW(wname, 0, 0, nil, win32.OPEN_EXISTING, create_file_attributes, nil) if h == win32.INVALID_HANDLE_VALUE { - e = Errno(win32.GetLastError()); - return; + e = Errno(win32.GetLastError()) + return } - defer win32.CloseHandle(h); - return file_info_from_get_file_information_by_handle(name, h); + defer win32.CloseHandle(h) + return file_info_from_get_file_information_by_handle(name, h) } lstat :: proc(name: string, allocator := context.allocator) -> (File_Info, Errno) { - attrs := win32.FILE_FLAG_BACKUP_SEMANTICS; - attrs |= win32.FILE_FLAG_OPEN_REPARSE_POINT; - return _stat(name, attrs, allocator); + attrs := win32.FILE_FLAG_BACKUP_SEMANTICS + attrs |= win32.FILE_FLAG_OPEN_REPARSE_POINT + return _stat(name, attrs, allocator) } stat :: proc(name: string, allocator := context.allocator) -> (File_Info, Errno) { - attrs := win32.FILE_FLAG_BACKUP_SEMANTICS; - return _stat(name, attrs, allocator); + attrs := win32.FILE_FLAG_BACKUP_SEMANTICS + return _stat(name, attrs, allocator) } fstat :: proc(fd: Handle, allocator := context.allocator) -> (File_Info, Errno) { if fd == 0 { - return {}, ERROR_INVALID_HANDLE; + return {}, ERROR_INVALID_HANDLE } - context.allocator = allocator; + context.allocator = allocator - path, err := cleanpath_from_handle(fd); + path, err := cleanpath_from_handle(fd) if err != ERROR_NONE { - return {}, err; + return {}, err } - h := win32.HANDLE(fd); + h := win32.HANDLE(fd) switch win32.GetFileType(h) { case win32.FILE_TYPE_PIPE, win32.FILE_TYPE_CHAR: - fi: File_Info; - fi.fullpath = path; - fi.name = basename(path); - fi.mode |= file_type_mode(h); - return fi, ERROR_NONE; + fi: File_Info + fi.fullpath = path + fi.name = basename(path) + fi.mode |= file_type_mode(h) + return fi, ERROR_NONE } - return file_info_from_get_file_information_by_handle(path, h); + return file_info_from_get_file_information_by_handle(path, h) } @(private) cleanpath_strip_prefix :: proc(buf: []u16) -> []u16 { - buf := buf; - N := 0; + buf := buf + N := 0 for c, i in buf { if c == 0 { break; } - N = i+1; + N = i+1 } - buf = buf[:N]; + buf = buf[:N] if len(buf) >= 4 { if buf[0] == '\\' && buf[1] == '\\' && buf[2] == '?' && buf[3] == '\\' { - buf = buf[4:]; + buf = buf[4:] } } - return buf; + return buf } @(private) cleanpath_from_handle :: proc(fd: Handle) -> (string, Errno) { if fd == 0 { - return "", ERROR_INVALID_HANDLE; + return "", ERROR_INVALID_HANDLE } - h := win32.HANDLE(fd); + h := win32.HANDLE(fd) - MAX_PATH := win32.DWORD(260) + 1; - buf: []u16; + MAX_PATH := win32.DWORD(260) + 1 + buf: []u16 for { - buf = make([]u16, MAX_PATH, context.temp_allocator); - err := win32.GetFinalPathNameByHandleW(h, raw_data(buf), MAX_PATH, 0); + buf = make([]u16, MAX_PATH, context.temp_allocator) + err := win32.GetFinalPathNameByHandleW(h, raw_data(buf), MAX_PATH, 0) switch Errno(err) { case ERROR_PATH_NOT_FOUND, ERROR_INVALID_PARAMETER: - return "", Errno(err); + return "", Errno(err) case ERROR_NOT_ENOUGH_MEMORY: - MAX_PATH = MAX_PATH*2 + 1; - continue; + MAX_PATH = MAX_PATH*2 + 1 + continue } - break; + break } - return cleanpath_from_buf(buf), ERROR_NONE; + return cleanpath_from_buf(buf), ERROR_NONE } @(private) cleanpath_from_handle_u16 :: proc(fd: Handle) -> ([]u16, Errno) { if fd == 0 { - return nil, ERROR_INVALID_HANDLE; + return nil, ERROR_INVALID_HANDLE } - h := win32.HANDLE(fd); + h := win32.HANDLE(fd) - MAX_PATH := win32.DWORD(260) + 1; - buf: []u16; + MAX_PATH := win32.DWORD(260) + 1 + buf: []u16 for { - buf = make([]u16, MAX_PATH, context.temp_allocator); - err := win32.GetFinalPathNameByHandleW(h, raw_data(buf), MAX_PATH, 0); + buf = make([]u16, MAX_PATH, context.temp_allocator) + err := win32.GetFinalPathNameByHandleW(h, raw_data(buf), MAX_PATH, 0) switch Errno(err) { case ERROR_PATH_NOT_FOUND, ERROR_INVALID_PARAMETER: - return nil, Errno(err); + return nil, Errno(err) case ERROR_NOT_ENOUGH_MEMORY: - MAX_PATH = MAX_PATH*2 + 1; - continue; + MAX_PATH = MAX_PATH*2 + 1 + continue } - break; + break } - return cleanpath_strip_prefix(buf), ERROR_NONE; + return cleanpath_strip_prefix(buf), ERROR_NONE } @(private) cleanpath_from_buf :: proc(buf: []u16) -> string { - buf := buf; - buf = cleanpath_strip_prefix(buf); - return win32.utf16_to_utf8(buf, context.allocator); + buf := buf + buf = cleanpath_strip_prefix(buf) + return win32.utf16_to_utf8(buf, context.allocator) } @(private) basename :: proc(name: string) -> (base: string) { - name := name; + name := name if len(name) > 3 && name[:3] == `\\?` { - name = name[3:]; + name = name[3:] } if len(name) == 2 && name[1] == ':' { - return "."; + return "." } else if len(name) > 2 && name[1] == ':' { - name = name[2:]; + name = name[2:] } - i := len(name)-1; + i := len(name)-1 for ; i > 0 && (name[i] == '/' || name[i] == '\\'); i -= 1 { - name = name[:i]; + name = name[:i] } for i -= 1; i >= 0; i -= 1 { if name[i] == '/' || name[i] == '\\' { - name = name[i+1:]; - break; + name = name[i+1:] + break } } - return name; + return name } @(private) file_type_mode :: proc(h: win32.HANDLE) -> File_Mode { switch win32.GetFileType(h) { case win32.FILE_TYPE_PIPE: - return File_Mode_Named_Pipe; + return File_Mode_Named_Pipe case win32.FILE_TYPE_CHAR: - return File_Mode_Device | File_Mode_Char_Device; + return File_Mode_Device | File_Mode_Char_Device } - return 0; + return 0 } @(private) file_mode_from_file_attributes :: proc(FileAttributes: win32.DWORD, h: win32.HANDLE, ReparseTag: win32.DWORD) -> (mode: File_Mode) { if FileAttributes & win32.FILE_ATTRIBUTE_READONLY != 0 { - mode |= 0o444; + mode |= 0o444 } else { - mode |= 0o666; + mode |= 0o666 } - is_sym := false; + is_sym := false if FileAttributes & win32.FILE_ATTRIBUTE_REPARSE_POINT == 0 { - is_sym = false; + is_sym = false } else { - is_sym = ReparseTag == win32.IO_REPARSE_TAG_SYMLINK || ReparseTag == win32.IO_REPARSE_TAG_MOUNT_POINT; + is_sym = ReparseTag == win32.IO_REPARSE_TAG_SYMLINK || ReparseTag == win32.IO_REPARSE_TAG_MOUNT_POINT } if is_sym { - mode |= File_Mode_Sym_Link; + mode |= File_Mode_Sym_Link } else { if FileAttributes & win32.FILE_ATTRIBUTE_DIRECTORY != 0 { - mode |= 0o111 | File_Mode_Dir; + mode |= 0o111 | File_Mode_Dir } if h != nil { - mode |= file_type_mode(h); + mode |= file_type_mode(h) } } - return; + return } @(private) file_info_from_win32_file_attribute_data :: proc(d: ^win32.WIN32_FILE_ATTRIBUTE_DATA, name: string) -> (fi: File_Info, e: Errno) { - fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow); + fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow) - fi.mode |= file_mode_from_file_attributes(d.dwFileAttributes, nil, 0); - fi.is_dir = fi.mode & File_Mode_Dir != 0; + fi.mode |= file_mode_from_file_attributes(d.dwFileAttributes, nil, 0) + fi.is_dir = fi.mode & File_Mode_Dir != 0 - fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime)); - fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime)); - fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime)); + fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime)) + fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime)) + fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime)) - fi.fullpath, e = full_path_from_name(name); - fi.name = basename(fi.fullpath); + fi.fullpath, e = full_path_from_name(name) + fi.name = basename(fi.fullpath) - return; + return } @(private) file_info_from_win32_find_data :: proc(d: ^win32.WIN32_FIND_DATAW, name: string) -> (fi: File_Info, e: Errno) { - fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow); + fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow) - fi.mode |= file_mode_from_file_attributes(d.dwFileAttributes, nil, 0); - fi.is_dir = fi.mode & File_Mode_Dir != 0; + fi.mode |= file_mode_from_file_attributes(d.dwFileAttributes, nil, 0) + fi.is_dir = fi.mode & File_Mode_Dir != 0 - fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime)); - fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime)); - fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime)); + fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime)) + fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime)) + fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime)) - fi.fullpath, e = full_path_from_name(name); - fi.name = basename(fi.fullpath); + fi.fullpath, e = full_path_from_name(name) + fi.name = basename(fi.fullpath) - return; + return } @(private) file_info_from_get_file_information_by_handle :: proc(path: string, h: win32.HANDLE) -> (File_Info, Errno) { - d: win32.BY_HANDLE_FILE_INFORMATION; + d: win32.BY_HANDLE_FILE_INFORMATION if !win32.GetFileInformationByHandle(h, &d) { - err := Errno(win32.GetLastError()); - return {}, err; + err := Errno(win32.GetLastError()) + return {}, err } - ti: win32.FILE_ATTRIBUTE_TAG_INFO; + ti: win32.FILE_ATTRIBUTE_TAG_INFO if !win32.GetFileInformationByHandleEx(h, .FileAttributeTagInfo, &ti, size_of(ti)) { - err := win32.GetLastError(); + err := win32.GetLastError() if err != u32(ERROR_INVALID_PARAMETER) { - return {}, Errno(err); + return {}, Errno(err) } // Indicate this is a symlink on FAT file systems - ti.ReparseTag = 0; + ti.ReparseTag = 0 } - fi: File_Info; + fi: File_Info - fi.fullpath = path; - fi.name = basename(path); - fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow); + fi.fullpath = path + fi.name = basename(path) + fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow) - fi.mode |= file_mode_from_file_attributes(ti.FileAttributes, h, ti.ReparseTag); - fi.is_dir = fi.mode & File_Mode_Dir != 0; + fi.mode |= file_mode_from_file_attributes(ti.FileAttributes, h, ti.ReparseTag) + fi.is_dir = fi.mode & File_Mode_Dir != 0 - fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime)); - fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime)); - fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime)); + fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime)) + fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime)) + fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime)) - return fi, ERROR_NONE; + return fi, ERROR_NONE } diff --git a/core/os/stream.odin b/core/os/stream.odin index db310e6ec..f80633a3f 100644 --- a/core/os/stream.odin +++ b/core/os/stream.odin @@ -3,67 +3,67 @@ package os import "core:io" stream_from_handle :: proc(fd: Handle) -> io.Stream { - s: io.Stream; - s.stream_data = rawptr(uintptr(fd)); - s.stream_vtable = _file_stream_vtable; - return s; + s: io.Stream + s.stream_data = rawptr(uintptr(fd)) + s.stream_vtable = _file_stream_vtable + return s } @(private) _file_stream_vtable := &io.Stream_VTable{ impl_read = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) { - fd := Handle(uintptr(s.stream_data)); - os_err: Errno; - n, os_err = read(fd, p); - return; + fd := Handle(uintptr(s.stream_data)) + os_err: Errno + n, os_err = read(fd, p) + return }, impl_read_at = proc(s: io.Stream, p: []byte, offset: i64) -> (n: int, err: io.Error) { when ODIN_OS == "windows" { - fd := Handle(uintptr(s.stream_data)); - os_err: Errno; - n, os_err = read_at(fd, p, offset); + fd := Handle(uintptr(s.stream_data)) + os_err: Errno + n, os_err = read_at(fd, p, offset) } - return; + return }, impl_write = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) { - fd := Handle(uintptr(s.stream_data)); - os_err: Errno; - n, os_err = write(fd, p); - return; + fd := Handle(uintptr(s.stream_data)) + os_err: Errno + n, os_err = write(fd, p) + return }, impl_write_at = proc(s: io.Stream, p: []byte, offset: i64) -> (n: int, err: io.Error) { when ODIN_OS == "windows" { - fd := Handle(uintptr(s.stream_data)); - os_err: Errno; - n, os_err = write_at(fd, p, offset); - _ = os_err; + fd := Handle(uintptr(s.stream_data)) + os_err: Errno + n, os_err = write_at(fd, p, offset) + _ = os_err } - return; + return }, impl_seek = proc(s: io.Stream, offset: i64, whence: io.Seek_From) -> (i64, io.Error) { - fd := Handle(uintptr(s.stream_data)); - n, os_err := seek(fd, offset, int(whence)); - _ = os_err; - return n, nil; + fd := Handle(uintptr(s.stream_data)) + n, os_err := seek(fd, offset, int(whence)) + _ = os_err + return n, nil }, impl_size = proc(s: io.Stream) -> i64 { - fd := Handle(uintptr(s.stream_data)); - sz, _ := file_size(fd); - return sz; + fd := Handle(uintptr(s.stream_data)) + sz, _ := file_size(fd) + return sz }, impl_flush = proc(s: io.Stream) -> io.Error { when ODIN_OS == "windows" { - fd := Handle(uintptr(s.stream_data)); - flush(fd); + fd := Handle(uintptr(s.stream_data)) + flush(fd) } else { // TOOD(bill): other operating systems } - return nil; + return nil }, impl_close = proc(s: io.Stream) -> io.Error { - fd := Handle(uintptr(s.stream_data)); - close(fd); - return nil; + fd := Handle(uintptr(s.stream_data)) + close(fd) + return nil }, -}; +} diff --git a/core/path/filepath/match.odin b/core/path/filepath/match.odin index de65a9d41..cba44953d 100644 --- a/core/path/filepath/match.odin +++ b/core/path/filepath/match.odin @@ -33,181 +33,181 @@ Match_Error :: enum { // NOTE(bill): This is effectively the shell pattern matching system found // match :: proc(pattern, name: string) -> (matched: bool, err: Match_Error) { - pattern, name := pattern, name; + pattern, name := pattern, name pattern_loop: for len(pattern) > 0 { - star: bool; - chunk: string; - star, chunk, pattern = scan_chunk(pattern); + star: bool + chunk: string + star, chunk, pattern = scan_chunk(pattern) if star && chunk == "" { - return !strings.contains(name, SEPARATOR_STRING), .None; + return !strings.contains(name, SEPARATOR_STRING), .None } - t: string; - ok: bool; - t, ok, err = match_chunk(chunk, name); + t: string + ok: bool + t, ok, err = match_chunk(chunk, name) if ok && (len(t) == 0 || len(pattern) > 0) { - name = t; - continue; + name = t + continue } if err != .None { - return; + return } if star { for i := 0; i < len(name) && name[i] != SEPARATOR; i += 1 { - t, ok, err = match_chunk(chunk, name[i+1:]); + t, ok, err = match_chunk(chunk, name[i+1:]) if ok { if len(pattern) == 0 && len(t) > 0 { - continue; + continue } - name = t; - continue pattern_loop; + name = t + continue pattern_loop } if err != .None { - return; + return } } } - return false, .None; + return false, .None } - return len(name) == 0, .None; + return len(name) == 0, .None } @(private="file") scan_chunk :: proc(pattern: string) -> (star: bool, chunk, rest: string) { - pattern := pattern; + pattern := pattern for len(pattern) > 0 && pattern[0] == '*' { - pattern = pattern[1:]; - star = true; + pattern = pattern[1:] + star = true } - in_range, i := false, 0; + in_range, i := false, 0 scan_loop: for i = 0; i < len(pattern); i += 1 { switch pattern[i] { case '\\': when ODIN_OS != "windows" { if i+1 < len(pattern) { - i += 1; + i += 1 } } case '[': - in_range = true; + in_range = true case ']': - in_range = false; + in_range = false case '*': if !in_range { - break scan_loop; + break scan_loop } } } - return star, pattern[:i], pattern[i:]; + return star, pattern[:i], pattern[i:] } @(private="file") match_chunk :: proc(chunk, s: string) -> (rest: string, ok: bool, err: Match_Error) { - chunk, s := chunk, s; + chunk, s := chunk, s for len(chunk) > 0 { if len(s) == 0 { - return; + return } switch chunk[0] { case '[': - r, w := utf8.decode_rune_in_string(s); - s = s[w:]; - chunk = chunk[1:]; - is_negated := false; + r, w := utf8.decode_rune_in_string(s) + s = s[w:] + chunk = chunk[1:] + is_negated := false if len(chunk) > 0 && chunk[0] == '^' { - is_negated = true; - chunk = chunk[1:]; + is_negated = true + chunk = chunk[1:] } - match := false; - range_count := 0; + match := false + range_count := 0 for { if len(chunk) > 0 && chunk[0] == ']' && range_count > 0 { - chunk = chunk[1:]; - break; + chunk = chunk[1:] + break } - lo, hi: rune; + lo, hi: rune if lo, chunk, err = get_escape(chunk); err != .None { - return; + return } - hi = lo; + hi = lo if chunk[0] == '-' { if hi, chunk, err = get_escape(chunk[1:]); err != .None { - return; + return } } if lo <= r && r <= hi { - match = true; + match = true } - range_count += 1; + range_count += 1 } if match == is_negated { - return; + return } case '?': if s[0] == SEPARATOR { - return; + return } - _, w := utf8.decode_rune_in_string(s); - s = s[w:]; - chunk = chunk[1:]; + _, w := utf8.decode_rune_in_string(s) + s = s[w:] + chunk = chunk[1:] case '\\': when ODIN_OS != "windows" { - chunk = chunk[1:]; + chunk = chunk[1:] if len(chunk) == 0 { - err = .Syntax_Error; - return; + err = .Syntax_Error + return } } - fallthrough; + fallthrough case: if chunk[0] != s[0] { - return; + return } - s = s[1:]; - chunk = chunk[1:]; + s = s[1:] + chunk = chunk[1:] } } - return s, true, .None; + return s, true, .None } @(private="file") get_escape :: proc(chunk: string) -> (r: rune, next_chunk: string, err: Match_Error) { if len(chunk) == 0 || chunk[0] == '-' || chunk[0] == ']' { - err = .Syntax_Error; - return; + err = .Syntax_Error + return } - chunk := chunk; + chunk := chunk if chunk[0] == '\\' && ODIN_OS != "windows" { - chunk = chunk[1:]; + chunk = chunk[1:] if len(chunk) == 0 { - err = .Syntax_Error; - return; + err = .Syntax_Error + return } } - w: int; - r, w = utf8.decode_rune_in_string(chunk); + w: int + r, w = utf8.decode_rune_in_string(chunk) if r == utf8.RUNE_ERROR && w == 1 { - err = .Syntax_Error; + err = .Syntax_Error } - next_chunk = chunk[w:]; + next_chunk = chunk[w:] if len(next_chunk) == 0 { - err = .Syntax_Error; + err = .Syntax_Error } - return; + return } @@ -222,128 +222,128 @@ get_escape :: proc(chunk: string) -> (r: rune, next_chunk: string, err: Match_Er glob :: proc(pattern: string, allocator := context.allocator) -> (matches: []string, err: Match_Error) { if !has_meta(pattern) { // TODO(bill): os.lstat on here to check for error - m := make([]string, 1, allocator); - m[0] = pattern; - return m[:], .None; + m := make([]string, 1, allocator) + m[0] = pattern + return m[:], .None } - temp_buf: [8]byte; + temp_buf: [8]byte - dir, file := split(pattern); - volume_len := 0; + dir, file := split(pattern) + volume_len := 0 when ODIN_OS == "windows" { - volume_len, dir = clean_glob_path_windows(dir, temp_buf[:]); + volume_len, dir = clean_glob_path_windows(dir, temp_buf[:]) } else { - dir = clean_glob_path(dir); + dir = clean_glob_path(dir) } if !has_meta(dir[volume_len:]) { - m, e := _glob(dir, file, nil); - return m[:], e; + m, e := _glob(dir, file, nil) + return m[:], e } - m: []string; - m, err = glob(dir); + m: []string + m, err = glob(dir) if err != .None { - return; + return } - dmatches := make([dynamic]string, 0, 0, allocator); + dmatches := make([dynamic]string, 0, 0, allocator) for d in m { - dmatches, err = _glob(d, file, &dmatches); + dmatches, err = _glob(d, file, &dmatches) if err != .None { - break; + break } } if len(dmatches) > 0 { - matches = dmatches[:]; + matches = dmatches[:] } - return; + return } _glob :: proc(dir, pattern: string, matches: ^[dynamic]string) -> (m: [dynamic]string, e: Match_Error) { if matches != nil { - m = matches^; + m = matches^ } else { - m = make([dynamic]string, 0, 0, context.allocator); + m = make([dynamic]string, 0, 0, context.allocator) } - d, derr := os.open(dir); + d, derr := os.open(dir) if derr != 0 { - return; + return } - defer os.close(d); + defer os.close(d) { - file_info, ferr := os.fstat(d); - defer os.file_info_delete(file_info); + file_info, ferr := os.fstat(d) + defer os.file_info_delete(file_info) if ferr != 0 { - return; + return } if !file_info.is_dir { - return; + return } } - fis, _ := os.read_dir(d, -1); + fis, _ := os.read_dir(d, -1) slice.sort_by(fis, proc(a, b: os.File_Info) -> bool { - return a.name < b.name; - }); + return a.name < b.name + }) defer { for fi in fis { - os.file_info_delete(fi); + os.file_info_delete(fi) } - delete(fis); + delete(fis) } for fi in fis { - n := fi.name; - matched := match(pattern, n) or_return; + n := fi.name + matched := match(pattern, n) or_return if matched { - append(&m, join(dir, n)); + append(&m, join(dir, n)) } } - return; + return } @(private) has_meta :: proc(path: string) -> bool { when ODIN_OS == "windows" { - CHARS :: `*?[`; + CHARS :: `*?[` } else { - CHARS :: `*?[\`; + CHARS :: `*?[\` } - return strings.contains_any(path, CHARS); + return strings.contains_any(path, CHARS) } @(private) clean_glob_path :: proc(path: string) -> string { switch path { case "": - return "."; + return "." case SEPARATOR_STRING: - return path; + return path } - return path[:len(path)-1]; + return path[:len(path)-1] } @(private) clean_glob_path_windows :: proc(path: string, temp_buf: []byte) -> (prefix_len: int, cleaned: string) { - vol_len := volume_name_len(path); + vol_len := volume_name_len(path) switch { case path == "": - return 0, "."; + return 0, "." case vol_len+1 == len(path) && is_separator(path[len(path)-1]): // /, \, C:\, C:/ - return vol_len+1, path; + return vol_len+1, path case vol_len == len(path) && len(path) == 2: // C: - copy(temp_buf[:], path); - temp_buf[2] = '.'; - return vol_len, string(temp_buf[:3]); + copy(temp_buf[:], path) + temp_buf[2] = '.' + return vol_len, string(temp_buf[:3]) } if vol_len >= len(path) { - vol_len = len(path) -1; + vol_len = len(path) -1 } - return vol_len, path[:len(path)-1]; + return vol_len, path[:len(path)-1] } diff --git a/core/path/filepath/path.odin b/core/path/filepath/path.odin index 7dd7484f0..39cd80a47 100644 --- a/core/path/filepath/path.odin +++ b/core/path/filepath/path.odin @@ -7,40 +7,40 @@ import "core:strings" // is_separator checks whether the byte is a valid separator character is_separator :: proc(c: byte) -> bool { switch c { - case '/': return true; - case '\\': return ODIN_OS == "windows"; + case '/': return true + case '\\': return ODIN_OS == "windows" } - return false; + return false } @(private) is_slash :: proc(c: byte) -> bool { - return c == '\\' || c == '/'; + return c == '\\' || c == '/' } split :: proc(path: string) -> (dir, file: string) { - vol := volume_name(path); - i := len(path) - 1; + vol := volume_name(path) + i := len(path) - 1 for i >= len(vol) && !is_separator(path[i]) { - i -= 1; + i -= 1 } - return path[:i+1], path[i+1:]; + return path[:i+1], path[i+1:] } volume_name :: proc(path: string) -> string { - return path[:volume_name_len(path)]; + return path[:volume_name_len(path)] } volume_name_len :: proc(path: string) -> int { if ODIN_OS == "windows" { if len(path) < 2 { - return 0; + return 0 } - c := path[0]; + c := path[0] if path[1] == ':' { switch c { case 'a'..='z', 'A'..='Z': - return 2; + return 2 } } @@ -49,153 +49,153 @@ volume_name_len :: proc(path: string) -> int { !is_slash(path[2]) && path[2] != '.' { for n := 3; n < l-1; n += 1 { if is_slash(path[n]) { - n += 1; + n += 1 if !is_slash(path[n]) { if path[n] == '.' { - break; + break } } for ; n < l; n += 1 { if is_slash(path[n]) { - break; + break } } - return n; + return n } - break; + break } } } - return 0; + return 0 } base :: proc(path: string) -> string { if path == "" { - return "."; + return "." } - path := path; + path := path for len(path) > 0 && is_separator(path[len(path)-1]) { - path = path[:len(path)-1]; + path = path[:len(path)-1] } - path = path[volume_name_len(path):]; + path = path[volume_name_len(path):] - i := len(path)-1; + i := len(path)-1 for i >= 0 && !is_separator(path[i]) { - i -= 1; + i -= 1 } if i >= 0 { - path = path[i+1:]; + path = path[i+1:] } if path == "" { - return SEPARATOR_STRING; + return SEPARATOR_STRING } - return path; + return path } clean :: proc(path: string, allocator := context.allocator) -> string { - context.allocator = allocator; + context.allocator = allocator - path := path; - original_path := path; - vol_len := volume_name_len(path); - path = path[vol_len:]; + path := path + original_path := path + vol_len := volume_name_len(path) + path = path[vol_len:] if path == "" { if vol_len > 1 && original_path[1] != ':' { - s, ok := from_slash(original_path); + s, ok := from_slash(original_path) if !ok { - s = strings.clone(s); + s = strings.clone(s) } - return s; + return s } - return strings.concatenate({original_path, "."}); + return strings.concatenate({original_path, "."}) } - rooted := is_separator(path[0]); + rooted := is_separator(path[0]) - n := len(path); + n := len(path) out := &Lazy_Buffer{ s = path, vol_and_path = original_path, vol_len = vol_len, - }; + } - r, dot_dot := 0, 0; + r, dot_dot := 0, 0 if rooted { - lazy_buffer_append(out, SEPARATOR); - r, dot_dot = 1, 1; + lazy_buffer_append(out, SEPARATOR) + r, dot_dot = 1, 1 } for r < n { switch { case is_separator(path[r]): - r += 1; + r += 1 case path[r] == '.' && (r+1 == n || is_separator(path[r+1])): - r += 1; + r += 1 case path[r] == '.' && path[r+1] == '.' && (r+2 == n || is_separator(path[r+2])): - r += 2; + r += 2 switch { case out.w > dot_dot: - out.w -= 1; + out.w -= 1 for out.w > dot_dot && !is_separator(lazy_buffer_index(out, out.w)) { - out.w -= 1; + out.w -= 1 } case !rooted: if out.w > 0 { - lazy_buffer_append(out, SEPARATOR); + lazy_buffer_append(out, SEPARATOR) } - lazy_buffer_append(out, '.'); - lazy_buffer_append(out, '.'); - dot_dot = out.w; + lazy_buffer_append(out, '.') + lazy_buffer_append(out, '.') + dot_dot = out.w } case: if rooted && out.w != 1 || !rooted && out.w != 0 { - lazy_buffer_append(out, SEPARATOR); + lazy_buffer_append(out, SEPARATOR) } for ; r < n && !is_separator(path[r]); r += 1 { - lazy_buffer_append(out, path[r]); + lazy_buffer_append(out, path[r]) } } } if out.w == 0 { - lazy_buffer_append(out, '.'); + lazy_buffer_append(out, '.') } - s := lazy_buffer_string(out); - cleaned, new_allocation := from_slash(s); + s := lazy_buffer_string(out) + cleaned, new_allocation := from_slash(s) if new_allocation { - delete(s); - lazy_buffer_destroy(out); + delete(s) + lazy_buffer_destroy(out) } - return cleaned; + return cleaned } from_slash :: proc(path: string, allocator := context.allocator) -> (new_path: string, new_allocation: bool) { if SEPARATOR == '/' { - return path, false; + return path, false } - return strings.replace_all(path, "/", SEPARATOR_STRING, allocator); + return strings.replace_all(path, "/", SEPARATOR_STRING, allocator) } to_slash :: proc(path: string, allocator := context.allocator) -> (new_path: string, new_allocation: bool) { if SEPARATOR == '/' { - return path, false; + return path, false } - return strings.replace_all(path, SEPARATOR_STRING, "/", allocator); + return strings.replace_all(path, SEPARATOR_STRING, "/", allocator) } ext :: proc(path: string) -> string { for i := len(path)-1; i >= 0 && !is_separator(path[i]); i -= 1 { if path[i] == '.' { - return path[i:]; + return path[i:] } } - return ""; + return "" } @@ -206,145 +206,145 @@ Relative_Error :: enum { } rel :: proc(base_path, target_path: string, allocator := context.allocator) -> (string, Relative_Error) { - context.allocator = allocator; - base_clean, target_clean := clean(base_path), clean(target_path); + context.allocator = allocator + base_clean, target_clean := clean(base_path), clean(target_path) - delete_target := true; + delete_target := true defer { if delete_target { - delete(target_clean); + delete(target_clean) } - delete(base_clean); + delete(base_clean) } if strings.equal_fold(target_clean, base_clean) { - return strings.clone("."), .None; + return strings.clone("."), .None } - base_vol, target_vol := volume_name(base_path), volume_name(target_path); - base := base_clean[len(base_vol):]; - target := target_clean[len(target_vol):]; + base_vol, target_vol := volume_name(base_path), volume_name(target_path) + base := base_clean[len(base_vol):] + target := target_clean[len(target_vol):] if base == "." { - base = ""; + base = "" } - base_slashed := len(base) > 0 && base[0] == SEPARATOR; - target_slashed := len(target) > 0 && target[0] == SEPARATOR; + base_slashed := len(base) > 0 && base[0] == SEPARATOR + target_slashed := len(target) > 0 && target[0] == SEPARATOR if base_slashed != target_slashed || !strings.equal_fold(base_vol, target_vol) { - return "", .Cannot_Relate; + return "", .Cannot_Relate } - bl, tl := len(base), len(target); - b0, bi, t0, ti: int; + bl, tl := len(base), len(target) + b0, bi, t0, ti: int for { for bi < bl && base[bi] != SEPARATOR { - bi += 1; + bi += 1 } for ti < tl && target[ti] != SEPARATOR { - ti += 1; + ti += 1 } if !strings.equal_fold(target[t0:ti], base[b0:bi]) { - break; + break } if bi < bl { - bi += 1; + bi += 1 } if ti < tl { - ti += 1; + ti += 1 } - b0, t0 = bi, ti; + b0, t0 = bi, ti } if base[b0:bi] == ".." { - return "", .Cannot_Relate; + return "", .Cannot_Relate } if b0 != bl { - seps := strings.count(base[b0:bl], SEPARATOR_STRING); - size := 2 + seps*3; + seps := strings.count(base[b0:bl], SEPARATOR_STRING) + size := 2 + seps*3 if tl != t0 { - size += 1 + tl - t0; + size += 1 + tl - t0 } - buf := make([]byte, size); - n := copy(buf, ".."); + buf := make([]byte, size) + n := copy(buf, "..") for in 0..<seps { - buf[n] = SEPARATOR; - copy(buf[n+1:], ".."); - n += 3; + buf[n] = SEPARATOR + copy(buf[n+1:], "..") + n += 3 } if t0 != tl { - buf[n] = SEPARATOR; - copy(buf[n+1:], target[t0:]); + buf[n] = SEPARATOR + copy(buf[n+1:], target[t0:]) } - return string(buf), .None; + return string(buf), .None } - delete_target = false; - return target[t0:], .None; + delete_target = false + return target[t0:], .None } dir :: proc(path: string, allocator := context.allocator) -> string { - vol := volume_name(path); - i := len(path) - 1; + vol := volume_name(path) + i := len(path) - 1 for i >= len(vol) && !is_separator(path[i]) { - i -= 1; + i -= 1 } - dir := clean(path[len(vol) : i+1], allocator); - defer delete(dir, allocator); + dir := clean(path[len(vol) : i+1], allocator) + defer delete(dir, allocator) if dir == "." && len(vol) > 2 { - return strings.clone(vol); + return strings.clone(vol) } - return strings.concatenate({vol, dir}); + return strings.concatenate({vol, dir}) } split_list :: proc(path: string, allocator := context.allocator) -> []string { if path == "" { - return nil; + return nil } - start: int; - quote: bool; + start: int + quote: bool - start, quote = 0, false; - count := 0; + start, quote = 0, false + count := 0 for i := 0; i < len(path); i += 1 { - c := path[i]; + c := path[i] switch { case c == '"': - quote = !quote; + quote = !quote case c == LIST_SEPARATOR && !quote: - count += 1; + count += 1 } } - start, quote = 0, false; - list := make([]string, count, allocator); - index := 0; + start, quote = 0, false + list := make([]string, count, allocator) + index := 0 for i := 0; i < len(path); i += 1 { - c := path[i]; + c := path[i] switch { case c == '"': - quote = !quote; + quote = !quote case c == LIST_SEPARATOR && !quote: - list[index] = path[start:i]; - index += 1; - start = i + 1; + list[index] = path[start:i] + index += 1 + start = i + 1 } } - assert(index == count); + assert(index == count) for s0, i in list { - s, new := strings.replace_all(s0, `"`, ``, allocator); + s, new := strings.replace_all(s0, `"`, ``, allocator) if !new { - s = strings.clone(s, allocator); + s = strings.clone(s, allocator) } - list[i] = s; + list[i] = s } - return list; + return list } @@ -366,38 +366,38 @@ Lazy_Buffer :: struct { @(private) lazy_buffer_index :: proc(lb: ^Lazy_Buffer, i: int) -> byte { if lb.b != nil { - return lb.b[i]; + return lb.b[i] } - return lb.s[i]; + return lb.s[i] } @(private) lazy_buffer_append :: proc(lb: ^Lazy_Buffer, c: byte) { if lb.b == nil { if lb.w < len(lb.s) && lb.s[lb.w] == c { - lb.w += 1; - return; + lb.w += 1 + return } - lb.b = make([]byte, len(lb.s)); - copy(lb.b, lb.s[:lb.w]); + lb.b = make([]byte, len(lb.s)) + copy(lb.b, lb.s[:lb.w]) } - lb.b[lb.w] = c; - lb.w += 1; + lb.b[lb.w] = c + lb.w += 1 } @(private) lazy_buffer_string :: proc(lb: ^Lazy_Buffer) -> string { if lb.b == nil { - return strings.clone(lb.vol_and_path[:lb.vol_len+lb.w]); + return strings.clone(lb.vol_and_path[:lb.vol_len+lb.w]) } - x := lb.vol_and_path[:lb.vol_len]; - y := string(lb.b[:lb.w]); - z := make([]byte, len(x)+len(y)); - copy(z, x); - copy(z[len(x):], y); - return string(z); + x := lb.vol_and_path[:lb.vol_len] + y := string(lb.b[:lb.w]) + z := make([]byte, len(x)+len(y)) + copy(z, x) + copy(z[len(x):], y) + return string(z) } @(private) lazy_buffer_destroy :: proc(lb: ^Lazy_Buffer) { - delete(lb.b); - lb^ = {}; + delete(lb.b) + lb^ = {} } diff --git a/core/path/filepath/path_windows.odin b/core/path/filepath/path_windows.odin index a0908be67..db8fb547c 100644 --- a/core/path/filepath/path_windows.odin +++ b/core/path/filepath/path_windows.odin @@ -4,128 +4,128 @@ import "core:strings" import "core:os" import win32 "core:sys/windows" -SEPARATOR :: '\\'; -SEPARATOR_STRING :: `\`; -LIST_SEPARATOR :: ';'; +SEPARATOR :: '\\' +SEPARATOR_STRING :: `\` +LIST_SEPARATOR :: ';' @(private) reserved_names := [?]string{ "CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9", -}; +} is_reserved_name :: proc(path: string) -> bool { if len(path) == 0 { - return false; + return false } for reserved in reserved_names { if strings.equal_fold(path, reserved) { - return true; + return true } } - return false; + return false } is_UNC :: proc(path: string) -> bool { - return volume_name_len(path) > 2; + return volume_name_len(path) > 2 } is_abs :: proc(path: string) -> bool { if is_reserved_name(path) { - return true; + return true } - l := volume_name_len(path); + l := volume_name_len(path) if l == 0 { - return false; + return false } - path := path; - path = path[l:]; + path := path + path = path[l:] if path == "" { - return false; + return false } - return is_slash(path[0]); + return is_slash(path[0]) } @(private) temp_full_path :: proc(name: string) -> (path: string, err: os.Errno) { - ta := context.temp_allocator; + ta := context.temp_allocator - name := name; + name := name if name == "" { - name = "."; + name = "." } - p := win32.utf8_to_utf16(name, ta); - buf := make([dynamic]u16, 100, ta); + p := win32.utf8_to_utf16(name, ta) + buf := make([dynamic]u16, 100, ta) for { - n := win32.GetFullPathNameW(raw_data(p), u32(len(buf)), raw_data(buf), nil); + n := win32.GetFullPathNameW(raw_data(p), u32(len(buf)), raw_data(buf), nil) if n == 0 { - delete(buf); - return "", os.Errno(win32.GetLastError()); + delete(buf) + return "", os.Errno(win32.GetLastError()) } if n <= u32(len(buf)) { - return win32.utf16_to_utf8(buf[:n], ta), os.ERROR_NONE; + return win32.utf16_to_utf8(buf[:n], ta), os.ERROR_NONE } - resize(&buf, len(buf)*2); + resize(&buf, len(buf)*2) } - return; + return } abs :: proc(path: string, allocator := context.allocator) -> (string, bool) { - full_path, err := temp_full_path(path); + full_path, err := temp_full_path(path) if err != 0 { - return "", false; + return "", false } - p := clean(full_path, allocator); - return p, true; + p := clean(full_path, allocator) + return p, true } join :: proc(elems: ..string, allocator := context.allocator) -> string { for e, i in elems { if e != "" { - return join_non_empty(elems[i:]); + return join_non_empty(elems[i:]) } } - return ""; + return "" } join_non_empty :: proc(elems: []string) -> string { if len(elems[0]) == 2 && elems[0][1] == ':' { - i := 1; + i := 1 for ; i < len(elems); i += 1 { if elems[i] != "" { - break; + break } } - s := strings.join(elems[i:], SEPARATOR_STRING, context.temp_allocator); - s = strings.concatenate({elems[0], s}, context.temp_allocator); - return clean(s); + s := strings.join(elems[i:], SEPARATOR_STRING, context.temp_allocator) + s = strings.concatenate({elems[0], s}, context.temp_allocator) + return clean(s) } - s := strings.join(elems, SEPARATOR_STRING, context.temp_allocator); - p := clean(s); + s := strings.join(elems, SEPARATOR_STRING, context.temp_allocator) + p := clean(s) if !is_UNC(p) { - return p; + return p } - head := clean(elems[0], context.temp_allocator); + head := clean(elems[0], context.temp_allocator) if is_UNC(head) { - return p; + return p } - delete(p); // It is not needed now + delete(p) // It is not needed now - tail := clean(strings.join(elems[1:], SEPARATOR_STRING, context.temp_allocator), context.temp_allocator); + tail := clean(strings.join(elems[1:], SEPARATOR_STRING, context.temp_allocator), context.temp_allocator) if head[len(head)-1] == SEPARATOR { - return strings.concatenate({head, tail}); + return strings.concatenate({head, tail}) } - return strings.concatenate({head, SEPARATOR_STRING, tail}); + return strings.concatenate({head, SEPARATOR_STRING, tail}) } diff --git a/core/path/filepath/walk.odin b/core/path/filepath/walk.odin index ba198ff0e..29d4fd5b1 100644 --- a/core/path/filepath/walk.odin +++ b/core/path/filepath/walk.odin @@ -14,7 +14,7 @@ import "core:slice" // The sole exception is if 'skip_dir' is returned as true: // when 'skip_dir' is invoked on a directory. 'walk' skips directory contents // when 'skip_dir' is invoked on a non-directory. 'walk' skips the remaining files in the containing directory -Walk_Proc :: #type proc(info: os.File_Info, in_err: os.Errno) -> (err: os.Errno, skip_dir: bool); +Walk_Proc :: #type proc(info: os.File_Info, in_err: os.Errno) -> (err: os.Errno, skip_dir: bool) // walk walks the file tree rooted at 'root', calling 'walk_proc' for each file or directory in the tree, including 'root' // All errors that happen visiting files and directories are filtered by walk_proc @@ -23,16 +23,16 @@ Walk_Proc :: #type proc(info: os.File_Info, in_err: os.Errno) -> (err: os.Errno, // NOTE: walk does not follow symbolic links // NOTE: os.File_Info uses the 'context.temp_allocator' to allocate, and will delete when it is done walk :: proc(root: string, walk_proc: Walk_Proc) -> os.Errno { - info, err := os.lstat(root, context.temp_allocator); - defer os.file_info_delete(info, context.temp_allocator); + info, err := os.lstat(root, context.temp_allocator) + defer os.file_info_delete(info, context.temp_allocator) - skip_dir: bool; + skip_dir: bool if err != 0 { - err, skip_dir = walk_proc(info, err); + err, skip_dir = walk_proc(info, err) } else { - err, skip_dir = _walk(info, walk_proc); + err, skip_dir = _walk(info, walk_proc) } - return 0 if skip_dir else err; + return 0 if skip_dir else err } @@ -41,48 +41,48 @@ _walk :: proc(info: os.File_Info, walk_proc: Walk_Proc) -> (err: os.Errno, skip_ if !info.is_dir { if info.fullpath == "" && info.name == "" { // ignore empty things - return; + return } - return walk_proc(info, 0); + return walk_proc(info, 0) } - fis: []os.File_Info; - err1: os.Errno; - fis, err = read_dir(info.fullpath, context.temp_allocator); - defer os.file_info_slice_delete(fis, context.temp_allocator); + fis: []os.File_Info + err1: os.Errno + fis, err = read_dir(info.fullpath, context.temp_allocator) + defer os.file_info_slice_delete(fis, context.temp_allocator) - err1, skip_dir = walk_proc(info, err); + err1, skip_dir = walk_proc(info, err) if err != 0 || err1 != 0 || skip_dir { - err = err1; - return; + err = err1 + return } for fi in fis { - err, skip_dir = _walk(fi, walk_proc); + err, skip_dir = _walk(fi, walk_proc) if err != 0 || skip_dir { if !fi.is_dir || !skip_dir { - return; + return } } } - return; + return } @(private) read_dir :: proc(dir_name: string, allocator := context.temp_allocator) -> ([]os.File_Info, os.Errno) { - f, err := os.open(dir_name); + f, err := os.open(dir_name) if err != 0 { - return nil, err; + return nil, err } - fis: []os.File_Info; - fis, err = os.read_dir(f, -1, allocator); - os.close(f); + fis: []os.File_Info + fis, err = os.read_dir(f, -1, allocator) + os.close(f) if err != 0 { - return nil, err; + return nil, err } slice.sort_by(fis, proc(a, b: os.File_Info) -> bool { - return a.name < b.name; - }); - return fis, 0; + return a.name < b.name + }) + return fis, 0 } diff --git a/core/path/match.odin b/core/path/match.odin index e77bf79c3..0bea4f6e7 100644 --- a/core/path/match.odin +++ b/core/path/match.odin @@ -29,175 +29,175 @@ Match_Error :: enum { // The only possible error returned is .Syntax_Error // match :: proc(pattern, name: string) -> (matched: bool, err: Match_Error) { - pattern, name := pattern, name; + pattern, name := pattern, name pattern_loop: for len(pattern) > 0 { - star: bool; - chunk: string; - star, chunk, pattern = scan_chunk(pattern); + star: bool + chunk: string + star, chunk, pattern = scan_chunk(pattern) if star && chunk == "" { - return !strings.contains(name, "/"), .None; + return !strings.contains(name, "/"), .None } - t: string; - ok: bool; - t, ok, err = match_chunk(chunk, name); + t: string + ok: bool + t, ok, err = match_chunk(chunk, name) if ok && (len(t) == 0 || len(pattern) > 0) { - name = t; - continue; + name = t + continue } if err != .None { - return; + return } if star { for i := 0; i < len(name) && name[i] != '/'; i += 1 { - t, ok, err = match_chunk(chunk, name[i+1:]); + t, ok, err = match_chunk(chunk, name[i+1:]) if ok { if len(pattern) == 0 && len(t) > 0 { - continue; + continue } - name = t; - continue pattern_loop; + name = t + continue pattern_loop } if err != .None { - return; + return } } } - return false, .None; + return false, .None } - return len(name) == 0, .None; + return len(name) == 0, .None } @(private="file") scan_chunk :: proc(pattern: string) -> (star: bool, chunk, rest: string) { - pattern := pattern; + pattern := pattern for len(pattern) > 0 && pattern[0] == '*' { - pattern = pattern[1:]; - star = true; + pattern = pattern[1:] + star = true } - in_range := false; - i: int; + in_range := false + i: int scan_loop: for i = 0; i < len(pattern); i += 1 { switch pattern[i] { case '\\': if i+1 < len(pattern) { - i += 1; + i += 1 } case '[': - in_range = true; + in_range = true case ']': - in_range = false; + in_range = false case '*': if !in_range { - break scan_loop; + break scan_loop } } } - return star, pattern[:i], pattern[i:]; + return star, pattern[:i], pattern[i:] } @(private="file") match_chunk :: proc(chunk, s: string) -> (rest: string, ok: bool, err: Match_Error) { - chunk, s := chunk, s; + chunk, s := chunk, s for len(chunk) > 0 { if len(s) == 0 { - return; + return } switch chunk[0] { case '[': - r, w := utf8.decode_rune_in_string(s); - s = s[w:]; - chunk = chunk[1:]; - is_negated := false; + r, w := utf8.decode_rune_in_string(s) + s = s[w:] + chunk = chunk[1:] + is_negated := false if len(chunk) > 0 && chunk[0] == '^' { - is_negated = true; - chunk = chunk[1:]; + is_negated = true + chunk = chunk[1:] } - match := false; - range_count := 0; + match := false + range_count := 0 for { if len(chunk) > 0 && chunk[0] == ']' && range_count > 0 { - chunk = chunk[1:]; - break; + chunk = chunk[1:] + break } - lo, hi: rune; + lo, hi: rune if lo, chunk, err = get_escape(chunk); err != .None { - return; + return } - hi = lo; + hi = lo if chunk[0] == '-' { if hi, chunk, err = get_escape(chunk[1:]); err != .None { - return; + return } } if lo <= r && r <= hi { - match = true; + match = true } - range_count += 1; + range_count += 1 } if match == is_negated { - return; + return } case '?': if s[0] == '/' { - return; + return } - _, w := utf8.decode_rune_in_string(s); - s = s[w:]; - chunk = chunk[1:]; + _, w := utf8.decode_rune_in_string(s) + s = s[w:] + chunk = chunk[1:] case '\\': - chunk = chunk[1:]; + chunk = chunk[1:] if len(chunk) == 0 { - err = .Syntax_Error; - return; + err = .Syntax_Error + return } - fallthrough; + fallthrough case: if chunk[0] != s[0] { - return; + return } - s = s[1:]; - chunk = chunk[1:]; + s = s[1:] + chunk = chunk[1:] } } - return s, true, .None; + return s, true, .None } @(private="file") get_escape :: proc(chunk: string) -> (r: rune, next_chunk: string, err: Match_Error) { if len(chunk) == 0 || chunk[0] == '-' || chunk[0] == ']' { - err = .Syntax_Error; - return; + err = .Syntax_Error + return } - chunk := chunk; + chunk := chunk if chunk[0] == '\\' { - chunk = chunk[1:]; + chunk = chunk[1:] if len(chunk) == 0 { - err = .Syntax_Error; - return; + err = .Syntax_Error + return } } - w: int; - r, w = utf8.decode_rune_in_string(chunk); + w: int + r, w = utf8.decode_rune_in_string(chunk) if r == utf8.RUNE_ERROR && w == 1 { - err = .Syntax_Error; + err = .Syntax_Error } - next_chunk = chunk[w:]; + next_chunk = chunk[w:] if len(next_chunk) == 0 { - err = .Syntax_Error; + err = .Syntax_Error } - return; + return } diff --git a/core/path/path.odin b/core/path/path.odin index ed6f2bfcf..d54106b3a 100644 --- a/core/path/path.odin +++ b/core/path/path.odin @@ -9,13 +9,13 @@ import "core:strings" // is_separator checks whether the byte is a valid separator character
is_separator :: proc(c: byte) -> bool {
- return c == '/';
+ return c == '/'
}
// is_abs checks whether the path is absolute
is_abs :: proc(path: string) -> bool {
- return len(path) > 0 && path[0] == '/';
+ return len(path) > 0 && path[0] == '/'
}
@@ -25,30 +25,30 @@ is_abs :: proc(path: string) -> bool { // If the path is all slashes, it returns "/"
base :: proc(path: string, new := false, allocator := context.allocator) -> (last_element: string) {
defer if new {
- last_element = strings.clone(last_element, allocator);
+ last_element = strings.clone(last_element, allocator)
}
if path == "" {
- last_element = ".";
- return;
+ last_element = "."
+ return
}
- path := path;
+ path := path
for len(path) > 0 && is_separator(path[len(path)-1]) {
- path = path[:len(path)-1];
+ path = path[:len(path)-1]
}
if i := strings.last_index(path, "/"); i >= 0 {
- path = path[i+1:];
+ path = path[i+1:]
}
if path == "" {
- last_element = "/";
+ last_element = "/"
} else {
- last_element = path;
+ last_element = path
}
- return;
+ return
}
// dir returns all but the last element of path, typically the path's directory.
@@ -57,8 +57,8 @@ base :: proc(path: string, new := false, allocator := context.allocator) -> (las // If the path consists entirely of slashes followed by non-slash bytes, it returns a single slash
// In any other case, the returned path does not end in a slash
dir :: proc(path: string, allocator := context.allocator) -> string {
- directory, _ := split(path);
- return clean(directory, allocator);
+ directory, _ := split(path)
+ return clean(directory, allocator)
}
@@ -67,13 +67,13 @@ dir :: proc(path: string, allocator := context.allocator) -> string { // If there is no slash in path, it returns an empty dir and file set to path
// The returned values have the property that path = dir+file
split :: proc(path: string) -> (dir, file: string) {
- i := strings.last_index(path, "/");
- return path[:i+1], path[i+1:];
+ i := strings.last_index(path, "/")
+ return path[:i+1], path[i+1:]
}
// split_elements splits the path elements into slices of the original path string
split_elements :: proc(path: string, allocator := context.allocator) -> []string {
- return strings.split(path, "/", allocator);
+ return strings.split(path, "/", allocator)
}
// clean returns the shortest path name equivalent to path through lexical analysis only
@@ -85,76 +85,76 @@ split_elements :: proc(path: string, allocator := context.allocator) -> []string // 4) remove .. that begin a rooted path ("/.." becomes "/")
//
clean :: proc(path: string, allocator := context.allocator) -> string {
- context.allocator = allocator;
+ context.allocator = allocator
if path == "" {
- return strings.clone(".");
+ return strings.clone(".")
}
// NOTE(bill): do not use is_separator because window paths do not follow this convention
- rooted := path[0] == '/';
- n := len(path);
+ rooted := path[0] == '/'
+ n := len(path)
- out := &Lazy_Buffer{s = path};
+ out := &Lazy_Buffer{s = path}
// Check for ../../.. prefixes
- r, dot_dot := 0, 0;
+ r, dot_dot := 0, 0
if rooted {
- lazy_buffer_append(out, '/');
- r, dot_dot = 1, 1;
+ lazy_buffer_append(out, '/')
+ r, dot_dot = 1, 1
}
for r < n {
switch {
case is_separator(path[r]):
- r += 1;
+ r += 1
case path[r] == '.' && (r+1 == n || is_separator(path[r+1])):
- r += 1;
+ r += 1
case path[r] == '.' && path[r+1] == '.' && (r+2 == n || is_separator(path[r+2])):
- r += 2;
+ r += 2
switch {
case out.w > dot_dot:
- out.w -= 1;
+ out.w -= 1
for out.w > dot_dot && !is_separator(lazy_buffer_index(out, out.w)) {
- out.w -= 1;
+ out.w -= 1
}
case !rooted:
if out.w > 0 {
- lazy_buffer_append(out, '/');
+ lazy_buffer_append(out, '/')
}
- lazy_buffer_append(out, '.');
- lazy_buffer_append(out, '.');
- dot_dot = out.w;
+ lazy_buffer_append(out, '.')
+ lazy_buffer_append(out, '.')
+ dot_dot = out.w
}
case:
if rooted && out.w != 1 || !rooted && out.w != 0 {
- lazy_buffer_append(out, '/');
+ lazy_buffer_append(out, '/')
}
for ; r < n && !is_separator(path[r]); r += 1 {
- lazy_buffer_append(out, path[r]);
+ lazy_buffer_append(out, path[r])
}
}
}
if out.w == 0 {
- delete(out.b);
- return strings.clone(".");
+ delete(out.b)
+ return strings.clone(".")
}
- return lazy_buffer_string(out);
+ return lazy_buffer_string(out)
}
// join joins numerous path elements into a single path
join :: proc(elems: ..string, allocator := context.allocator) -> string {
- context.allocator = allocator;
+ context.allocator = allocator
for elem, i in elems {
if elem != "" {
- s := strings.join(elems[i:], "/");
- return clean(s);
+ s := strings.join(elems[i:], "/")
+ return clean(s)
}
}
- return "";
+ return ""
}
// ext returns the file name extension used by "path"
@@ -163,32 +163,32 @@ join :: proc(elems: ..string, allocator := context.allocator) -> string { ext :: proc(path: string, new := false, allocator := context.allocator) -> string {
for i := len(path)-1; i >= 0 && !is_separator(path[i]); i -= 1 {
if path[i] == '.' {
- res := path[i:];
+ res := path[i:]
if new {
- res = strings.clone(res, allocator);
+ res = strings.clone(res, allocator)
}
- return res;
+ return res
}
}
- return "";
+ return ""
}
// name returns the file without the base and without the extension
name :: proc(path: string, new := false, allocator := context.allocator) -> (name: string) {
- _, file := split(path);
- name = file;
+ _, file := split(path)
+ name = file
defer if new {
- name = strings.clone(name, allocator);
+ name = strings.clone(name, allocator)
}
for i := len(file)-1; i >= 0 && !is_separator(file[i]); i -= 1 {
if file[i] == '.' {
- name = file[:i];
- return;
+ name = file[:i]
+ return
}
}
- return file;
+ return file
}
@@ -208,27 +208,27 @@ Lazy_Buffer :: struct { @(private)
lazy_buffer_index :: proc(lb: ^Lazy_Buffer, i: int) -> byte {
if lb.b != nil {
- return lb.b[i];
+ return lb.b[i]
}
- return lb.s[i];
+ return lb.s[i]
}
@(private)
lazy_buffer_append :: proc(lb: ^Lazy_Buffer, c: byte) {
if lb.b == nil {
if lb.w < len(lb.s) && lb.s[lb.w] == c {
- lb.w += 1;
- return;
+ lb.w += 1
+ return
}
- lb.b = make([]byte, len(lb.s));
- copy(lb.b, lb.s[:lb.w]);
+ lb.b = make([]byte, len(lb.s))
+ copy(lb.b, lb.s[:lb.w])
}
- lb.b[lb.w] = c;
- lb.w += 1;
+ lb.b[lb.w] = c
+ lb.w += 1
}
@(private)
lazy_buffer_string :: proc(lb: ^Lazy_Buffer) -> string {
if lb.b == nil {
- return strings.clone(lb.s[:lb.w]);
+ return strings.clone(lb.s[:lb.w])
}
- return string(lb.b[:lb.w]);
+ return string(lb.b[:lb.w])
}
diff --git a/core/reflect/map.odin b/core/reflect/map.odin index a2fc0d789..c56173074 100644 --- a/core/reflect/map.odin +++ b/core/reflect/map.odin @@ -2,8 +2,8 @@ package reflect import "core:runtime" import "core:mem" -_ :: runtime; -_ :: mem; +_ :: runtime +_ :: mem Map_Entry_Info :: struct($Key, $Value: typeid) { hash: uintptr, @@ -12,31 +12,31 @@ Map_Entry_Info :: struct($Key, $Value: typeid) { } map_entry_info_slice :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (entries: []Map_Entry_Info(K, V)) #no_bounds_check { - m := m; - rm := (^mem.Raw_Map)(&m); + m := m + rm := (^mem.Raw_Map)(&m) - info := type_info_base(type_info_of(M)).variant.(Type_Info_Map); - gs := type_info_base(info.generated_struct).variant.(Type_Info_Struct); - ed := type_info_base(gs.types[1]).variant.(Type_Info_Dynamic_Array); - entry_type := ed.elem.variant.(Type_Info_Struct); - key_offset := entry_type.offsets[2]; - value_offset := entry_type.offsets[3]; - entry_size := uintptr(ed.elem_size); + info := type_info_base(type_info_of(M)).variant.(Type_Info_Map) + gs := type_info_base(info.generated_struct).variant.(Type_Info_Struct) + ed := type_info_base(gs.types[1]).variant.(Type_Info_Dynamic_Array) + entry_type := ed.elem.variant.(Type_Info_Struct) + key_offset := entry_type.offsets[2] + value_offset := entry_type.offsets[3] + entry_size := uintptr(ed.elem_size) - entries = make(type_of(entries), rm.entries.len); + entries = make(type_of(entries), rm.entries.len) - data := uintptr(rm.entries.data); + data := uintptr(rm.entries.data) for i in 0..<rm.entries.len { - header := (^runtime.Map_Entry_Header)(data); + header := (^runtime.Map_Entry_Header)(data) - hash := header.hash; - key := (^K)(data + key_offset)^; - value := (^V)(data + value_offset)^; + hash := header.hash + key := (^K)(data + key_offset)^ + value := (^V)(data + value_offset)^ - entries[i] = {hash, key, value}; + entries[i] = {hash, key, value} - data += entry_size; + data += entry_size } - return entries; + return entries } diff --git a/core/reflect/reflect.odin b/core/reflect/reflect.odin index a7aec0d19..ed653b6b1 100644 --- a/core/reflect/reflect.odin +++ b/core/reflect/reflect.odin @@ -3,38 +3,38 @@ package reflect import "core:runtime" import "core:mem" import "core:intrinsics" -_ :: intrinsics; - -Type_Info :: runtime.Type_Info; - -Type_Info_Named :: runtime.Type_Info_Named; -Type_Info_Integer :: runtime.Type_Info_Integer; -Type_Info_Rune :: runtime.Type_Info_Rune; -Type_Info_Float :: runtime.Type_Info_Float; -Type_Info_Complex :: runtime.Type_Info_Complex; -Type_Info_Quaternion :: runtime.Type_Info_Quaternion; -Type_Info_String :: runtime.Type_Info_String; -Type_Info_Boolean :: runtime.Type_Info_Boolean; -Type_Info_Any :: runtime.Type_Info_Any; -Type_Info_Type_Id :: runtime.Type_Info_Type_Id; -Type_Info_Pointer :: runtime.Type_Info_Pointer; -Type_Info_Multi_Pointer :: runtime.Type_Info_Multi_Pointer; -Type_Info_Procedure :: runtime.Type_Info_Procedure; -Type_Info_Array :: runtime.Type_Info_Array; -Type_Info_Enumerated_Array :: runtime.Type_Info_Enumerated_Array; -Type_Info_Dynamic_Array :: runtime.Type_Info_Dynamic_Array; -Type_Info_Slice :: runtime.Type_Info_Slice; -Type_Info_Tuple :: runtime.Type_Info_Tuple; -Type_Info_Struct :: runtime.Type_Info_Struct; -Type_Info_Union :: runtime.Type_Info_Union; -Type_Info_Enum :: runtime.Type_Info_Enum; -Type_Info_Map :: runtime.Type_Info_Map; -Type_Info_Bit_Set :: runtime.Type_Info_Bit_Set; -Type_Info_Simd_Vector :: runtime.Type_Info_Simd_Vector; -Type_Info_Relative_Pointer :: runtime.Type_Info_Relative_Pointer; -Type_Info_Relative_Slice :: runtime.Type_Info_Relative_Slice; - -Type_Info_Enum_Value :: runtime.Type_Info_Enum_Value; +_ :: intrinsics + +Type_Info :: runtime.Type_Info + +Type_Info_Named :: runtime.Type_Info_Named +Type_Info_Integer :: runtime.Type_Info_Integer +Type_Info_Rune :: runtime.Type_Info_Rune +Type_Info_Float :: runtime.Type_Info_Float +Type_Info_Complex :: runtime.Type_Info_Complex +Type_Info_Quaternion :: runtime.Type_Info_Quaternion +Type_Info_String :: runtime.Type_Info_String +Type_Info_Boolean :: runtime.Type_Info_Boolean +Type_Info_Any :: runtime.Type_Info_Any +Type_Info_Type_Id :: runtime.Type_Info_Type_Id +Type_Info_Pointer :: runtime.Type_Info_Pointer +Type_Info_Multi_Pointer :: runtime.Type_Info_Multi_Pointer +Type_Info_Procedure :: runtime.Type_Info_Procedure +Type_Info_Array :: runtime.Type_Info_Array +Type_Info_Enumerated_Array :: runtime.Type_Info_Enumerated_Array +Type_Info_Dynamic_Array :: runtime.Type_Info_Dynamic_Array +Type_Info_Slice :: runtime.Type_Info_Slice +Type_Info_Tuple :: runtime.Type_Info_Tuple +Type_Info_Struct :: runtime.Type_Info_Struct +Type_Info_Union :: runtime.Type_Info_Union +Type_Info_Enum :: runtime.Type_Info_Enum +Type_Info_Map :: runtime.Type_Info_Map +Type_Info_Bit_Set :: runtime.Type_Info_Bit_Set +Type_Info_Simd_Vector :: runtime.Type_Info_Simd_Vector +Type_Info_Relative_Pointer :: runtime.Type_Info_Relative_Pointer +Type_Info_Relative_Slice :: runtime.Type_Info_Relative_Slice + +Type_Info_Enum_Value :: runtime.Type_Info_Enum_Value Type_Kind :: enum { @@ -70,161 +70,161 @@ Type_Kind :: enum { type_kind :: proc(T: typeid) -> Type_Kind { - ti := type_info_of(T); + ti := type_info_of(T) if ti != nil { switch _ in ti.variant { - case Type_Info_Named: return .Named; - case Type_Info_Integer: return .Integer; - case Type_Info_Rune: return .Rune; - case Type_Info_Float: return .Float; - case Type_Info_Complex: return .Complex; - case Type_Info_Quaternion: return .Quaternion; - case Type_Info_String: return .String; - case Type_Info_Boolean: return .Boolean; - case Type_Info_Any: return .Any; - case Type_Info_Type_Id: return .Type_Id; - case Type_Info_Pointer: return .Pointer; - case Type_Info_Multi_Pointer: return .Multi_Pointer; - case Type_Info_Procedure: return .Procedure; - case Type_Info_Array: return .Array; - case Type_Info_Enumerated_Array: return .Enumerated_Array; - case Type_Info_Dynamic_Array: return .Dynamic_Array; - case Type_Info_Slice: return .Slice; - case Type_Info_Tuple: return .Tuple; - case Type_Info_Struct: return .Struct; - case Type_Info_Union: return .Union; - case Type_Info_Enum: return .Enum; - case Type_Info_Map: return .Map; - case Type_Info_Bit_Set: return .Bit_Set; - case Type_Info_Simd_Vector: return .Simd_Vector; - case Type_Info_Relative_Pointer: return .Relative_Pointer; - case Type_Info_Relative_Slice: return .Relative_Slice; + case Type_Info_Named: return .Named + case Type_Info_Integer: return .Integer + case Type_Info_Rune: return .Rune + case Type_Info_Float: return .Float + case Type_Info_Complex: return .Complex + case Type_Info_Quaternion: return .Quaternion + case Type_Info_String: return .String + case Type_Info_Boolean: return .Boolean + case Type_Info_Any: return .Any + case Type_Info_Type_Id: return .Type_Id + case Type_Info_Pointer: return .Pointer + case Type_Info_Multi_Pointer: return .Multi_Pointer + case Type_Info_Procedure: return .Procedure + case Type_Info_Array: return .Array + case Type_Info_Enumerated_Array: return .Enumerated_Array + case Type_Info_Dynamic_Array: return .Dynamic_Array + case Type_Info_Slice: return .Slice + case Type_Info_Tuple: return .Tuple + case Type_Info_Struct: return .Struct + case Type_Info_Union: return .Union + case Type_Info_Enum: return .Enum + case Type_Info_Map: return .Map + case Type_Info_Bit_Set: return .Bit_Set + case Type_Info_Simd_Vector: return .Simd_Vector + case Type_Info_Relative_Pointer: return .Relative_Pointer + case Type_Info_Relative_Slice: return .Relative_Slice } } - return .Invalid; + return .Invalid } // TODO(bill): Better name underlying_type_kind :: proc(T: typeid) -> Type_Kind { - return type_kind(runtime.typeid_base(T)); + return type_kind(runtime.typeid_base(T)) } // TODO(bill): Better name backing_type_kind :: proc(T: typeid) -> Type_Kind { - return type_kind(runtime.typeid_core(T)); + return type_kind(runtime.typeid_core(T)) } type_info_base :: proc(info: ^Type_Info) -> ^Type_Info { if info == nil { return nil; } - base := info; + base := info loop: for { #partial switch i in base.variant { - case Type_Info_Named: base = i.base; - case: break loop; + case Type_Info_Named: base = i.base + case: break loop } } - return base; + return base } type_info_core :: proc(info: ^Type_Info) -> ^Type_Info { if info == nil { return nil; } - base := info; + base := info loop: for { #partial switch i in base.variant { - case Type_Info_Named: base = i.base; - case Type_Info_Enum: base = i.base; - case: break loop; + case Type_Info_Named: base = i.base + case Type_Info_Enum: base = i.base + case: break loop } } - return base; + return base } -type_info_base_without_enum :: type_info_core; +type_info_base_without_enum :: type_info_core typeid_base :: proc(id: typeid) -> typeid { - ti := type_info_of(id); - ti = type_info_base(ti); - return ti.id; + ti := type_info_of(id) + ti = type_info_base(ti) + return ti.id } typeid_core :: proc(id: typeid) -> typeid { - ti := type_info_base_without_enum(type_info_of(id)); - return ti.id; + ti := type_info_base_without_enum(type_info_of(id)) + return ti.id } -typeid_base_without_enum :: typeid_core; +typeid_base_without_enum :: typeid_core typeid_elem :: proc(id: typeid) -> typeid { - ti := type_info_of(id); + ti := type_info_of(id) if ti == nil { return nil; } - bits := 8*ti.size; + bits := 8*ti.size #partial switch v in ti.variant { case Type_Info_Complex: switch bits { - case 64: return f32; - case 128: return f64; + case 64: return f32 + case 128: return f64 } case Type_Info_Quaternion: switch bits { - case 128: return f32; - case 256: return f64; + case 128: return f32 + case 256: return f64 } - case Type_Info_Pointer: return v.elem.id; - case Type_Info_Multi_Pointer: return v.elem.id; - case Type_Info_Array: return v.elem.id; - case Type_Info_Enumerated_Array: return v.elem.id; - case Type_Info_Slice: return v.elem.id; - case Type_Info_Dynamic_Array: return v.elem.id; + case Type_Info_Pointer: return v.elem.id + case Type_Info_Multi_Pointer: return v.elem.id + case Type_Info_Array: return v.elem.id + case Type_Info_Enumerated_Array: return v.elem.id + case Type_Info_Slice: return v.elem.id + case Type_Info_Dynamic_Array: return v.elem.id } - return id; + return id } size_of_typeid :: proc(T: typeid) -> int { if ti := type_info_of(T); ti != nil { - return ti.size; + return ti.size } - return 0; + return 0 } align_of_typeid :: proc(T: typeid) -> int { if ti := type_info_of(T); ti != nil { - return ti.align; + return ti.align } - return 1; + return 1 } as_bytes :: proc(v: any) -> []byte { if v != nil { - sz := size_of_typeid(v.id); - return mem.slice_ptr((^byte)(v.data), sz); + sz := size_of_typeid(v.id) + return mem.slice_ptr((^byte)(v.data), sz) } - return nil; + return nil } any_data :: #force_inline proc(v: any) -> (data: rawptr, id: typeid) { - return v.data, v.id; + return v.data, v.id } is_nil :: proc(v: any) -> bool { if v == nil { - return true; + return true } - data := as_bytes(v); + data := as_bytes(v) if data != nil { - return true; + return true } for v in data { if v != 0 { - return false; + return false } } - return true; + return true } length :: proc(val: any) -> int { @@ -232,34 +232,34 @@ length :: proc(val: any) -> int { #partial switch a in type_info_of(val.id).variant { case Type_Info_Named: - return length({val.data, a.base.id}); + return length({val.data, a.base.id}) case Type_Info_Pointer: - return length({val.data, a.elem.id}); + return length({val.data, a.elem.id}) case Type_Info_Array: - return a.count; + return a.count case Type_Info_Enumerated_Array: - return a.count; + return a.count case Type_Info_Slice: - return (^mem.Raw_Slice)(val.data).len; + return (^mem.Raw_Slice)(val.data).len case Type_Info_Dynamic_Array: - return (^mem.Raw_Dynamic_Array)(val.data).len; + return (^mem.Raw_Dynamic_Array)(val.data).len case Type_Info_Map: - return (^mem.Raw_Map)(val.data).entries.len; + return (^mem.Raw_Map)(val.data).entries.len case Type_Info_String: if a.is_cstring { - return len((^cstring)(val.data)^); + return len((^cstring)(val.data)^) } else { - return (^mem.Raw_String)(val.data).len; + return (^mem.Raw_String)(val.data).len } } - return 0; + return 0 } capacity :: proc(val: any) -> int { @@ -267,24 +267,24 @@ capacity :: proc(val: any) -> int { #partial switch a in type_info_of(val.id).variant { case Type_Info_Named: - return capacity({val.data, a.base.id}); + return capacity({val.data, a.base.id}) case Type_Info_Pointer: - return capacity({val.data, a.elem.id}); + return capacity({val.data, a.elem.id}) case Type_Info_Array: - return a.count; + return a.count case Type_Info_Enumerated_Array: - return a.count; + return a.count case Type_Info_Dynamic_Array: - return (^mem.Raw_Dynamic_Array)(val.data).cap; + return (^mem.Raw_Dynamic_Array)(val.data).cap case Type_Info_Map: - return (^mem.Raw_Map)(val.data).entries.cap; + return (^mem.Raw_Map)(val.data).entries.cap } - return 0; + return 0 } @@ -293,58 +293,58 @@ index :: proc(val: any, i: int, loc := #caller_location) -> any { #partial switch a in type_info_of(val.id).variant { case Type_Info_Named: - return index({val.data, a.base.id}, i, loc); + return index({val.data, a.base.id}, i, loc) case Type_Info_Pointer: - ptr := (^rawptr)(val.data)^; + ptr := (^rawptr)(val.data)^ if ptr == nil { - return nil; + return nil } - return index({ptr, a.elem.id}, i, loc); + return index({ptr, a.elem.id}, i, loc) case Type_Info_Multi_Pointer: - ptr := (^rawptr)(val.data)^; + ptr := (^rawptr)(val.data)^ if ptr == nil { - return nil; + return nil } - return index({ptr, a.elem.id}, i, loc); + return index({ptr, a.elem.id}, i, loc) case Type_Info_Array: - runtime.bounds_check_error_loc(loc, i, a.count); - offset := uintptr(a.elem.size * i); - data := rawptr(uintptr(val.data) + offset); - return any{data, a.elem.id}; + runtime.bounds_check_error_loc(loc, i, a.count) + offset := uintptr(a.elem.size * i) + data := rawptr(uintptr(val.data) + offset) + return any{data, a.elem.id} case Type_Info_Enumerated_Array: - runtime.bounds_check_error_loc(loc, i, a.count); - offset := uintptr(a.elem.size * i); - data := rawptr(uintptr(val.data) + offset); - return any{data, a.elem.id}; + runtime.bounds_check_error_loc(loc, i, a.count) + offset := uintptr(a.elem.size * i) + data := rawptr(uintptr(val.data) + offset) + return any{data, a.elem.id} case Type_Info_Slice: - raw := (^mem.Raw_Slice)(val.data); - runtime.bounds_check_error_loc(loc, i, raw.len); - offset := uintptr(a.elem.size * i); - data := rawptr(uintptr(raw.data) + offset); - return any{data, a.elem.id}; + raw := (^mem.Raw_Slice)(val.data) + runtime.bounds_check_error_loc(loc, i, raw.len) + offset := uintptr(a.elem.size * i) + data := rawptr(uintptr(raw.data) + offset) + return any{data, a.elem.id} case Type_Info_Dynamic_Array: - raw := (^mem.Raw_Dynamic_Array)(val.data); - runtime.bounds_check_error_loc(loc, i, raw.len); - offset := uintptr(a.elem.size * i); - data := rawptr(uintptr(raw.data) + offset); - return any{data, a.elem.id}; + raw := (^mem.Raw_Dynamic_Array)(val.data) + runtime.bounds_check_error_loc(loc, i, raw.len) + offset := uintptr(a.elem.size * i) + data := rawptr(uintptr(raw.data) + offset) + return any{data, a.elem.id} case Type_Info_String: if a.is_cstring { return nil; } - raw := (^mem.Raw_String)(val.data); - runtime.bounds_check_error_loc(loc, i, raw.len); - offset := uintptr(size_of(u8) * i); - data := rawptr(uintptr(raw.data) + offset); - return any{data, typeid_of(u8)}; + raw := (^mem.Raw_String)(val.data) + runtime.bounds_check_error_loc(loc, i, raw.len) + offset := uintptr(size_of(u8) * i) + data := rawptr(uintptr(raw.data) + offset) + return any{data, typeid_of(u8)} } - return nil; + return nil } @@ -353,7 +353,7 @@ index :: proc(val: any, i: int, loc := #caller_location) -> any { // // Through convention, tags are the concatenation of optionally space separationed key:"value" pairs. // Each key is a non-empty string which contains no control characters other than space, quotes, and colon. -Struct_Tag :: distinct string; +Struct_Tag :: distinct string Struct_Field :: struct { name: string, @@ -364,40 +364,40 @@ Struct_Field :: struct { } struct_field_at :: proc(T: typeid, i: int) -> (field: Struct_Field) { - ti := runtime.type_info_base(type_info_of(T)); + ti := runtime.type_info_base(type_info_of(T)) if s, ok := ti.variant.(runtime.Type_Info_Struct); ok { if 0 <= i && i < len(s.names) { - field.name = s.names[i]; - field.type = s.types[i]; - field.tag = Struct_Tag(s.tags[i]); - field.offset = s.offsets[i]; - field.is_using = s.usings[i]; + field.name = s.names[i] + field.type = s.types[i] + field.tag = Struct_Tag(s.tags[i]) + field.offset = s.offsets[i] + field.is_using = s.usings[i] } } - return; + return } struct_field_by_name :: proc(T: typeid, name: string) -> (field: Struct_Field) { - ti := runtime.type_info_base(type_info_of(T)); + ti := runtime.type_info_base(type_info_of(T)) if s, ok := ti.variant.(runtime.Type_Info_Struct); ok { for fname, i in s.names { if fname == name { - field.name = s.names[i]; - field.type = s.types[i]; - field.tag = Struct_Tag(s.tags[i]); - field.offset = s.offsets[i]; - field.is_using = s.usings[i]; - break; + field.name = s.names[i] + field.type = s.types[i] + field.tag = Struct_Tag(s.tags[i]) + field.offset = s.offsets[i] + field.is_using = s.usings[i] + break } } } - return; + return } struct_field_value_by_name :: proc(a: any, field: string, allow_using := false) -> any { if a == nil { return nil; } - ti := runtime.type_info_base(type_info_of(a.id)); + ti := runtime.type_info_base(type_info_of(a.id)) if s, ok := ti.variant.(runtime.Type_Info_Struct); ok { for name, i in s.names { @@ -405,61 +405,61 @@ struct_field_value_by_name :: proc(a: any, field: string, allow_using := false) return any{ rawptr(uintptr(a.data) + s.offsets[i]), s.types[i].id, - }; + } } if allow_using && s.usings[i] { f := any{ rawptr(uintptr(a.data) + s.offsets[i]), s.types[i].id, - }; + } if res := struct_field_value_by_name(f, field, allow_using); res != nil { - return res; + return res } } } } - return nil; + return nil } struct_field_names :: proc(T: typeid) -> []string { - ti := runtime.type_info_base(type_info_of(T)); + ti := runtime.type_info_base(type_info_of(T)) if s, ok := ti.variant.(runtime.Type_Info_Struct); ok { - return s.names; + return s.names } - return nil; + return nil } struct_field_types :: proc(T: typeid) -> []^Type_Info { - ti := runtime.type_info_base(type_info_of(T)); + ti := runtime.type_info_base(type_info_of(T)) if s, ok := ti.variant.(runtime.Type_Info_Struct); ok { - return s.types; + return s.types } - return nil; + return nil } struct_field_tags :: proc(T: typeid) -> []Struct_Tag { - ti := runtime.type_info_base(type_info_of(T)); + ti := runtime.type_info_base(type_info_of(T)) if s, ok := ti.variant.(runtime.Type_Info_Struct); ok { - return transmute([]Struct_Tag)s.tags; + return transmute([]Struct_Tag)s.tags } - return nil; + return nil } struct_field_offsets :: proc(T: typeid) -> []uintptr { - ti := runtime.type_info_base(type_info_of(T)); + ti := runtime.type_info_base(type_info_of(T)) if s, ok := ti.variant.(runtime.Type_Info_Struct); ok { - return s.offsets; + return s.offsets } - return nil; + return nil } struct_fields_zipped :: proc(T: typeid) -> (fields: #soa[]Struct_Field) { - ti := runtime.type_info_base(type_info_of(T)); + ti := runtime.type_info_base(type_info_of(T)) if s, ok := ti.variant.(runtime.Type_Info_Struct); ok { return soa_zip( name = s.names, @@ -467,139 +467,139 @@ struct_fields_zipped :: proc(T: typeid) -> (fields: #soa[]Struct_Field) { tag = transmute([]Struct_Tag)s.tags, offset = s.offsets, is_using = s.usings, - ); + ) } - return nil; + return nil } struct_tag_get :: proc(tag: Struct_Tag, key: string) -> (value: Struct_Tag) { - value, _ = struct_tag_lookup(tag, key); - return; + value, _ = struct_tag_lookup(tag, key) + return } struct_tag_lookup :: proc(tag: Struct_Tag, key: string) -> (value: Struct_Tag, ok: bool) { for t := tag; t != ""; /**/ { - i := 0; + i := 0 for i < len(t) && t[i] == ' ' { // Skip whitespace - i += 1; + i += 1 } - t = t[i:]; + t = t[i:] if len(t) == 0 { - break; + break } - i = 0; + i = 0 loop: for i < len(t) { switch t[i] { case ':', '"': - break loop; + break loop case 0x00 ..< ' ', 0x7f ..= 0x9f: // break if control character is found - break loop; + break loop } - i += 1; + i += 1 } if i == 0 { - break; + break } if i+1 >= len(t) { - break; + break } if t[i] != ':' || t[i+1] != '"' { - break; + break } - name := string(t[:i]); - t = t[i+1:]; + name := string(t[:i]) + t = t[i+1:] - i = 1; + i = 1 for i < len(t) && t[i] != '"' { // find closing quote if t[i] == '\\' { - i += 1; // Skip escaped characters + i += 1 // Skip escaped characters } - i += 1; + i += 1 } if i >= len(t) { - break; + break } - val := string(t[:i+1]); - t = t[i+1:]; + val := string(t[:i+1]) + t = t[i+1:] if key == name { - return Struct_Tag(val[1:i]), true; + return Struct_Tag(val[1:i]), true } } - return; + return } enum_string :: proc(a: any) -> string { if a == nil { return ""; } - ti := runtime.type_info_base(type_info_of(a.id)); + ti := runtime.type_info_base(type_info_of(a.id)) if e, ok := ti.variant.(runtime.Type_Info_Enum); ok { - v, _ := as_i64(a); + v, _ := as_i64(a) for value, i in e.values { if value == Type_Info_Enum_Value(v) { - return e.names[i]; + return e.names[i] } } } else { - panic("expected an enum to reflect.enum_string"); + panic("expected an enum to reflect.enum_string") } - return ""; + return "" } // Given a enum type and a value name, get the enum value. enum_from_name :: proc($Enum_Type: typeid, name: string) -> (value: Enum_Type, ok: bool) { - ti := type_info_base(type_info_of(Enum_Type)); + ti := type_info_base(type_info_of(Enum_Type)) if eti, eti_ok := ti.variant.(runtime.Type_Info_Enum); eti_ok { for value_name, i in eti.names { if value_name != name { - continue; + continue } - v := eti.values[i]; - value = Enum_Type(v); - ok = true; - return; + v := eti.values[i] + value = Enum_Type(v) + ok = true + return } } - return; + return } enum_from_name_any :: proc(Enum_Type: typeid, name: string) -> (value: Type_Info_Enum_Value, ok: bool) { - ti := runtime.type_info_base(type_info_of(Enum_Type)); + ti := runtime.type_info_base(type_info_of(Enum_Type)) if eti, eti_ok := ti.variant.(runtime.Type_Info_Enum); eti_ok { for value_name, i in eti.names { if value_name != name { - continue; + continue } - value = eti.values[i]; - ok = true; - return; + value = eti.values[i] + ok = true + return } } - return; + return } enum_field_names :: proc(Enum_Type: typeid) -> []string { - ti := runtime.type_info_base(type_info_of(Enum_Type)); + ti := runtime.type_info_base(type_info_of(Enum_Type)) if eti, eti_ok := ti.variant.(runtime.Type_Info_Enum); eti_ok { - return eti.names; + return eti.names } - return nil; + return nil } enum_field_values :: proc(Enum_Type: typeid) -> []Type_Info_Enum_Value { - ti := runtime.type_info_base(type_info_of(Enum_Type)); + ti := runtime.type_info_base(type_info_of(Enum_Type)) if eti, eti_ok := ti.variant.(runtime.Type_Info_Enum); eti_ok { - return eti.values; + return eti.values } - return nil; + return nil } Enum_Field :: struct { @@ -608,307 +608,307 @@ Enum_Field :: struct { } enum_fields_zipped :: proc(Enum_Type: typeid) -> (fields: #soa[]Enum_Field) { - ti := runtime.type_info_base(type_info_of(Enum_Type)); + ti := runtime.type_info_base(type_info_of(Enum_Type)) if eti, eti_ok := ti.variant.(runtime.Type_Info_Enum); eti_ok { - return soa_zip(name=eti.names, value=eti.values); + return soa_zip(name=eti.names, value=eti.values) } - return nil; + return nil } union_variant_type_info :: proc(a: any) -> ^Type_Info { - id := union_variant_typeid(a); - return type_info_of(id); + id := union_variant_typeid(a) + return type_info_of(id) } type_info_union_is_pure_maybe :: proc(info: runtime.Type_Info_Union) -> bool { - return info.maybe && len(info.variants) == 1 && is_pointer(info.variants[0]); + return info.maybe && len(info.variants) == 1 && is_pointer(info.variants[0]) } union_variant_typeid :: proc(a: any) -> typeid { if a == nil { return nil; } - ti := runtime.type_info_base(type_info_of(a.id)); + ti := runtime.type_info_base(type_info_of(a.id)) if info, ok := ti.variant.(runtime.Type_Info_Union); ok { if type_info_union_is_pure_maybe(info) { if a.data != nil { - return info.variants[0].id; + return info.variants[0].id } - return nil; + return nil } - tag_ptr := uintptr(a.data) + info.tag_offset; - tag_any := any{rawptr(tag_ptr), info.tag_type.id}; + tag_ptr := uintptr(a.data) + info.tag_offset + tag_any := any{rawptr(tag_ptr), info.tag_type.id} - tag: i64 = ---; + tag: i64 = --- switch i in tag_any { - case u8: tag = i64(i); - case i8: tag = i64(i); - case u16: tag = i64(i); - case i16: tag = i64(i); - case u32: tag = i64(i); - case i32: tag = i64(i); - case u64: tag = i64(i); - case i64: tag = i; - case: unimplemented(); + case u8: tag = i64(i) + case i8: tag = i64(i) + case u16: tag = i64(i) + case i16: tag = i64(i) + case u32: tag = i64(i) + case i32: tag = i64(i) + case u64: tag = i64(i) + case i64: tag = i + case: unimplemented() } if a.data != nil && tag != 0 { - i := tag if info.no_nil else tag-1; - return info.variants[i].id; + i := tag if info.no_nil else tag-1 + return info.variants[i].id } - return nil; + return nil } - panic("expected a union to reflect.union_variant_typeid"); + panic("expected a union to reflect.union_variant_typeid") } get_union_variant_raw_tag :: proc(a: any) -> i64 { if a == nil { return -1; } - ti := runtime.type_info_base(type_info_of(a.id)); + ti := runtime.type_info_base(type_info_of(a.id)) if info, ok := ti.variant.(runtime.Type_Info_Union); ok { if type_info_union_is_pure_maybe(info) { - return 1 if a.data != nil else 0; + return 1 if a.data != nil else 0 } - tag_ptr := uintptr(a.data) + info.tag_offset; - tag_any := any{rawptr(tag_ptr), info.tag_type.id}; + tag_ptr := uintptr(a.data) + info.tag_offset + tag_any := any{rawptr(tag_ptr), info.tag_type.id} - tag: i64 = ---; + tag: i64 = --- switch i in tag_any { - case u8: tag = i64(i); - case i8: tag = i64(i); - case u16: tag = i64(i); - case i16: tag = i64(i); - case u32: tag = i64(i); - case i32: tag = i64(i); - case u64: tag = i64(i); - case i64: tag = i; - case: unimplemented(); + case u8: tag = i64(i) + case i8: tag = i64(i) + case u16: tag = i64(i) + case i16: tag = i64(i) + case u32: tag = i64(i) + case i32: tag = i64(i) + case u64: tag = i64(i) + case i64: tag = i + case: unimplemented() } - return tag; + return tag } - panic("expected a union to reflect.get_union_variant_raw_tag"); + panic("expected a union to reflect.get_union_variant_raw_tag") } set_union_variant_raw_tag :: proc(a: any, tag: i64) { if a == nil { return; } - ti := runtime.type_info_base(type_info_of(a.id)); + ti := runtime.type_info_base(type_info_of(a.id)) if info, ok := ti.variant.(runtime.Type_Info_Union); ok { if type_info_union_is_pure_maybe(info) { // Cannot do anything - return; + return } - tag_ptr := uintptr(a.data) + info.tag_offset; - tag_any := any{rawptr(tag_ptr), info.tag_type.id}; + tag_ptr := uintptr(a.data) + info.tag_offset + tag_any := any{rawptr(tag_ptr), info.tag_type.id} switch i in &tag_any { - case u8: i = u8(tag); - case i8: i = i8(tag); - case u16: i = u16(tag); - case i16: i = i16(tag); - case u32: i = u32(tag); - case i32: i = i32(tag); - case u64: i = u64(tag); - case i64: i = tag; - case: unimplemented(); + case u8: i = u8(tag) + case i8: i = i8(tag) + case u16: i = u16(tag) + case i16: i = i16(tag) + case u32: i = u32(tag) + case i32: i = i32(tag) + case u64: i = u64(tag) + case i64: i = tag + case: unimplemented() } - return; + return } - panic("expected a union to reflect.set_union_variant_raw_tag"); + panic("expected a union to reflect.set_union_variant_raw_tag") } set_union_variant_typeid :: proc(a: any, id: typeid) { if a == nil { return; } - ti := runtime.type_info_base(type_info_of(a.id)); + ti := runtime.type_info_base(type_info_of(a.id)) if info, ok := ti.variant.(runtime.Type_Info_Union); ok { if type_info_union_is_pure_maybe(info) { // Cannot do anything - return; + return } if id == nil && !info.no_nil { - set_union_variant_raw_tag(a, 0); - return; + set_union_variant_raw_tag(a, 0) + return } for variant, i in info.variants { if variant.id == id { - tag := i64(i); + tag := i64(i) if !info.no_nil { - tag += 1; + tag += 1 } - set_union_variant_raw_tag(a, tag); - return; + set_union_variant_raw_tag(a, tag) + return } } - return; + return } - panic("expected a union to reflect.set_union_variant_typeid"); + panic("expected a union to reflect.set_union_variant_typeid") } set_union_variant_type_info :: proc(a: any, tag_ti: ^Type_Info) { if a == nil { return; } - ti := runtime.type_info_base(type_info_of(a.id)); + ti := runtime.type_info_base(type_info_of(a.id)) if info, ok := ti.variant.(runtime.Type_Info_Union); ok { if type_info_union_is_pure_maybe(info) { // Cannot do anything - return; + return } if tag_ti == nil && !info.no_nil { - set_union_variant_raw_tag(a, 0); - return; + set_union_variant_raw_tag(a, 0) + return } for variant, i in info.variants { if variant == tag_ti { - tag := i64(i); + tag := i64(i) if !info.no_nil { - tag += 1; + tag += 1 } - set_union_variant_raw_tag(a, tag); - return; + set_union_variant_raw_tag(a, tag) + return } } - return; + return } - panic("expected a union to reflect.set_union_variant_type_info"); + panic("expected a union to reflect.set_union_variant_type_info") } as_bool :: proc(a: any) -> (value: bool, valid: bool) { if a == nil { return; } - a := a; - ti := runtime.type_info_core(type_info_of(a.id)); - a.id = ti.id; + a := a + ti := runtime.type_info_core(type_info_of(a.id)) + a.id = ti.id #partial switch info in ti.variant { case Type_Info_Boolean: - valid = true; + valid = true switch v in a { - case bool: value = v; - case b8: value = bool(v); - case b16: value = bool(v); - case b32: value = bool(v); - case b64: value = bool(v); - case: valid = false; + case bool: value = v + case b8: value = bool(v) + case b16: value = bool(v) + case b32: value = bool(v) + case b64: value = bool(v) + case: valid = false } } - return; + return } as_int :: proc(a: any) -> (value: int, valid: bool) { - v: i64; - v, valid = as_i64(a); - value = int(v); - return; + v: i64 + v, valid = as_i64(a) + value = int(v) + return } as_uint :: proc(a: any) -> (value: uint, valid: bool) { - v: u64; - v, valid = as_u64(a); - value = uint(v); - return; + v: u64 + v, valid = as_u64(a) + value = uint(v) + return } as_i64 :: proc(a: any) -> (value: i64, valid: bool) { if a == nil { return; } - a := a; - ti := runtime.type_info_core(type_info_of(a.id)); - a.id = ti.id; + a := a + ti := runtime.type_info_core(type_info_of(a.id)) + a.id = ti.id #partial switch info in ti.variant { case Type_Info_Integer: - valid = true; + valid = true switch v in a { - case i8: value = i64(v); - case i16: value = i64(v); - case i32: value = i64(v); - case i64: value = v; - case i128: value = i64(v); - case int: value = i64(v); - - case u8: value = i64(v); - case u16: value = i64(v); - case u32: value = i64(v); - case u64: value = i64(v); - case u128: value = i64(v); - case uint: value = i64(v); - case uintptr: value = i64(v); - - case u16le: value = i64(v); - case u32le: value = i64(v); - case u64le: value = i64(v); - case u128le: value = i64(v); - - case i16le: value = i64(v); - case i32le: value = i64(v); - case i64le: value = i64(v); - case i128le: value = i64(v); - - case u16be: value = i64(v); - case u32be: value = i64(v); - case u64be: value = i64(v); - case u128be: value = i64(v); - - case i16be: value = i64(v); - case i32be: value = i64(v); - case i64be: value = i64(v); - case i128be: value = i64(v); - case: valid = false; + case i8: value = i64(v) + case i16: value = i64(v) + case i32: value = i64(v) + case i64: value = v + case i128: value = i64(v) + case int: value = i64(v) + + case u8: value = i64(v) + case u16: value = i64(v) + case u32: value = i64(v) + case u64: value = i64(v) + case u128: value = i64(v) + case uint: value = i64(v) + case uintptr: value = i64(v) + + case u16le: value = i64(v) + case u32le: value = i64(v) + case u64le: value = i64(v) + case u128le: value = i64(v) + + case i16le: value = i64(v) + case i32le: value = i64(v) + case i64le: value = i64(v) + case i128le: value = i64(v) + + case u16be: value = i64(v) + case u32be: value = i64(v) + case u64be: value = i64(v) + case u128be: value = i64(v) + + case i16be: value = i64(v) + case i32be: value = i64(v) + case i64be: value = i64(v) + case i128be: value = i64(v) + case: valid = false } case Type_Info_Rune: - r := a.(rune); - value = i64(r); - valid = true; + r := a.(rune) + value = i64(r) + valid = true case Type_Info_Float: - valid = true; + valid = true switch v in a { - case f32: value = i64(v); - case f64: value = i64(v); - case f32le: value = i64(v); - case f64le: value = i64(v); - case f32be: value = i64(v); - case f64be: value = i64(v); - case: valid = false; + case f32: value = i64(v) + case f64: value = i64(v) + case f32le: value = i64(v) + case f64le: value = i64(v) + case f32be: value = i64(v) + case f64be: value = i64(v) + case: valid = false } case Type_Info_Boolean: - valid = true; + valid = true switch v in a { - case bool: value = i64(v); - case b8: value = i64(v); - case b16: value = i64(v); - case b32: value = i64(v); - case b64: value = i64(v); - case: valid = false; + case bool: value = i64(v) + case b8: value = i64(v) + case b16: value = i64(v) + case b32: value = i64(v) + case b64: value = i64(v) + case: valid = false } case Type_Info_Complex: switch v in a { case complex64: if imag(v) == 0 { - value = i64(real(v)); - valid = true; + value = i64(real(v)) + valid = true } case complex128: if imag(v) == 0 { - value = i64(real(v)); - valid = true; + value = i64(real(v)) + valid = true } } @@ -916,106 +916,106 @@ as_i64 :: proc(a: any) -> (value: i64, valid: bool) { switch v in a { case quaternion128: if imag(v) == 0 && jmag(v) == 0 && kmag(v) == 0 { - value = i64(real(v)); - valid = true; + value = i64(real(v)) + valid = true } case quaternion256: if imag(v) == 0 && jmag(v) == 0 && kmag(v) == 0 { - value = i64(real(v)); - valid = true; + value = i64(real(v)) + valid = true } } } - return; + return } as_u64 :: proc(a: any) -> (value: u64, valid: bool) { if a == nil { return; } - a := a; - ti := runtime.type_info_core(type_info_of(a.id)); - a.id = ti.id; + a := a + ti := runtime.type_info_core(type_info_of(a.id)) + a.id = ti.id #partial switch info in ti.variant { case Type_Info_Integer: - valid = true; + valid = true switch v in a { - case i8: value = u64(v); - case i16: value = u64(v); - case i32: value = u64(v); - case i64: value = u64(v); - case i128: value = u64(v); - case int: value = u64(v); - - case u8: value = u64(v); - case u16: value = u64(v); - case u32: value = u64(v); - case u64: value = (v); - case u128: value = u64(v); - case uint: value = u64(v); - case uintptr:value = u64(v); - - case u16le: value = u64(v); - case u32le: value = u64(v); - case u64le: value = u64(v); - case u128le: value = u64(v); - - case i16le: value = u64(v); - case i32le: value = u64(v); - case i64le: value = u64(v); - case i128le: value = u64(v); - - case u16be: value = u64(v); - case u32be: value = u64(v); - case u64be: value = u64(v); - case u128be: value = u64(v); - - case i16be: value = u64(v); - case i32be: value = u64(v); - case i64be: value = u64(v); - case i128be: value = u64(v); - case: valid = false; + case i8: value = u64(v) + case i16: value = u64(v) + case i32: value = u64(v) + case i64: value = u64(v) + case i128: value = u64(v) + case int: value = u64(v) + + case u8: value = u64(v) + case u16: value = u64(v) + case u32: value = u64(v) + case u64: value = (v) + case u128: value = u64(v) + case uint: value = u64(v) + case uintptr:value = u64(v) + + case u16le: value = u64(v) + case u32le: value = u64(v) + case u64le: value = u64(v) + case u128le: value = u64(v) + + case i16le: value = u64(v) + case i32le: value = u64(v) + case i64le: value = u64(v) + case i128le: value = u64(v) + + case u16be: value = u64(v) + case u32be: value = u64(v) + case u64be: value = u64(v) + case u128be: value = u64(v) + + case i16be: value = u64(v) + case i32be: value = u64(v) + case i64be: value = u64(v) + case i128be: value = u64(v) + case: valid = false } case Type_Info_Rune: - r := a.(rune); - value = u64(r); - valid = true; + r := a.(rune) + value = u64(r) + valid = true case Type_Info_Float: - valid = true; + valid = true switch v in a { - case f32: value = u64(v); - case f64: value = u64(v); - case f32le: value = u64(v); - case f64le: value = u64(v); - case f32be: value = u64(v); - case f64be: value = u64(v); - case: valid = false; + case f32: value = u64(v) + case f64: value = u64(v) + case f32le: value = u64(v) + case f64le: value = u64(v) + case f32be: value = u64(v) + case f64be: value = u64(v) + case: valid = false } case Type_Info_Boolean: - valid = true; + valid = true switch v in a { - case bool: value = u64(v); - case b8: value = u64(v); - case b16: value = u64(v); - case b32: value = u64(v); - case b64: value = u64(v); - case: valid = false; + case bool: value = u64(v) + case b8: value = u64(v) + case b16: value = u64(v) + case b32: value = u64(v) + case b64: value = u64(v) + case: valid = false } case Type_Info_Complex: switch v in a { case complex64: if imag(v) == 0 { - value = u64(real(v)); - valid = true; + value = u64(real(v)) + valid = true } case complex128: if imag(v) == 0 { - value = u64(real(v)); - valid = true; + value = u64(real(v)) + valid = true } } @@ -1023,104 +1023,104 @@ as_u64 :: proc(a: any) -> (value: u64, valid: bool) { switch v in a { case quaternion128: if imag(v) == 0 && jmag(v) == 0 && kmag(v) == 0 { - value = u64(real(v)); - valid = true; + value = u64(real(v)) + valid = true } case quaternion256: if imag(v) == 0 && jmag(v) == 0 && kmag(v) == 0 { - value = u64(real(v)); - valid = true; + value = u64(real(v)) + valid = true } } } - return; + return } as_f64 :: proc(a: any) -> (value: f64, valid: bool) { if a == nil { return; } - a := a; - ti := runtime.type_info_core(type_info_of(a.id)); - a.id = ti.id; + a := a + ti := runtime.type_info_core(type_info_of(a.id)) + a.id = ti.id #partial switch info in ti.variant { case Type_Info_Integer: - valid = true; + valid = true switch v in a { - case i8: value = f64(v); - case i16: value = f64(v); - case i32: value = f64(v); - case i64: value = f64(v); - case i128: value = f64(v); - - case u8: value = f64(v); - case u16: value = f64(v); - case u32: value = f64(v); - case u64: value = f64(v); - case u128: value = f64(v); - - case u16le: value = f64(v); - case u32le: value = f64(v); - case u64le: value = f64(v); - case u128le:value = f64(v); - - case i16le: value = f64(v); - case i32le: value = f64(v); - case i64le: value = f64(v); - case i128le:value = f64(v); - - case u16be: value = f64(v); - case u32be: value = f64(v); - case u64be: value = f64(v); - case u128be:value = f64(v); - - case i16be: value = f64(v); - case i32be: value = f64(v); - case i64be: value = f64(v); - case i128be:value = f64(v); - case: valid = false; + case i8: value = f64(v) + case i16: value = f64(v) + case i32: value = f64(v) + case i64: value = f64(v) + case i128: value = f64(v) + + case u8: value = f64(v) + case u16: value = f64(v) + case u32: value = f64(v) + case u64: value = f64(v) + case u128: value = f64(v) + + case u16le: value = f64(v) + case u32le: value = f64(v) + case u64le: value = f64(v) + case u128le:value = f64(v) + + case i16le: value = f64(v) + case i32le: value = f64(v) + case i64le: value = f64(v) + case i128le:value = f64(v) + + case u16be: value = f64(v) + case u32be: value = f64(v) + case u64be: value = f64(v) + case u128be:value = f64(v) + + case i16be: value = f64(v) + case i32be: value = f64(v) + case i64be: value = f64(v) + case i128be:value = f64(v) + case: valid = false } case Type_Info_Rune: - r := a.(rune); - value = f64(i32(r)); - valid = true; + r := a.(rune) + value = f64(i32(r)) + valid = true case Type_Info_Float: - valid = true; + valid = true switch v in a { - case f32: value = f64(v); - case f64: value = (v); - case f32le: value = f64(v); - case f64le: value = f64(v); - case f32be: value = f64(v); - case f64be: value = f64(v); - case: valid = false; + case f32: value = f64(v) + case f64: value = (v) + case f32le: value = f64(v) + case f64le: value = f64(v) + case f32be: value = f64(v) + case f64be: value = f64(v) + case: valid = false } case Type_Info_Boolean: - valid = true; + valid = true switch v in a { - case bool: value = f64(i32(v)); - case b8: value = f64(i32(v)); - case b16: value = f64(i32(v)); - case b32: value = f64(i32(v)); - case b64: value = f64(i32(v)); - case: valid = false; + case bool: value = f64(i32(v)) + case b8: value = f64(i32(v)) + case b16: value = f64(i32(v)) + case b32: value = f64(i32(v)) + case b64: value = f64(i32(v)) + case: valid = false } case Type_Info_Complex: switch v in a { case complex64: if imag(v) == 0 { - value = f64(real(v)); - valid = true; + value = f64(real(v)) + valid = true } case complex128: if imag(v) == 0 { - value = real(v); - valid = true; + value = real(v) + valid = true } } @@ -1128,91 +1128,91 @@ as_f64 :: proc(a: any) -> (value: f64, valid: bool) { switch v in a { case quaternion128: if imag(v) == 0 && jmag(v) == 0 && kmag(v) == 0 { - value = f64(real(v)); - valid = true; + value = f64(real(v)) + valid = true } case quaternion256: if imag(v) == 0 && jmag(v) == 0 && kmag(v) == 0 { - value = real(v); - valid = true; + value = real(v) + valid = true } } } - return; + return } as_string :: proc(a: any) -> (value: string, valid: bool) { if a == nil { return; } - a := a; - ti := runtime.type_info_core(type_info_of(a.id)); - a.id = ti.id; + a := a + ti := runtime.type_info_core(type_info_of(a.id)) + a.id = ti.id #partial switch info in ti.variant { case Type_Info_String: - valid = true; + valid = true switch v in a { - case string: value = v; - case cstring: value = string(v); - case: valid = false; + case string: value = v + case cstring: value = string(v) + case: valid = false } } - return; + return } relative_pointer_to_absolute :: proc(a: any) -> rawptr { if a == nil { return nil; } - a := a; - ti := runtime.type_info_core(type_info_of(a.id)); - a.id = ti.id; + a := a + ti := runtime.type_info_core(type_info_of(a.id)) + a.id = ti.id #partial switch info in ti.variant { case Type_Info_Relative_Pointer: - return relative_pointer_to_absolute_raw(a.data, info.base_integer.id); + return relative_pointer_to_absolute_raw(a.data, info.base_integer.id) } - return nil; + return nil } relative_pointer_to_absolute_raw :: proc(data: rawptr, base_integer_id: typeid) -> rawptr { _handle :: proc(ptr: ^$T) -> rawptr where intrinsics.type_is_integer(T) { if ptr^ == 0 { - return nil; + return nil } when intrinsics.type_is_unsigned(T) { - return rawptr(uintptr(ptr) + uintptr(ptr^)); + return rawptr(uintptr(ptr) + uintptr(ptr^)) } else { - return rawptr(uintptr(ptr) + uintptr(i64(ptr^))); + return rawptr(uintptr(ptr) + uintptr(i64(ptr^))) } } - ptr_any := any{data, base_integer_id}; - ptr: rawptr; + ptr_any := any{data, base_integer_id} + ptr: rawptr switch i in &ptr_any { - case u8: ptr = _handle(&i); - case u16: ptr = _handle(&i); - case u32: ptr = _handle(&i); - case u64: ptr = _handle(&i); - case i8: ptr = _handle(&i); - case i16: ptr = _handle(&i); - case i32: ptr = _handle(&i); - case i64: ptr = _handle(&i); - case u16le: ptr = _handle(&i); - case u32le: ptr = _handle(&i); - case u64le: ptr = _handle(&i); - case i16le: ptr = _handle(&i); - case i32le: ptr = _handle(&i); - case i64le: ptr = _handle(&i); - case u16be: ptr = _handle(&i); - case u32be: ptr = _handle(&i); - case u64be: ptr = _handle(&i); - case i16be: ptr = _handle(&i); - case i32be: ptr = _handle(&i); - case i64be: ptr = _handle(&i); + case u8: ptr = _handle(&i) + case u16: ptr = _handle(&i) + case u32: ptr = _handle(&i) + case u64: ptr = _handle(&i) + case i8: ptr = _handle(&i) + case i16: ptr = _handle(&i) + case i32: ptr = _handle(&i) + case i64: ptr = _handle(&i) + case u16le: ptr = _handle(&i) + case u32le: ptr = _handle(&i) + case u64le: ptr = _handle(&i) + case i16le: ptr = _handle(&i) + case i32le: ptr = _handle(&i) + case i64le: ptr = _handle(&i) + case u16be: ptr = _handle(&i) + case u32be: ptr = _handle(&i) + case u64be: ptr = _handle(&i) + case i16be: ptr = _handle(&i) + case i32be: ptr = _handle(&i) + case i64be: ptr = _handle(&i) } - return ptr; + return ptr } @@ -1220,60 +1220,60 @@ relative_pointer_to_absolute_raw :: proc(data: rawptr, base_integer_id: typeid) as_pointer :: proc(a: any) -> (value: rawptr, valid: bool) { if a == nil { return; } - a := a; - ti := runtime.type_info_core(type_info_of(a.id)); - a.id = ti.id; + a := a + ti := runtime.type_info_core(type_info_of(a.id)) + a.id = ti.id #partial switch info in ti.variant { case Type_Info_Pointer: - valid = true; - value = a.data; + valid = true + value = a.data case Type_Info_String: - valid = true; + valid = true switch v in a { - case cstring: value = rawptr(v); - case: valid = false; + case cstring: value = rawptr(v) + case: valid = false } case Type_Info_Relative_Pointer: - valid = true; - value = relative_pointer_to_absolute_raw(a.data, info.base_integer.id); + valid = true + value = relative_pointer_to_absolute_raw(a.data, info.base_integer.id) } - return; + return } as_raw_data :: proc(a: any) -> (value: rawptr, valid: bool) { if a == nil { return; } - a := a; - ti := runtime.type_info_core(type_info_of(a.id)); - a.id = ti.id; + a := a + ti := runtime.type_info_core(type_info_of(a.id)) + a.id = ti.id #partial switch info in ti.variant { case Type_Info_String: - valid = true; + valid = true switch v in a { - case string: value = raw_data(v); - case cstring: value = rawptr(v); // just in case - case: valid = false; + case string: value = raw_data(v) + case cstring: value = rawptr(v) // just in case + case: valid = false } case Type_Info_Array: - valid = true; - value = a.data; + valid = true + value = a.data case Type_Info_Slice: - valid = true; - value = (^mem.Raw_Slice)(a.data).data; + valid = true + value = (^mem.Raw_Slice)(a.data).data case Type_Info_Dynamic_Array: - valid = true; - value = (^mem.Raw_Dynamic_Array)(a.data).data; + valid = true + value = (^mem.Raw_Dynamic_Array)(a.data).data } - return; + return } /* diff --git a/core/reflect/types.odin b/core/reflect/types.odin index 74b0e23b9..3c4ccadf8 100644 --- a/core/reflect/types.odin +++ b/core/reflect/types.odin @@ -5,111 +5,111 @@ import "core:strings" are_types_identical :: proc(a, b: ^Type_Info) -> bool { if a == b { - return true; + return true } if (a == nil && b != nil) || (a != nil && b == nil) { - return false; + return false } switch { case a.size != b.size, a.align != b.align: - return false; + return false } switch x in a.variant { case Type_Info_Named: - y := b.variant.(Type_Info_Named) or_return; - return x.base == y.base; + y := b.variant.(Type_Info_Named) or_return + return x.base == y.base case Type_Info_Integer: - y := b.variant.(Type_Info_Integer) or_return; - return x.signed == y.signed && x.endianness == y.endianness; + y := b.variant.(Type_Info_Integer) or_return + return x.signed == y.signed && x.endianness == y.endianness case Type_Info_Rune: - _, ok := b.variant.(Type_Info_Rune); - return ok; + _, ok := b.variant.(Type_Info_Rune) + return ok case Type_Info_Float: - _, ok := b.variant.(Type_Info_Float); - return ok; + _, ok := b.variant.(Type_Info_Float) + return ok case Type_Info_Complex: - _, ok := b.variant.(Type_Info_Complex); - return ok; + _, ok := b.variant.(Type_Info_Complex) + return ok case Type_Info_Quaternion: - _, ok := b.variant.(Type_Info_Quaternion); - return ok; + _, ok := b.variant.(Type_Info_Quaternion) + return ok case Type_Info_Type_Id: - _, ok := b.variant.(Type_Info_Type_Id); - return ok; + _, ok := b.variant.(Type_Info_Type_Id) + return ok case Type_Info_String: - _, ok := b.variant.(Type_Info_String); - return ok; + _, ok := b.variant.(Type_Info_String) + return ok case Type_Info_Boolean: - _, ok := b.variant.(Type_Info_Boolean); - return ok; + _, ok := b.variant.(Type_Info_Boolean) + return ok case Type_Info_Any: - _, ok := b.variant.(Type_Info_Any); - return ok; + _, ok := b.variant.(Type_Info_Any) + return ok case Type_Info_Pointer: - y := b.variant.(Type_Info_Pointer) or_return; - return are_types_identical(x.elem, y.elem); + y := b.variant.(Type_Info_Pointer) or_return + return are_types_identical(x.elem, y.elem) case Type_Info_Multi_Pointer: - y := b.variant.(Type_Info_Multi_Pointer) or_return; - return are_types_identical(x.elem, y.elem); + y := b.variant.(Type_Info_Multi_Pointer) or_return + return are_types_identical(x.elem, y.elem) case Type_Info_Procedure: - y := b.variant.(Type_Info_Procedure) or_return; + y := b.variant.(Type_Info_Procedure) or_return switch { case x.variadic != y.variadic, x.convention != y.convention: - return false; + return false } - return are_types_identical(x.params, y.params) && are_types_identical(x.results, y.results); + return are_types_identical(x.params, y.params) && are_types_identical(x.results, y.results) case Type_Info_Array: - y := b.variant.(Type_Info_Array) or_return; + y := b.variant.(Type_Info_Array) or_return if x.count != y.count { return false; } - return are_types_identical(x.elem, y.elem); + return are_types_identical(x.elem, y.elem) case Type_Info_Enumerated_Array: - y := b.variant.(Type_Info_Enumerated_Array) or_return; + y := b.variant.(Type_Info_Enumerated_Array) or_return if x.count != y.count { return false; } return are_types_identical(x.index, y.index) && - are_types_identical(x.elem, y.elem); + are_types_identical(x.elem, y.elem) case Type_Info_Dynamic_Array: - y := b.variant.(Type_Info_Dynamic_Array) or_return; - return are_types_identical(x.elem, y.elem); + y := b.variant.(Type_Info_Dynamic_Array) or_return + return are_types_identical(x.elem, y.elem) case Type_Info_Slice: - y := b.variant.(Type_Info_Slice) or_return; - return are_types_identical(x.elem, y.elem); + y := b.variant.(Type_Info_Slice) or_return + return are_types_identical(x.elem, y.elem) case Type_Info_Tuple: - y := b.variant.(Type_Info_Tuple) or_return; + y := b.variant.(Type_Info_Tuple) or_return if len(x.types) != len(y.types) { return false; } for _, i in x.types { - xt, yt := x.types[i], y.types[i]; + xt, yt := x.types[i], y.types[i] if !are_types_identical(xt, yt) { - return false; + return false } } - return true; + return true case Type_Info_Struct: - y := b.variant.(Type_Info_Struct) or_return; + y := b.variant.(Type_Info_Struct) or_return switch { case len(x.types) != len(y.types), x.is_packed != y.is_packed, @@ -118,207 +118,207 @@ are_types_identical :: proc(a, b: ^Type_Info) -> bool { x.soa_kind != y.soa_kind, x.soa_base_type != y.soa_base_type, x.soa_len != y.soa_len: - return false; + return false } for _, i in x.types { - xn, yn := x.names[i], y.names[i]; - xt, yt := x.types[i], y.types[i]; - xl, yl := x.tags[i], y.tags[i]; + xn, yn := x.names[i], y.names[i] + xt, yt := x.types[i], y.types[i] + xl, yl := x.tags[i], y.tags[i] if xn != yn { return false; } if !are_types_identical(xt, yt) { return false; } if xl != yl { return false; } } - return true; + return true case Type_Info_Union: - y := b.variant.(Type_Info_Union) or_return; + y := b.variant.(Type_Info_Union) or_return if len(x.variants) != len(y.variants) { return false; } for _, i in x.variants { - xv, yv := x.variants[i], y.variants[i]; + xv, yv := x.variants[i], y.variants[i] if !are_types_identical(xv, yv) { return false; } } - return true; + return true case Type_Info_Enum: // NOTE(bill): Should be handled above - return false; + return false case Type_Info_Map: - y := b.variant.(Type_Info_Map) or_return; - return are_types_identical(x.key, y.key) && are_types_identical(x.value, y.value); + y := b.variant.(Type_Info_Map) or_return + return are_types_identical(x.key, y.key) && are_types_identical(x.value, y.value) case Type_Info_Bit_Set: - y := b.variant.(Type_Info_Bit_Set) or_return; - return x.elem == y.elem && x.lower == y.lower && x.upper == y.upper; + y := b.variant.(Type_Info_Bit_Set) or_return + return x.elem == y.elem && x.lower == y.lower && x.upper == y.upper case Type_Info_Simd_Vector: - y := b.variant.(Type_Info_Simd_Vector) or_return; - return x.count == y.count && x.elem == y.elem; + y := b.variant.(Type_Info_Simd_Vector) or_return + return x.count == y.count && x.elem == y.elem case Type_Info_Relative_Pointer: - y := b.variant.(Type_Info_Relative_Pointer) or_return; - return x.base_integer == y.base_integer && x.pointer == y.pointer; + y := b.variant.(Type_Info_Relative_Pointer) or_return + return x.base_integer == y.base_integer && x.pointer == y.pointer case Type_Info_Relative_Slice: - y := b.variant.(Type_Info_Relative_Slice) or_return; - return x.base_integer == y.base_integer && x.slice == y.slice; + y := b.variant.(Type_Info_Relative_Slice) or_return + return x.base_integer == y.base_integer && x.slice == y.slice } - return false; + return false } is_signed :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } #partial switch i in type_info_base(info).variant { - case Type_Info_Integer: return i.signed; - case Type_Info_Float: return true; + case Type_Info_Integer: return i.signed + case Type_Info_Float: return true } - return false; + return false } is_unsigned :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } #partial switch i in type_info_base(info).variant { - case Type_Info_Integer: return !i.signed; - case Type_Info_Float: return false; + case Type_Info_Integer: return !i.signed + case Type_Info_Float: return false } - return false; + return false } is_byte :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } #partial switch i in type_info_base(info).variant { - case Type_Info_Integer: return info.size == 1; + case Type_Info_Integer: return info.size == 1 } - return false; + return false } is_integer :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } - _, ok := type_info_base(info).variant.(Type_Info_Integer); - return ok; + _, ok := type_info_base(info).variant.(Type_Info_Integer) + return ok } is_rune :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } - _, ok := type_info_base(info).variant.(Type_Info_Rune); - return ok; + _, ok := type_info_base(info).variant.(Type_Info_Rune) + return ok } is_float :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } - _, ok := type_info_base(info).variant.(Type_Info_Float); - return ok; + _, ok := type_info_base(info).variant.(Type_Info_Float) + return ok } is_complex :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } - _, ok := type_info_base(info).variant.(Type_Info_Complex); - return ok; + _, ok := type_info_base(info).variant.(Type_Info_Complex) + return ok } is_quaternion :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } - _, ok := type_info_base(info).variant.(Type_Info_Quaternion); - return ok; + _, ok := type_info_base(info).variant.(Type_Info_Quaternion) + return ok } is_any :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } - _, ok := type_info_base(info).variant.(Type_Info_Any); - return ok; + _, ok := type_info_base(info).variant.(Type_Info_Any) + return ok } is_string :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } - _, ok := type_info_base(info).variant.(Type_Info_String); - return ok; + _, ok := type_info_base(info).variant.(Type_Info_String) + return ok } is_cstring :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } - v, ok := type_info_base(info).variant.(Type_Info_String); - return ok && v.is_cstring; + v, ok := type_info_base(info).variant.(Type_Info_String) + return ok && v.is_cstring } is_boolean :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } - _, ok := type_info_base(info).variant.(Type_Info_Boolean); - return ok; + _, ok := type_info_base(info).variant.(Type_Info_Boolean) + return ok } is_pointer :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } - _, ok := type_info_base(info).variant.(Type_Info_Pointer); - return ok; + _, ok := type_info_base(info).variant.(Type_Info_Pointer) + return ok } is_multi_pointer :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } - _, ok := type_info_base(info).variant.(Type_Info_Multi_Pointer); - return ok; + _, ok := type_info_base(info).variant.(Type_Info_Multi_Pointer) + return ok } is_procedure :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } - _, ok := type_info_base(info).variant.(Type_Info_Procedure); - return ok; + _, ok := type_info_base(info).variant.(Type_Info_Procedure) + return ok } is_array :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } - _, ok := type_info_base(info).variant.(Type_Info_Array); - return ok; + _, ok := type_info_base(info).variant.(Type_Info_Array) + return ok } is_enumerated_array :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } - _, ok := type_info_base(info).variant.(Type_Info_Enumerated_Array); - return ok; + _, ok := type_info_base(info).variant.(Type_Info_Enumerated_Array) + return ok } is_dynamic_array :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } - _, ok := type_info_base(info).variant.(Type_Info_Dynamic_Array); - return ok; + _, ok := type_info_base(info).variant.(Type_Info_Dynamic_Array) + return ok } is_dynamic_map :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } - _, ok := type_info_base(info).variant.(Type_Info_Map); - return ok; + _, ok := type_info_base(info).variant.(Type_Info_Map) + return ok } is_slice :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } - _, ok := type_info_base(info).variant.(Type_Info_Slice); - return ok; + _, ok := type_info_base(info).variant.(Type_Info_Slice) + return ok } is_tuple :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } - _, ok := type_info_base(info).variant.(Type_Info_Tuple); - return ok; + _, ok := type_info_base(info).variant.(Type_Info_Tuple) + return ok } is_struct :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } - s, ok := type_info_base(info).variant.(Type_Info_Struct); - return ok && !s.is_raw_union; + s, ok := type_info_base(info).variant.(Type_Info_Struct) + return ok && !s.is_raw_union } is_raw_union :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } - s, ok := type_info_base(info).variant.(Type_Info_Struct); - return ok && s.is_raw_union; + s, ok := type_info_base(info).variant.(Type_Info_Struct) + return ok && s.is_raw_union } is_union :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } - _, ok := type_info_base(info).variant.(Type_Info_Union); - return ok; + _, ok := type_info_base(info).variant.(Type_Info_Union) + return ok } is_enum :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } - _, ok := type_info_base(info).variant.(Type_Info_Enum); - return ok; + _, ok := type_info_base(info).variant.(Type_Info_Enum) + return ok } is_simd_vector :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } - _, ok := type_info_base(info).variant.(Type_Info_Simd_Vector); - return ok; + _, ok := type_info_base(info).variant.(Type_Info_Simd_Vector) + return ok } is_relative_pointer :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } - _, ok := type_info_base(info).variant.(Type_Info_Relative_Pointer); - return ok; + _, ok := type_info_base(info).variant.(Type_Info_Relative_Pointer) + return ok } is_relative_slice :: proc(info: ^Type_Info) -> bool { if info == nil { return false; } - _, ok := type_info_base(info).variant.(Type_Info_Relative_Slice); - return ok; + _, ok := type_info_base(info).variant.(Type_Info_Relative_Slice) + return ok } @@ -329,256 +329,256 @@ is_relative_slice :: proc(info: ^Type_Info) -> bool { write_typeid_builder :: proc(buf: ^strings.Builder, id: typeid) { - write_type(buf, type_info_of(id)); + write_type(buf, type_info_of(id)) } write_typeid_writer :: proc(writer: io.Writer, id: typeid) { - write_type(writer, type_info_of(id)); + write_type(writer, type_info_of(id)) } write_typeid :: proc{ write_typeid_builder, write_typeid_writer, -}; +} write_type :: proc{ write_type_builder, write_type_writer, -}; +} write_type_builder :: proc(buf: ^strings.Builder, ti: ^Type_Info) -> int { - return write_type_writer(strings.to_writer(buf), ti); + return write_type_writer(strings.to_writer(buf), ti) } write_type_writer :: proc(w: io.Writer, ti: ^Type_Info) -> (n: int) { - using strings; + using strings if ti == nil { - return write_string(w, "nil"); + return write_string(w, "nil") } - _n1 :: proc(err: io.Error) -> int { return 1 if err == nil else 0; }; - _n2 :: proc(n: int, _: io.Error) -> int { return n; }; - _n :: proc{_n1, _n2}; + _n1 :: proc(err: io.Error) -> int { return 1 if err == nil else 0; } + _n2 :: proc(n: int, _: io.Error) -> int { return n; } + _n :: proc{_n1, _n2} switch info in ti.variant { case Type_Info_Named: - return write_string(w, info.name); + return write_string(w, info.name) case Type_Info_Integer: switch ti.id { - case int: return write_string(w, "int"); - case uint: return write_string(w, "uint"); - case uintptr: return write_string(w, "uintptr"); + case int: return write_string(w, "int") + case uint: return write_string(w, "uint") + case uintptr: return write_string(w, "uintptr") case: - n += _n(io.write_byte(w, 'i' if info.signed else 'u')); - n += _n(io.write_i64(w, i64(8*ti.size), 10)); + n += _n(io.write_byte(w, 'i' if info.signed else 'u')) + n += _n(io.write_i64(w, i64(8*ti.size), 10)) switch info.endianness { case .Platform: // Okay - case .Little: n += write_string(w, "le"); - case .Big: n += write_string(w, "be"); + case .Little: n += write_string(w, "le") + case .Big: n += write_string(w, "be") } } case Type_Info_Rune: - n += _n(io.write_string(w, "rune")); + n += _n(io.write_string(w, "rune")) case Type_Info_Float: - n += _n(io.write_byte(w, 'f')); - n += _n(io.write_i64(w, i64(8*ti.size), 10)); + n += _n(io.write_byte(w, 'f')) + n += _n(io.write_i64(w, i64(8*ti.size), 10)) switch info.endianness { case .Platform: // Okay - case .Little: n += write_string(w, "le"); - case .Big: n += write_string(w, "be"); + case .Little: n += write_string(w, "le") + case .Big: n += write_string(w, "be") } case Type_Info_Complex: - n += _n(io.write_string(w, "complex")); - n += _n(io.write_i64(w, i64(8*ti.size), 10)); + n += _n(io.write_string(w, "complex")) + n += _n(io.write_i64(w, i64(8*ti.size), 10)) case Type_Info_Quaternion: - n += _n(io.write_string(w, "quaternion")); - n += _n(io.write_i64(w, i64(8*ti.size), 10)); + n += _n(io.write_string(w, "quaternion")) + n += _n(io.write_i64(w, i64(8*ti.size), 10)) case Type_Info_String: if info.is_cstring { - n += write_string(w, "cstring"); + n += write_string(w, "cstring") } else { - n += write_string(w, "string"); + n += write_string(w, "string") } case Type_Info_Boolean: switch ti.id { - case bool: n += write_string(w, "bool"); + case bool: n += write_string(w, "bool") case: - n += _n(io.write_byte(w, 'b')); - n += _n(io.write_i64(w, i64(8*ti.size), 10)); + n += _n(io.write_byte(w, 'b')) + n += _n(io.write_i64(w, i64(8*ti.size), 10)) } case Type_Info_Any: - n += write_string(w, "any"); + n += write_string(w, "any") case Type_Info_Type_Id: - n += write_string(w, "typeid"); + n += write_string(w, "typeid") case Type_Info_Pointer: if info.elem == nil { - write_string(w, "rawptr"); + write_string(w, "rawptr") } else { - write_string(w, "^"); - write_type(w, info.elem); + write_string(w, "^") + write_type(w, info.elem) } case Type_Info_Multi_Pointer: - write_string(w, "[^]"); - write_type(w, info.elem); + write_string(w, "[^]") + write_type(w, info.elem) case Type_Info_Procedure: - n += write_string(w, "proc"); + n += write_string(w, "proc") if info.params == nil { - n += write_string(w, "()"); + n += write_string(w, "()") } else { - t := info.params.variant.(Type_Info_Tuple); - n += write_string(w, "("); + t := info.params.variant.(Type_Info_Tuple) + n += write_string(w, "(") for t, i in t.types { if i > 0 { - n += write_string(w, ", "); + n += write_string(w, ", ") } - n += write_type(w, t); + n += write_type(w, t) } - n += write_string(w, ")"); + n += write_string(w, ")") } if info.results != nil { - n += write_string(w, " -> "); - n += write_type(w, info.results); + n += write_string(w, " -> ") + n += write_type(w, info.results) } case Type_Info_Tuple: - count := len(info.names); + count := len(info.names) if count != 1 { n += write_string(w, "("); } for name, i in info.names { if i > 0 { n += write_string(w, ", "); } - t := info.types[i]; + t := info.types[i] if len(name) > 0 { - n += write_string(w, name); - n += write_string(w, ": "); + n += write_string(w, name) + n += write_string(w, ": ") } - n += write_type(w, t); + n += write_type(w, t) } if count != 1 { n += write_string(w, ")"); } case Type_Info_Array: - n += _n(io.write_string(w, "[")); - n += _n(io.write_i64(w, i64(info.count), 10)); - n += _n(io.write_string(w, "]")); - n += write_type(w, info.elem); + n += _n(io.write_string(w, "[")) + n += _n(io.write_i64(w, i64(info.count), 10)) + n += _n(io.write_string(w, "]")) + n += write_type(w, info.elem) case Type_Info_Enumerated_Array: - n += write_string(w, "["); - n += write_type(w, info.index); - n += write_string(w, "]"); - n += write_type(w, info.elem); + n += write_string(w, "[") + n += write_type(w, info.index) + n += write_string(w, "]") + n += write_type(w, info.elem) case Type_Info_Dynamic_Array: - n += _n(io.write_string(w, "[dynamic]")); - n += write_type(w, info.elem); + n += _n(io.write_string(w, "[dynamic]")) + n += write_type(w, info.elem) case Type_Info_Slice: - n += _n(io.write_string(w, "[]")); - n += write_type(w, info.elem); + n += _n(io.write_string(w, "[]")) + n += write_type(w, info.elem) case Type_Info_Map: - n += _n(io.write_string(w, "map[")); - n += write_type(w, info.key); - n += _n(io.write_byte(w, ']')); - n += write_type(w, info.value); + n += _n(io.write_string(w, "map[")) + n += write_type(w, info.key) + n += _n(io.write_byte(w, ']')) + n += write_type(w, info.value) case Type_Info_Struct: switch info.soa_kind { case .None: // Ignore case .Fixed: - n += _n(io.write_string(w, "#soa[")); - n += _n(io.write_i64(w, i64(info.soa_len))); - n += _n(io.write_byte(w, ']')); - n += write_type(w, info.soa_base_type); - return; + n += _n(io.write_string(w, "#soa[")) + n += _n(io.write_i64(w, i64(info.soa_len))) + n += _n(io.write_byte(w, ']')) + n += write_type(w, info.soa_base_type) + return case .Slice: - n += _n(io.write_string(w, "#soa[]")); - n += write_type(w, info.soa_base_type); - return; + n += _n(io.write_string(w, "#soa[]")) + n += write_type(w, info.soa_base_type) + return case .Dynamic: - n += _n(io.write_string(w, "#soa[dynamic]")); - n += write_type(w, info.soa_base_type); - return; + n += _n(io.write_string(w, "#soa[dynamic]")) + n += write_type(w, info.soa_base_type) + return } - n += write_string(w, "struct "); + n += write_string(w, "struct ") if info.is_packed { n += write_string(w, "#packed "); } if info.is_raw_union { n += write_string(w, "#raw_union "); } if info.custom_align { - n += _n(io.write_string(w, "#align ")); - n += _n(io.write_i64(w, i64(ti.align), 10)); - n += _n(io.write_byte(w, ' ')); + n += _n(io.write_string(w, "#align ")) + n += _n(io.write_i64(w, i64(ti.align), 10)) + n += _n(io.write_byte(w, ' ')) } - n += _n(io.write_byte(w, '{')); + n += _n(io.write_byte(w, '{')) for name, i in info.names { if i > 0 { n += write_string(w, ", "); } - n += _n(io.write_string(w, name)); - n += _n(io.write_string(w, ": ")); - n += write_type(w, info.types[i]); + n += _n(io.write_string(w, name)) + n += _n(io.write_string(w, ": ")) + n += write_type(w, info.types[i]) } - n += _n(io.write_byte(w, '}')); + n += _n(io.write_byte(w, '}')) case Type_Info_Union: - n += write_string(w, "union "); + n += write_string(w, "union ") if info.custom_align { - n += write_string(w, "#align "); - n += _n(io.write_i64(w, i64(ti.align), 10)); - n += _n(io.write_byte(w, ' ')); + n += write_string(w, "#align ") + n += _n(io.write_i64(w, i64(ti.align), 10)) + n += _n(io.write_byte(w, ' ')) } - n += _n(io.write_byte(w, '{')); + n += _n(io.write_byte(w, '{')) for variant, i in info.variants { if i > 0 { n += write_string(w, ", "); } - n += write_type(w, variant); + n += write_type(w, variant) } - n += _n(io.write_byte(w, '}')); + n += _n(io.write_byte(w, '}')) case Type_Info_Enum: - n += write_string(w, "enum "); - n += write_type(w, info.base); - n += write_string(w, " {"); + n += write_string(w, "enum ") + n += write_type(w, info.base) + n += write_string(w, " {") for name, i in info.names { if i > 0 { n += write_string(w, ", "); } - n += write_string(w, name); + n += write_string(w, name) } - n += _n(io.write_byte(w, '}')); + n += _n(io.write_byte(w, '}')) case Type_Info_Bit_Set: - n += write_string(w, "bit_set["); + n += write_string(w, "bit_set[") switch { case is_enum(info.elem): - n += write_type(w, info.elem); + n += write_type(w, info.elem) case is_rune(info.elem): - n += write_encoded_rune(w, rune(info.lower)); - n += write_string(w, ".."); - n += write_encoded_rune(w, rune(info.upper)); + n += write_encoded_rune(w, rune(info.lower)) + n += write_string(w, "..") + n += write_encoded_rune(w, rune(info.upper)) case: - n += _n(io.write_i64(w, info.lower, 10)); - n += write_string(w, ".."); - n += _n(io.write_i64(w, info.upper, 10)); + n += _n(io.write_i64(w, info.lower, 10)) + n += write_string(w, "..") + n += _n(io.write_i64(w, info.upper, 10)) } if info.underlying != nil { - n += write_string(w, "; "); - n += write_type(w, info.underlying); + n += write_string(w, "; ") + n += write_type(w, info.underlying) } - n += _n(io.write_byte(w, ']')); + n += _n(io.write_byte(w, ']')) case Type_Info_Simd_Vector: - n += write_string(w, "#simd["); - n += _n(io.write_i64(w, i64(info.count))); - n += _n(io.write_byte(w, ']')); - n += write_type(w, info.elem); + n += write_string(w, "#simd[") + n += _n(io.write_i64(w, i64(info.count))) + n += _n(io.write_byte(w, ']')) + n += write_type(w, info.elem) case Type_Info_Relative_Pointer: - n += write_string(w, "#relative("); - n += write_type(w, info.base_integer); - n += write_string(w, ") "); - n += write_type(w, info.pointer); + n += write_string(w, "#relative(") + n += write_type(w, info.base_integer) + n += write_string(w, ") ") + n += write_type(w, info.pointer) case Type_Info_Relative_Slice: - n += write_string(w, "#relative("); - n += write_type(w, info.base_integer); - n += write_string(w, ") "); - n += write_type(w, info.slice); + n += write_string(w, "#relative(") + n += write_type(w, info.base_integer) + n += write_string(w, ") ") + n += write_type(w, info.slice) } - return; + return } diff --git a/core/runtime/core.odin b/core/runtime/core.odin index e4c3dd30a..e49470ebc 100644 --- a/core/runtime/core.odin +++ b/core/runtime/core.odin @@ -35,7 +35,7 @@ Calling_Convention :: enum u8 { Naked = 7, } -Type_Info_Enum_Value :: distinct i64; +Type_Info_Enum_Value :: distinct i64 Platform_Endianness :: enum u8 { Platform = 0, @@ -44,9 +44,9 @@ Platform_Endianness :: enum u8 { } // Procedure type to test whether two values of the same type are equal -Equal_Proc :: distinct proc "contextless" (rawptr, rawptr) -> bool; +Equal_Proc :: distinct proc "contextless" (rawptr, rawptr) -> bool // Procedure type to hash a value, default seed value is 0 -Hasher_Proc :: distinct proc "contextless" (data: rawptr, seed: uintptr = 0) -> uintptr; +Hasher_Proc :: distinct proc "contextless" (data: rawptr, seed: uintptr = 0) -> uintptr Type_Info_Struct_Soa_Kind :: enum u8 { None = 0, @@ -61,33 +61,33 @@ Type_Info_Named :: struct { base: ^Type_Info, pkg: string, loc: Source_Code_Location, -}; -Type_Info_Integer :: struct {signed: bool, endianness: Platform_Endianness}; -Type_Info_Rune :: struct {}; -Type_Info_Float :: struct {endianness: Platform_Endianness}; -Type_Info_Complex :: struct {}; -Type_Info_Quaternion :: struct {}; -Type_Info_String :: struct {is_cstring: bool}; -Type_Info_Boolean :: struct {}; -Type_Info_Any :: struct {}; -Type_Info_Type_Id :: struct {}; +} +Type_Info_Integer :: struct {signed: bool, endianness: Platform_Endianness} +Type_Info_Rune :: struct {} +Type_Info_Float :: struct {endianness: Platform_Endianness} +Type_Info_Complex :: struct {} +Type_Info_Quaternion :: struct {} +Type_Info_String :: struct {is_cstring: bool} +Type_Info_Boolean :: struct {} +Type_Info_Any :: struct {} +Type_Info_Type_Id :: struct {} Type_Info_Pointer :: struct { elem: ^Type_Info, // nil -> rawptr -}; +} Type_Info_Multi_Pointer :: struct { elem: ^Type_Info, -}; +} Type_Info_Procedure :: struct { params: ^Type_Info, // Type_Info_Tuple results: ^Type_Info, // Type_Info_Tuple variadic: bool, convention: Calling_Convention, -}; +} Type_Info_Array :: struct { elem: ^Type_Info, elem_size: int, count: int, -}; +} Type_Info_Enumerated_Array :: struct { elem: ^Type_Info, index: ^Type_Info, @@ -95,13 +95,13 @@ Type_Info_Enumerated_Array :: struct { count: int, min_value: Type_Info_Enum_Value, max_value: Type_Info_Enum_Value, -}; -Type_Info_Dynamic_Array :: struct {elem: ^Type_Info, elem_size: int}; -Type_Info_Slice :: struct {elem: ^Type_Info, elem_size: int}; +} +Type_Info_Dynamic_Array :: struct {elem: ^Type_Info, elem_size: int} +Type_Info_Slice :: struct {elem: ^Type_Info, elem_size: int} Type_Info_Tuple :: struct { // Only used for procedures parameters and results types: []^Type_Info, names: []string, -}; +} Type_Info_Struct :: struct { types: []^Type_Info, @@ -119,7 +119,7 @@ Type_Info_Struct :: struct { soa_kind: Type_Info_Struct_Soa_Kind, soa_base_type: ^Type_Info, soa_len: int, -}; +} Type_Info_Union :: struct { variants: []^Type_Info, tag_offset: uintptr, @@ -130,44 +130,44 @@ Type_Info_Union :: struct { custom_align: bool, no_nil: bool, maybe: bool, -}; +} Type_Info_Enum :: struct { base: ^Type_Info, names: []string, values: []Type_Info_Enum_Value, -}; +} Type_Info_Map :: struct { key: ^Type_Info, value: ^Type_Info, generated_struct: ^Type_Info, key_equal: Equal_Proc, key_hasher: Hasher_Proc, -}; +} Type_Info_Bit_Set :: struct { elem: ^Type_Info, underlying: ^Type_Info, // Possibly nil lower: i64, upper: i64, -}; +} Type_Info_Simd_Vector :: struct { elem: ^Type_Info, elem_size: int, count: int, -}; +} Type_Info_Relative_Pointer :: struct { pointer: ^Type_Info, base_integer: ^Type_Info, -}; +} Type_Info_Relative_Slice :: struct { slice: ^Type_Info, base_integer: ^Type_Info, -}; +} Type_Info_Flag :: enum u8 { Comparable = 0, Simple_Compare = 1, -}; -Type_Info_Flags :: distinct bit_set[Type_Info_Flag; u32]; +} +Type_Info_Flags :: distinct bit_set[Type_Info_Flag; u32] Type_Info :: struct { size: int, @@ -247,9 +247,9 @@ Typeid_Kind :: enum u8 { // NOTE(bill): only the ones that are needed (not all types) // This will be set by the compiler -type_table: []Type_Info; +type_table: []Type_Info -args__: []cstring; +args__: []cstring // IMPORTANT NOTE(bill): Must be in this order (as the compiler relies upon it) @@ -260,7 +260,7 @@ Source_Code_Location :: struct { procedure: string, } -Assertion_Failure_Proc :: #type proc(prefix, message: string, loc: Source_Code_Location) -> !; +Assertion_Failure_Proc :: #type proc(prefix, message: string, loc: Source_Code_Location) -> ! // Allocation Stuff Allocator_Mode :: enum byte { @@ -272,7 +272,7 @@ Allocator_Mode :: enum byte { Query_Info, } -Allocator_Mode_Set :: distinct bit_set[Allocator_Mode]; +Allocator_Mode_Set :: distinct bit_set[Allocator_Mode] Allocator_Query_Info :: struct { pointer: rawptr, @@ -291,7 +291,7 @@ Allocator_Error :: enum byte { Allocator_Proc :: #type proc(allocator_data: rawptr, mode: Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, - location: Source_Code_Location = #caller_location) -> ([]byte, Allocator_Error); + location: Source_Code_Location = #caller_location) -> ([]byte, Allocator_Error) Allocator :: struct { procedure: Allocator_Proc, data: rawptr, @@ -319,8 +319,8 @@ Logger_Option :: enum { Thread_Id, } -Logger_Options :: bit_set[Logger_Option]; -Logger_Proc :: #type proc(data: rawptr, level: Logger_Level, text: string, options: Logger_Options, location := #caller_location); +Logger_Options :: bit_set[Logger_Option] +Logger_Proc :: #type proc(data: rawptr, level: Logger_Level, text: string, options: Logger_Options, location := #caller_location) Logger :: struct { procedure: Logger_Proc, @@ -386,63 +386,63 @@ foreign { type_info_base :: proc "contextless" (info: ^Type_Info) -> ^Type_Info { if info == nil { - return nil; + return nil } - base := info; + base := info loop: for { #partial switch i in base.variant { - case Type_Info_Named: base = i.base; - case: break loop; + case Type_Info_Named: base = i.base + case: break loop } } - return base; + return base } type_info_core :: proc "contextless" (info: ^Type_Info) -> ^Type_Info { if info == nil { - return nil; + return nil } - base := info; + base := info loop: for { #partial switch i in base.variant { - case Type_Info_Named: base = i.base; - case Type_Info_Enum: base = i.base; - case: break loop; + case Type_Info_Named: base = i.base + case Type_Info_Enum: base = i.base + case: break loop } } - return base; + return base } -type_info_base_without_enum :: type_info_core; +type_info_base_without_enum :: type_info_core __type_info_of :: proc "contextless" (id: typeid) -> ^Type_Info #no_bounds_check { - MASK :: 1<<(8*size_of(typeid) - 8) - 1; - data := transmute(uintptr)id; - n := int(data & MASK); + MASK :: 1<<(8*size_of(typeid) - 8) - 1 + data := transmute(uintptr)id + n := int(data & MASK) if n < 0 || n >= len(type_table) { - n = 0; + n = 0 } - return &type_table[n]; + return &type_table[n] } typeid_base :: proc "contextless" (id: typeid) -> typeid { - ti := type_info_of(id); - ti = type_info_base(ti); - return ti.id; + ti := type_info_of(id) + ti = type_info_base(ti) + return ti.id } typeid_core :: proc "contextless" (id: typeid) -> typeid { - ti := type_info_core(type_info_of(id)); - return ti.id; + ti := type_info_core(type_info_of(id)) + return ti.id } -typeid_base_without_enum :: typeid_core; +typeid_base_without_enum :: typeid_core -debug_trap :: intrinsics.debug_trap; -trap :: intrinsics.trap; -read_cycle_counter :: intrinsics.read_cycle_counter; +debug_trap :: intrinsics.debug_trap +trap :: intrinsics.trap +read_cycle_counter :: intrinsics.read_cycle_counter @@ -451,53 +451,53 @@ default_logger_proc :: proc(data: rawptr, level: Logger_Level, text: string, opt } default_logger :: proc() -> Logger { - return Logger{default_logger_proc, nil, Logger_Level.Debug, nil}; + return Logger{default_logger_proc, nil, Logger_Level.Debug, nil} } default_context :: proc "contextless" () -> Context { - c: Context; - __init_context(&c); - return c; + c: Context + __init_context(&c) + return c } @private __init_context_from_ptr :: proc "contextless" (c: ^Context, other: ^Context) { if c == nil { - return; + return } - c^ = other^; - __init_context(c); + c^ = other^ + __init_context(c) } @private __init_context :: proc "contextless" (c: ^Context) { if c == nil { - return; + return } // NOTE(bill): Do not initialize these procedures with a call as they are not defined with the "contexless" calling convention - c.allocator.procedure = default_allocator_proc; - c.allocator.data = nil; + c.allocator.procedure = default_allocator_proc + c.allocator.data = nil - c.temp_allocator.procedure = default_temp_allocator_proc; - c.temp_allocator.data = &global_default_temp_allocator_data; + c.temp_allocator.procedure = default_temp_allocator_proc + c.temp_allocator.data = &global_default_temp_allocator_data - c.assertion_failure_proc = default_assertion_failure_proc; + c.assertion_failure_proc = default_assertion_failure_proc - c.logger.procedure = default_logger_proc; - c.logger.data = nil; + c.logger.procedure = default_logger_proc + c.logger.data = nil } default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code_Location) -> ! { - print_caller_location(loc); - print_string(" "); - print_string(prefix); + print_caller_location(loc) + print_string(" ") + print_string(prefix) if len(message) > 0 { - print_string(": "); - print_string(message); + print_string(": ") + print_string(message) } - print_byte('\n'); + print_byte('\n') // intrinsics.debug_trap(); - intrinsics.trap(); + intrinsics.trap() } diff --git a/core/runtime/core_builtin.odin b/core/runtime/core_builtin.odin index 88e769056..f4973089b 100644 --- a/core/runtime/core_builtin.odin +++ b/core/runtime/core_builtin.odin @@ -3,156 +3,156 @@ package runtime import "core:intrinsics" @builtin -Maybe :: union($T: typeid) #maybe {T}; +Maybe :: union($T: typeid) #maybe {T} -@thread_local global_default_temp_allocator_data: Default_Temp_Allocator; +@thread_local global_default_temp_allocator_data: Default_Temp_Allocator @builtin init_global_temporary_allocator :: proc(size: int, backup_allocator := context.allocator) { - default_temp_allocator_init(&global_default_temp_allocator_data, size, backup_allocator); + default_temp_allocator_init(&global_default_temp_allocator_data, size, backup_allocator) } @builtin copy_slice :: proc "contextless" (dst, src: $T/[]$E) -> int { - n := max(0, min(len(dst), len(src))); + n := max(0, min(len(dst), len(src))) if n > 0 { - intrinsics.mem_copy(raw_data(dst), raw_data(src), n*size_of(E)); + intrinsics.mem_copy(raw_data(dst), raw_data(src), n*size_of(E)) } - return n; + return n } @builtin copy_from_string :: proc "contextless" (dst: $T/[]$E/u8, src: $S/string) -> int { - n := max(0, min(len(dst), len(src))); + n := max(0, min(len(dst), len(src))) if n > 0 { - intrinsics.mem_copy(raw_data(dst), raw_data(src), n); + intrinsics.mem_copy(raw_data(dst), raw_data(src), n) } - return n; + return n } @builtin -copy :: proc{copy_slice, copy_from_string}; +copy :: proc{copy_slice, copy_from_string} @builtin unordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_location) #no_bounds_check { - bounds_check_error_loc(loc, index, len(array)); - n := len(array)-1; + bounds_check_error_loc(loc, index, len(array)) + n := len(array)-1 if index != n { - array[index] = array[n]; + array[index] = array[n] } - (^Raw_Dynamic_Array)(array).len -= 1; + (^Raw_Dynamic_Array)(array).len -= 1 } @builtin ordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_location) #no_bounds_check { - bounds_check_error_loc(loc, index, len(array)); + bounds_check_error_loc(loc, index, len(array)) if index+1 < len(array) { - copy(array[index:], array[index+1:]); + copy(array[index:], array[index+1:]) } - (^Raw_Dynamic_Array)(array).len -= 1; + (^Raw_Dynamic_Array)(array).len -= 1 } @builtin remove_range :: proc(array: ^$D/[dynamic]$T, lo, hi: int, loc := #caller_location) #no_bounds_check { - slice_expr_error_lo_hi_loc(loc, lo, hi, len(array)); - n := max(hi-lo, 0); + slice_expr_error_lo_hi_loc(loc, lo, hi, len(array)) + n := max(hi-lo, 0) if n > 0 { if hi != len(array) { - copy(array[lo:], array[hi:]); + copy(array[lo:], array[hi:]) } - (^Raw_Dynamic_Array)(array).len -= n; + (^Raw_Dynamic_Array)(array).len -= n } } @builtin pop :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) #no_bounds_check { - assert(len(array) > 0, "", loc); - res = array[len(array)-1]; - (^Raw_Dynamic_Array)(array).len -= 1; - return res; + assert(len(array) > 0, "", loc) + res = array[len(array)-1] + (^Raw_Dynamic_Array)(array).len -= 1 + return res } @builtin pop_safe :: proc(array: ^$T/[dynamic]$E) -> (res: E, ok: bool) #no_bounds_check { if len(array) == 0 { - return; + return } - res, ok = array[len(array)-1], true; - (^Raw_Dynamic_Array)(array).len -= 1; - return; + res, ok = array[len(array)-1], true + (^Raw_Dynamic_Array)(array).len -= 1 + return } @builtin pop_front :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) #no_bounds_check { - assert(len(array) > 0, "", loc); - res = array[0]; + assert(len(array) > 0, "", loc) + res = array[0] if len(array) > 1 { - copy(array[0:], array[1:]); + copy(array[0:], array[1:]) } - (^Raw_Dynamic_Array)(array).len -= 1; - return res; + (^Raw_Dynamic_Array)(array).len -= 1 + return res } @builtin pop_front_safe :: proc(array: ^$T/[dynamic]$E) -> (res: E, ok: bool) #no_bounds_check { if len(array) == 0 { - return; + return } - res, ok = array[0], true; + res, ok = array[0], true if len(array) > 1 { - copy(array[0:], array[1:]); + copy(array[0:], array[1:]) } - (^Raw_Dynamic_Array)(array).len -= 1; - return; + (^Raw_Dynamic_Array)(array).len -= 1 + return } @builtin -clear :: proc{clear_dynamic_array, clear_map}; +clear :: proc{clear_dynamic_array, clear_map} @builtin -reserve :: proc{reserve_dynamic_array, reserve_map}; +reserve :: proc{reserve_dynamic_array, reserve_map} @builtin -resize :: proc{resize_dynamic_array}; +resize :: proc{resize_dynamic_array} @builtin -free :: proc{mem_free}; +free :: proc{mem_free} @builtin -free_all :: proc{mem_free_all}; +free_all :: proc{mem_free_all} @builtin delete_string :: proc(str: string, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { - return mem_free(raw_data(str), allocator, loc); + return mem_free(raw_data(str), allocator, loc) } @builtin delete_cstring :: proc(str: cstring, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { - return mem_free((^byte)(str), allocator, loc); + return mem_free((^byte)(str), allocator, loc) } @builtin delete_dynamic_array :: proc(array: $T/[dynamic]$E, loc := #caller_location) -> Allocator_Error { - return mem_free(raw_data(array), array.allocator, loc); + return mem_free(raw_data(array), array.allocator, loc) } @builtin delete_slice :: proc(array: $T/[]$E, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { - return mem_free(raw_data(array), allocator, loc); + return mem_free(raw_data(array), allocator, loc) } @builtin delete_map :: proc(m: $T/map[$K]$V, loc := #caller_location) -> Allocator_Error { - raw := transmute(Raw_Map)m; - err := delete_slice(raw.hashes, raw.entries.allocator, loc); - err1 := mem_free(raw.entries.data, raw.entries.allocator, loc); + raw := transmute(Raw_Map)m + err := delete_slice(raw.hashes, raw.entries.allocator, loc) + err1 := mem_free(raw.entries.data, raw.entries.allocator, loc) if err == nil { - err = err1; + err = err1 } - return err; + return err } @@ -163,84 +163,84 @@ delete :: proc{ delete_dynamic_array, delete_slice, delete_map, -}; +} // The new built-in procedure allocates memory. The first argument is a type, not a value, and the value // return is a pointer to a newly allocated value of that type using the specified allocator, default is context.allocator @builtin new :: proc($T: typeid, allocator := context.allocator, loc := #caller_location) -> (^T, Allocator_Error) #optional_second { - return new_aligned(T, align_of(T), allocator, loc); + return new_aligned(T, align_of(T), allocator, loc) } new_aligned :: proc($T: typeid, alignment: int, allocator := context.allocator, loc := #caller_location) -> (t: ^T, err: Allocator_Error) { - data := mem_alloc_bytes(size_of(T), alignment, allocator, loc) or_return; - t = (^T)(raw_data(data)); - return; + data := mem_alloc_bytes(size_of(T), alignment, allocator, loc) or_return + t = (^T)(raw_data(data)) + return } @builtin new_clone :: proc(data: $T, allocator := context.allocator, loc := #caller_location) -> (t: ^T, err: Allocator_Error) #optional_second { - t_data := mem_alloc_bytes(size_of(T), align_of(T), allocator, loc) or_return; - t = (^T)(raw_data(t_data)); + t_data := mem_alloc_bytes(size_of(T), align_of(T), allocator, loc) or_return + t = (^T)(raw_data(t_data)) if t != nil { - t^ = data; + t^ = data } - return; + return } -DEFAULT_RESERVE_CAPACITY :: 16; +DEFAULT_RESERVE_CAPACITY :: 16 make_aligned :: proc($T: typeid/[]$E, #any_int len: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_second { - make_slice_error_loc(loc, len); - data, err := mem_alloc_bytes(size_of(E)*len, alignment, allocator, loc); + make_slice_error_loc(loc, len) + data, err := mem_alloc_bytes(size_of(E)*len, alignment, allocator, loc) if data == nil && size_of(E) != 0 { - return nil, err; + return nil, err } - s := Raw_Slice{raw_data(data), len}; - return transmute(T)s, err; + s := Raw_Slice{raw_data(data), len} + return transmute(T)s, err } @(builtin) make_slice :: proc($T: typeid/[]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_second { - return make_aligned(T, len, align_of(E), allocator, loc); + return make_aligned(T, len, align_of(E), allocator, loc) } @(builtin) make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_second { - return make_dynamic_array_len_cap(T, 0, DEFAULT_RESERVE_CAPACITY, allocator, loc); + return make_dynamic_array_len_cap(T, 0, DEFAULT_RESERVE_CAPACITY, allocator, loc) } @(builtin) make_dynamic_array_len :: proc($T: typeid/[dynamic]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_second { - return make_dynamic_array_len_cap(T, len, len, allocator, loc); + return make_dynamic_array_len_cap(T, len, len, allocator, loc) } @(builtin) make_dynamic_array_len_cap :: proc($T: typeid/[dynamic]$E, #any_int len: int, #any_int cap: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_second { - make_dynamic_array_error_loc(loc, len, cap); - data := mem_alloc_bytes(size_of(E)*cap, align_of(E), allocator, loc) or_return; - s := Raw_Dynamic_Array{raw_data(data), len, cap, allocator}; + make_dynamic_array_error_loc(loc, len, cap) + data := mem_alloc_bytes(size_of(E)*cap, align_of(E), allocator, loc) or_return + s := Raw_Dynamic_Array{raw_data(data), len, cap, allocator} if data == nil && size_of(E) != 0 { - s.len, s.cap = 0, 0; + s.len, s.cap = 0, 0 } - array = transmute(T)s; - return; + array = transmute(T)s + return } @(builtin) make_map :: proc($T: typeid/map[$K]$E, #any_int cap: int = DEFAULT_RESERVE_CAPACITY, allocator := context.allocator, loc := #caller_location) -> T { - make_map_expr_error_loc(loc, cap); - context.allocator = allocator; + make_map_expr_error_loc(loc, cap) + context.allocator = allocator - m: T; - reserve_map(&m, cap); - return m; + m: T + reserve_map(&m, cap) + return m } @(builtin) make_multi_pointer :: proc($T: typeid/[^]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (mp: T, err: Allocator_Error) #optional_second { - make_slice_error_loc(loc, len); - data := mem_alloc_bytes(size_of(E)*len, align_of(E), allocator, loc) or_return; + make_slice_error_loc(loc, len) + data := mem_alloc_bytes(size_of(E)*len, align_of(E), allocator, loc) or_return if data == nil && size_of(E) != 0 { - return; + return } - mp = cast(T)raw_data(data); - return; + mp = cast(T)raw_data(data) + return } @@ -256,27 +256,27 @@ make :: proc{ make_dynamic_array_len_cap, make_map, make_multi_pointer, -}; +} @builtin clear_map :: proc "contextless" (m: ^$T/map[$K]$V) { if m == nil { - return; + return } - raw_map := (^Raw_Map)(m); - entries := (^Raw_Dynamic_Array)(&raw_map.entries); - entries.len = 0; + raw_map := (^Raw_Map)(m) + entries := (^Raw_Dynamic_Array)(&raw_map.entries) + entries.len = 0 for _, i in raw_map.hashes { - raw_map.hashes[i] = -1; + raw_map.hashes[i] = -1 } } @builtin reserve_map :: proc(m: ^$T/map[$K]$V, capacity: int) { if m != nil { - __dynamic_map_reserve(__get_map_header(m), capacity); + __dynamic_map_reserve(__get_map_header(m), capacity) } } @@ -285,20 +285,20 @@ reserve_map :: proc(m: ^$T/map[$K]$V, capacity: int) { @builtin delete_key :: proc(m: ^$T/map[$K]$V, key: K) -> (deleted_key: K, deleted_value: V) { if m != nil { - key := key; - h := __get_map_header(m); - hash := __get_map_hash(&key); - fr := __dynamic_map_find(h, hash); + key := key + h := __get_map_header(m) + hash := __get_map_hash(&key) + fr := __dynamic_map_find(h, hash) if fr.entry_index >= 0 { - entry := __dynamic_map_get_entry(h, fr.entry_index); - deleted_key = (^K)(uintptr(entry)+h.key_offset)^; - deleted_value = (^V)(uintptr(entry)+h.value_offset)^; + entry := __dynamic_map_get_entry(h, fr.entry_index) + deleted_key = (^K)(uintptr(entry)+h.key_offset)^ + deleted_value = (^V)(uintptr(entry)+h.value_offset)^ - __dynamic_map_erase(h, fr); + __dynamic_map_erase(h, fr) } } - return; + return } @@ -306,57 +306,57 @@ delete_key :: proc(m: ^$T/map[$K]$V, key: K) -> (deleted_key: K, deleted_value: @builtin append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) { if array == nil { - return; + return } if cap(array) < len(array)+1 { - cap := 2 * cap(array) + max(8, 1); - _ = reserve(array, cap, loc); + cap := 2 * cap(array) + max(8, 1) + _ = reserve(array, cap, loc) } if cap(array)-len(array) > 0 { - a := (^Raw_Dynamic_Array)(array); + a := (^Raw_Dynamic_Array)(array) when size_of(E) != 0 { - data := ([^]E)(a.data); - assert(condition=data != nil, loc=loc); - data[a.len] = arg; + data := ([^]E)(a.data) + assert(condition=data != nil, loc=loc) + data[a.len] = arg } - a.len += 1; + a.len += 1 } } @builtin append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location) { if array == nil { - return; + return } - arg_len := len(args); + arg_len := len(args) if arg_len <= 0 { - return; + return } if cap(array) < len(array)+arg_len { - cap := 2 * cap(array) + max(8, arg_len); - _ = reserve(array, cap, loc); + cap := 2 * cap(array) + max(8, arg_len) + _ = reserve(array, cap, loc) } - arg_len = min(cap(array)-len(array), arg_len); + arg_len = min(cap(array)-len(array), arg_len) if arg_len > 0 { - a := (^Raw_Dynamic_Array)(array); + a := (^Raw_Dynamic_Array)(array) when size_of(E) != 0 { - data := ([^]E)(a.data); - assert(condition=data != nil, loc=loc); - intrinsics.mem_copy(&data[a.len], raw_data(args), size_of(E) * arg_len); + data := ([^]E)(a.data) + assert(condition=data != nil, loc=loc) + intrinsics.mem_copy(&data[a.len], raw_data(args), size_of(E) * arg_len) } - a.len += arg_len; + a.len += arg_len } } // The append_string built-in procedure appends a string to the end of a [dynamic]u8 like type @builtin append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #caller_location) { - args := transmute([]E)arg; - append_elems(array=array, args=args, loc=loc); + args := transmute([]E)arg + append_elems(array=array, args=args, loc=loc) } @@ -364,86 +364,86 @@ append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #ca @builtin append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_location) { for arg in args { - append(array = array, args = transmute([]E)(arg), loc = loc); + append(array = array, args = transmute([]E)(arg), loc = loc) } } // The append built-in procedure appends elements to the end of a dynamic array -@builtin append :: proc{append_elem, append_elems, append_elem_string}; +@builtin append :: proc{append_elem, append_elems, append_elem_string} @builtin append_nothing :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) { if array == nil { - return; + return } - resize(array, len(array)+1); + resize(array, len(array)+1) } @builtin insert_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, arg: E, loc := #caller_location) -> (ok: bool) #no_bounds_check { if array == nil { - return; + return } - n := len(array); - m :: 1; - resize(array, n+m, loc); + n := len(array) + m :: 1 + resize(array, n+m, loc) if n+m <= len(array) { when size_of(E) != 0 { - copy(array[index+m:], array[index:]); - array[index] = arg; + copy(array[index+m:], array[index:]) + array[index] = arg } - ok = true; + ok = true } - return; + return } @builtin insert_at_elems :: proc(array: ^$T/[dynamic]$E, index: int, args: ..E, loc := #caller_location) -> (ok: bool) #no_bounds_check { if array == nil { - return; + return } if len(args) == 0 { - ok = true; - return; + ok = true + return } - n := len(array); - m := len(args); - resize(array, n+m, loc); + n := len(array) + m := len(args) + resize(array, n+m, loc) if n+m <= len(array) { when size_of(E) != 0 { - copy(array[index+m:], array[index:]); - copy(array[index:], args); + copy(array[index+m:], array[index:]) + copy(array[index:], args) } - ok = true; + ok = true } - return; + return } @builtin insert_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, index: int, arg: string, loc := #caller_location) -> (ok: bool) #no_bounds_check { if array == nil { - return; + return } if len(args) == 0 { - ok = true; - return; + ok = true + return } - n := len(array); - m := len(args); - resize(array, n+m, loc); + n := len(array) + m := len(args) + resize(array, n+m, loc) if n+m <= len(array) { - copy(array[index+m:], array[index:]); - copy(array[index:], args); - ok = true; + copy(array[index+m:], array[index:]) + copy(array[index:], args) + ok = true } - return; + return } -@builtin insert_at :: proc{insert_at_elem, insert_at_elems, insert_at_elem_string}; +@builtin insert_at :: proc{insert_at_elem, insert_at_elems, insert_at_elem_string} @@ -451,134 +451,134 @@ insert_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, index: int, arg: string @builtin clear_dynamic_array :: proc "contextless" (array: ^$T/[dynamic]$E) { if array != nil { - (^Raw_Dynamic_Array)(array).len = 0; + (^Raw_Dynamic_Array)(array).len = 0 } } @builtin reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #caller_location) -> bool { if array == nil { - return false; + return false } - a := (^Raw_Dynamic_Array)(array); + a := (^Raw_Dynamic_Array)(array) if capacity <= a.cap { - return true; + return true } if a.allocator.procedure == nil { - a.allocator = context.allocator; + a.allocator = context.allocator } - assert(a.allocator.procedure != nil); + assert(a.allocator.procedure != nil) - old_size := a.cap * size_of(E); - new_size := capacity * size_of(E); - allocator := a.allocator; + old_size := a.cap * size_of(E) + new_size := capacity * size_of(E) + allocator := a.allocator new_data, err := allocator.procedure( allocator.data, .Resize, new_size, align_of(E), a.data, old_size, loc, - ); + ) if new_data == nil || err != nil { - return false; + return false } - a.data = raw_data(new_data); - a.cap = capacity; - return true; + a.data = raw_data(new_data) + a.cap = capacity + return true } @builtin resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller_location) -> bool { if array == nil { - return false; + return false } - a := (^Raw_Dynamic_Array)(array); + a := (^Raw_Dynamic_Array)(array) if length <= a.cap { - a.len = max(length, 0); - return true; + a.len = max(length, 0) + return true } if a.allocator.procedure == nil { - a.allocator = context.allocator; + a.allocator = context.allocator } - assert(a.allocator.procedure != nil); + assert(a.allocator.procedure != nil) - old_size := a.cap * size_of(E); - new_size := length * size_of(E); - allocator := a.allocator; + old_size := a.cap * size_of(E) + new_size := length * size_of(E) + allocator := a.allocator new_data, err := allocator.procedure( allocator.data, .Resize, new_size, align_of(E), a.data, old_size, loc, - ); + ) if new_data == nil || err != nil { - return false; + return false } - a.data = raw_data(new_data); - a.len = length; - a.cap = length; - return true; + a.data = raw_data(new_data) + a.len = length + a.cap = length + return true } @builtin map_insert :: proc(m: ^$T/map[$K]$V, key: K, value: V, loc := #caller_location) -> (ptr: ^V) { - key, value := key, value; - h := __get_map_header(m); - hash := __get_map_hash(&key); + key, value := key, value + h := __get_map_header(m) + hash := __get_map_hash(&key) - data := uintptr(__dynamic_map_set(h, hash, &value, loc)); - return (^V)(data + h.value_offset); + data := uintptr(__dynamic_map_set(h, hash, &value, loc)) + return (^V)(data + h.value_offset) } @builtin incl_elem :: proc(s: ^$S/bit_set[$E; $U], elem: E) { - s^ |= {elem}; + s^ |= {elem} } @builtin incl_elems :: proc(s: ^$S/bit_set[$E; $U], elems: ..E) { for elem in elems { - s^ |= {elem}; + s^ |= {elem} } } @builtin incl_bit_set :: proc(s: ^$S/bit_set[$E; $U], other: S) { - s^ |= other; + s^ |= other } @builtin excl_elem :: proc(s: ^$S/bit_set[$E; $U], elem: E) { - s^ &~= {elem}; + s^ &~= {elem} } @builtin excl_elems :: proc(s: ^$S/bit_set[$E; $U], elems: ..E) { for elem in elems { - s^ &~= {elem}; + s^ &~= {elem} } } @builtin excl_bit_set :: proc(s: ^$S/bit_set[$E; $U], other: S) { - s^ &~= other; + s^ &~= other } -@builtin incl :: proc{incl_elem, incl_elems, incl_bit_set}; -@builtin excl :: proc{excl_elem, excl_elems, excl_bit_set}; +@builtin incl :: proc{incl_elem, incl_elems, incl_bit_set} +@builtin excl :: proc{excl_elem, excl_elems, excl_bit_set} @builtin card :: proc(s: $S/bit_set[$E; $U]) -> int { when size_of(S) == 1 { - return int(intrinsics.count_ones(transmute(u8)s)); + return int(intrinsics.count_ones(transmute(u8)s)) } else when size_of(S) == 2 { - return int(intrinsics.count_ones(transmute(u16)s)); + return int(intrinsics.count_ones(transmute(u16)s)) } else when size_of(S) == 4 { - return int(intrinsics.count_ones(transmute(u32)s)); + return int(intrinsics.count_ones(transmute(u32)s)) } else when size_of(S) == 8 { - return int(intrinsics.count_ones(transmute(u64)s)); + return int(intrinsics.count_ones(transmute(u64)s)) } else when size_of(S) == 16 { - return int(intrinsics.count_ones(transmute(u128)s)); + return int(intrinsics.count_ones(transmute(u128)s)) } else { #panic("Unhandled card bit_set size"); } @@ -588,25 +588,25 @@ card :: proc(s: $S/bit_set[$E; $U]) -> int { @builtin raw_array_data :: proc "contextless" (a: $P/^($T/[$N]$E)) -> ^E { - return (^E)(a); + return (^E)(a) } @builtin raw_slice_data :: proc "contextless" (s: $S/[]$E) -> ^E { - ptr := (transmute(Raw_Slice)s).data; - return (^E)(ptr); + ptr := (transmute(Raw_Slice)s).data + return (^E)(ptr) } @builtin raw_dynamic_array_data :: proc "contextless" (s: $S/[dynamic]$E) -> ^E { - ptr := (transmute(Raw_Dynamic_Array)s).data; - return (^E)(ptr); + ptr := (transmute(Raw_Dynamic_Array)s).data + return (^E)(ptr) } @builtin raw_string_data :: proc "contextless" (s: $S/string) -> ^u8 { - return (transmute(Raw_String)s).data; + return (transmute(Raw_String)s).data } @builtin -raw_data :: proc{raw_array_data, raw_slice_data, raw_dynamic_array_data, raw_string_data}; +raw_data :: proc{raw_array_data, raw_slice_data, raw_dynamic_array_data, raw_string_data} @@ -615,45 +615,45 @@ raw_data :: proc{raw_array_data, raw_slice_data, raw_dynamic_array_data, raw_str assert :: proc(condition: bool, message := "", loc := #caller_location) { if !condition { proc(message: string, loc: Source_Code_Location) { - p := context.assertion_failure_proc; + p := context.assertion_failure_proc if p == nil { - p = default_assertion_failure_proc; + p = default_assertion_failure_proc } - p("runtime assertion", message, loc); - }(message, loc); + p("runtime assertion", message, loc) + }(message, loc) } } @builtin @(disabled=ODIN_DISABLE_ASSERT) panic :: proc(message: string, loc := #caller_location) -> ! { - p := context.assertion_failure_proc; + p := context.assertion_failure_proc if p == nil { - p = default_assertion_failure_proc; + p = default_assertion_failure_proc } - p("panic", message, loc); + p("panic", message, loc) } @builtin @(disabled=ODIN_DISABLE_ASSERT) unimplemented :: proc(message := "", loc := #caller_location) -> ! { - p := context.assertion_failure_proc; + p := context.assertion_failure_proc if p == nil { - p = default_assertion_failure_proc; + p = default_assertion_failure_proc } - p("not yet implemented", message, loc); + p("not yet implemented", message, loc) } @builtin @(disabled=ODIN_DISABLE_ASSERT) unreachable :: proc(message := "", loc := #caller_location) -> ! { - p := context.assertion_failure_proc; + p := context.assertion_failure_proc if p == nil { - p = default_assertion_failure_proc; + p = default_assertion_failure_proc } if message != "" { - p("internal error", message, loc); + p("internal error", message, loc) } else { - p("internal error", "entered unreachable code", loc); + p("internal error", "entered unreachable code", loc) } } diff --git a/core/runtime/core_builtin_soa.odin b/core/runtime/core_builtin_soa.odin index 3fbbde161..6b6e78e5e 100644 --- a/core/runtime/core_builtin_soa.odin +++ b/core/runtime/core_builtin_soa.odin @@ -1,7 +1,7 @@ package runtime import "core:intrinsics" -_ :: intrinsics; +_ :: intrinsics /* @@ -52,112 +52,112 @@ Raw_SOA_Footer_Dynamic_Array :: struct { raw_soa_footer_slice :: proc(array: ^$T/#soa[]$E) -> (footer: ^Raw_SOA_Footer_Slice) { if array == nil { - return nil; + return nil } - field_count := uintptr(intrinsics.type_struct_field_count(E)); - footer = (^Raw_SOA_Footer_Slice)(uintptr(array) + field_count*size_of(rawptr)); - return; + field_count := uintptr(intrinsics.type_struct_field_count(E)) + footer = (^Raw_SOA_Footer_Slice)(uintptr(array) + field_count*size_of(rawptr)) + return } raw_soa_footer_dynamic_array :: proc(array: ^$T/#soa[dynamic]$E) -> (footer: ^Raw_SOA_Footer_Dynamic_Array) { if array == nil { - return nil; + return nil } - field_count := uintptr(intrinsics.type_struct_field_count(E)); - footer = (^Raw_SOA_Footer_Dynamic_Array)(uintptr(array) + field_count*size_of(rawptr)); - return; + field_count := uintptr(intrinsics.type_struct_field_count(E)) + footer = (^Raw_SOA_Footer_Dynamic_Array)(uintptr(array) + field_count*size_of(rawptr)) + return } raw_soa_footer :: proc{ raw_soa_footer_slice, raw_soa_footer_dynamic_array, -}; +} @builtin make_soa_aligned :: proc($T: typeid/#soa[]$E, length: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_second { if length <= 0 { - return; + return } - footer := raw_soa_footer(&array); + footer := raw_soa_footer(&array) if size_of(E) == 0 { - footer.len = length; - return; + footer.len = length + return } - max_align := max(alignment, align_of(E)); + max_align := max(alignment, align_of(E)) - ti := type_info_of(typeid_of(T)); - ti = type_info_base(ti); - si := &ti.variant.(Type_Info_Struct); + ti := type_info_of(typeid_of(T)) + ti = type_info_base(ti) + si := &ti.variant.(Type_Info_Struct) - field_count := uintptr(intrinsics.type_struct_field_count(E)); + field_count := uintptr(intrinsics.type_struct_field_count(E)) - total_size := 0; + total_size := 0 for i in 0..<field_count { - type := si.types[i].variant.(Type_Info_Pointer).elem; - total_size += type.size * length; - total_size = align_forward_int(total_size, max_align); + type := si.types[i].variant.(Type_Info_Pointer).elem + total_size += type.size * length + total_size = align_forward_int(total_size, max_align) } - allocator := allocator; + allocator := allocator if allocator.procedure == nil { - allocator = context.allocator; + allocator = context.allocator } - assert(allocator.procedure != nil); + assert(allocator.procedure != nil) - new_bytes: []byte; + new_bytes: []byte new_bytes, err = allocator.procedure( allocator.data, .Alloc, total_size, max_align, nil, 0, loc, - ); + ) if new_bytes == nil || err != nil { - return; + return } - new_data := raw_data(new_bytes); + new_data := raw_data(new_bytes) - data := uintptr(&array); - offset := 0; + data := uintptr(&array) + offset := 0 for i in 0..<field_count { - type := si.types[i].variant.(Type_Info_Pointer).elem; + type := si.types[i].variant.(Type_Info_Pointer).elem - offset = align_forward_int(offset, max_align); + offset = align_forward_int(offset, max_align) - (^uintptr)(data)^ = uintptr(new_data) + uintptr(offset); - data += size_of(rawptr); - offset += type.size * length; + (^uintptr)(data)^ = uintptr(new_data) + uintptr(offset) + data += size_of(rawptr) + offset += type.size * length } - footer.len = length; + footer.len = length - return; + return } @builtin make_soa_slice :: proc($T: typeid/#soa[]$E, length: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_second { - return make_soa_aligned(T, length, align_of(E), allocator, loc); + return make_soa_aligned(T, length, align_of(E), allocator, loc) } @builtin make_soa_dynamic_array :: proc($T: typeid/#soa[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (array: T) { - context.allocator = allocator; - reserve_soa(&array, DEFAULT_RESERVE_CAPACITY, loc); - return; + context.allocator = allocator + reserve_soa(&array, DEFAULT_RESERVE_CAPACITY, loc) + return } @builtin make_soa_dynamic_array_len :: proc($T: typeid/#soa[dynamic]$E, auto_cast length: int, allocator := context.allocator, loc := #caller_location) -> (array: T) { - context.allocator = allocator; - resize_soa(&array, length, loc); - return; + context.allocator = allocator + resize_soa(&array, length, loc) + return } @builtin make_soa_dynamic_array_len_cap :: proc($T: typeid/#soa[dynamic]$E, auto_cast length, capacity: int, allocator := context.allocator, loc := #caller_location) -> (array: T) { - context.allocator = allocator; + context.allocator = allocator if reserve_soa(&array, capacity, loc) { - resize_soa(&array, length, loc); + resize_soa(&array, length, loc) } - return; + return } @@ -167,206 +167,206 @@ make_soa :: proc{ make_soa_dynamic_array, make_soa_dynamic_array_len, make_soa_dynamic_array_len_cap, -}; +} @builtin resize_soa :: proc(array: ^$T/#soa[dynamic]$E, length: int, loc := #caller_location) -> bool { if array == nil { - return false; + return false } if !reserve_soa(array, length, loc) { - return false; + return false } - footer := raw_soa_footer(array); - footer.len = length; - return true; + footer := raw_soa_footer(array) + footer.len = length + return true } @builtin reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_location) -> bool { if array == nil { - return false; + return false } - old_cap := cap(array); + old_cap := cap(array) if capacity <= old_cap { - return true; + return true } if array.allocator.procedure == nil { - array.allocator = context.allocator; + array.allocator = context.allocator } - assert(array.allocator.procedure != nil); + assert(array.allocator.procedure != nil) - footer := raw_soa_footer(array); + footer := raw_soa_footer(array) if size_of(E) == 0 { - footer.cap = capacity; - return true; + footer.cap = capacity + return true } - ti := type_info_of(typeid_of(T)); - ti = type_info_base(ti); - si := &ti.variant.(Type_Info_Struct); + ti := type_info_of(typeid_of(T)) + ti = type_info_base(ti) + si := &ti.variant.(Type_Info_Struct) - field_count := uintptr(intrinsics.type_struct_field_count(E)); - assert(footer.cap == old_cap); + field_count := uintptr(intrinsics.type_struct_field_count(E)) + assert(footer.cap == old_cap) - old_size := 0; - new_size := 0; + old_size := 0 + new_size := 0 - max_align :: align_of(E); + max_align :: align_of(E) for i in 0..<field_count { - type := si.types[i].variant.(Type_Info_Pointer).elem; + type := si.types[i].variant.(Type_Info_Pointer).elem - old_size += type.size * old_cap; - new_size += type.size * capacity; + old_size += type.size * old_cap + new_size += type.size * capacity - old_size = align_forward_int(old_size, max_align); - new_size = align_forward_int(new_size, max_align); + old_size = align_forward_int(old_size, max_align) + new_size = align_forward_int(new_size, max_align) } - old_data := (^rawptr)(array)^; + old_data := (^rawptr)(array)^ new_bytes, err := array.allocator.procedure( array.allocator.data, .Alloc, new_size, max_align, nil, old_size, loc, - ); + ) if new_bytes == nil || err != nil { - return false; + return false } - new_data := raw_data(new_bytes); + new_data := raw_data(new_bytes) - footer.cap = capacity; + footer.cap = capacity - old_offset := 0; - new_offset := 0; + old_offset := 0 + new_offset := 0 for i in 0..<field_count { - type := si.types[i].variant.(Type_Info_Pointer).elem; + type := si.types[i].variant.(Type_Info_Pointer).elem - old_offset = align_forward_int(old_offset, max_align); - new_offset = align_forward_int(new_offset, max_align); + old_offset = align_forward_int(old_offset, max_align) + new_offset = align_forward_int(new_offset, max_align) - new_data_elem := rawptr(uintptr(new_data) + uintptr(new_offset)); - old_data_elem := rawptr(uintptr(old_data) + uintptr(old_offset)); + new_data_elem := rawptr(uintptr(new_data) + uintptr(new_offset)) + old_data_elem := rawptr(uintptr(old_data) + uintptr(old_offset)) - mem_copy(new_data_elem, old_data_elem, type.size * old_cap); + mem_copy(new_data_elem, old_data_elem, type.size * old_cap) - (^rawptr)(uintptr(array) + i*size_of(rawptr))^ = new_data_elem; + (^rawptr)(uintptr(array) + i*size_of(rawptr))^ = new_data_elem - old_offset += type.size * old_cap; - new_offset += type.size * capacity; + old_offset += type.size * old_cap + new_offset += type.size * capacity } _, err = array.allocator.procedure( array.allocator.data, .Free, 0, max_align, old_data, old_size, loc, - ); + ) - return true; + return true } @builtin append_soa_elem :: proc(array: ^$T/#soa[dynamic]$E, arg: E, loc := #caller_location) { if array == nil { - return; + return } - arg_len := 1; + arg_len := 1 if cap(array) <= len(array)+arg_len { - cap := 2 * cap(array) + max(8, arg_len); - _ = reserve_soa(array, cap, loc); + cap := 2 * cap(array) + max(8, arg_len) + _ = reserve_soa(array, cap, loc) } - arg_len = min(cap(array)-len(array), arg_len); + arg_len = min(cap(array)-len(array), arg_len) - footer := raw_soa_footer(array); + footer := raw_soa_footer(array) if size_of(E) > 0 && arg_len > 0 { - ti := type_info_of(typeid_of(T)); - ti = type_info_base(ti); - si := &ti.variant.(Type_Info_Struct); - field_count := uintptr(intrinsics.type_struct_field_count(E)); + ti := type_info_of(typeid_of(T)) + ti = type_info_base(ti) + si := &ti.variant.(Type_Info_Struct) + field_count := uintptr(intrinsics.type_struct_field_count(E)) - data := (^rawptr)(array)^; + data := (^rawptr)(array)^ - soa_offset := 0; - item_offset := 0; + soa_offset := 0 + item_offset := 0 - arg_copy := arg; - arg_ptr := &arg_copy; + arg_copy := arg + arg_ptr := &arg_copy - max_align :: align_of(E); + max_align :: align_of(E) for i in 0..<field_count { - type := si.types[i].variant.(Type_Info_Pointer).elem; + type := si.types[i].variant.(Type_Info_Pointer).elem - soa_offset = align_forward_int(soa_offset, max_align); - item_offset = align_forward_int(item_offset, type.align); + soa_offset = align_forward_int(soa_offset, max_align) + item_offset = align_forward_int(item_offset, type.align) - dst := rawptr(uintptr(data) + uintptr(soa_offset) + uintptr(type.size * footer.len)); - src := rawptr(uintptr(arg_ptr) + uintptr(item_offset)); - mem_copy(dst, src, type.size); + dst := rawptr(uintptr(data) + uintptr(soa_offset) + uintptr(type.size * footer.len)) + src := rawptr(uintptr(arg_ptr) + uintptr(item_offset)) + mem_copy(dst, src, type.size) - soa_offset += type.size * cap(array); - item_offset += type.size; + soa_offset += type.size * cap(array) + item_offset += type.size } } - footer.len += arg_len; + footer.len += arg_len } @builtin append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, args: ..E, loc := #caller_location) { if array == nil { - return; + return } - arg_len := len(args); + arg_len := len(args) if arg_len == 0 { - return; + return } if cap(array) <= len(array)+arg_len { - cap := 2 * cap(array) + max(8, arg_len); - _ = reserve_soa(array, cap, loc); + cap := 2 * cap(array) + max(8, arg_len) + _ = reserve_soa(array, cap, loc) } - arg_len = min(cap(array)-len(array), arg_len); + arg_len = min(cap(array)-len(array), arg_len) - footer := raw_soa_footer(array); + footer := raw_soa_footer(array) if size_of(E) > 0 && arg_len > 0 { - ti := type_info_of(typeid_of(T)); - ti = type_info_base(ti); - si := &ti.variant.(Type_Info_Struct); - field_count := uintptr(intrinsics.type_struct_field_count(E)); + ti := type_info_of(typeid_of(T)) + ti = type_info_base(ti) + si := &ti.variant.(Type_Info_Struct) + field_count := uintptr(intrinsics.type_struct_field_count(E)) - data := (^rawptr)(array)^; + data := (^rawptr)(array)^ - soa_offset := 0; - item_offset := 0; + soa_offset := 0 + item_offset := 0 - args_ptr := &args[0]; + args_ptr := &args[0] - max_align :: align_of(E); + max_align :: align_of(E) for i in 0..<field_count { - type := si.types[i].variant.(Type_Info_Pointer).elem; + type := si.types[i].variant.(Type_Info_Pointer).elem - soa_offset = align_forward_int(soa_offset, max_align); - item_offset = align_forward_int(item_offset, type.align); + soa_offset = align_forward_int(soa_offset, max_align) + item_offset = align_forward_int(item_offset, type.align) - dst := uintptr(data) + uintptr(soa_offset) + uintptr(type.size * footer.len); - src := uintptr(args_ptr) + uintptr(item_offset); + dst := uintptr(data) + uintptr(soa_offset) + uintptr(type.size * footer.len) + src := uintptr(args_ptr) + uintptr(item_offset) for j in 0..<arg_len { - d := rawptr(dst + uintptr(j*type.size)); - s := rawptr(src + uintptr(j*size_of(E))); - mem_copy(d, s, type.size); + d := rawptr(dst + uintptr(j*type.size)) + s := rawptr(src + uintptr(j*size_of(E))) + mem_copy(d, s, type.size) } - soa_offset += type.size * cap(array); - item_offset += type.size; + soa_offset += type.size * cap(array) + item_offset += type.size } } - footer.len += arg_len; + footer.len += arg_len } @@ -375,23 +375,23 @@ append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, args: ..E, loc := #caller_l append_soa :: proc{ append_soa_elem, append_soa_elems, -}; +} delete_soa_slice :: proc(array: $T/#soa[]$E, allocator := context.allocator, loc := #caller_location) { when intrinsics.type_struct_field_count(E) != 0 { - array := array; - ptr := (^rawptr)(&array)^; - free(ptr, allocator, loc); + array := array + ptr := (^rawptr)(&array)^ + free(ptr, allocator, loc) } } delete_soa_dynamic_array :: proc(array: $T/#soa[dynamic]$E, loc := #caller_location) { when intrinsics.type_struct_field_count(E) != 0 { - array := array; - ptr := (^rawptr)(&array)^; - footer := raw_soa_footer(&array); - free(ptr, footer.allocator, loc); + array := array + ptr := (^rawptr)(&array)^ + footer := raw_soa_footer(&array) + free(ptr, footer.allocator, loc) } } @@ -400,4 +400,4 @@ delete_soa_dynamic_array :: proc(array: $T/#soa[dynamic]$E, loc := #caller_locat delete_soa :: proc{ delete_soa_slice, delete_soa_dynamic_array, -}; +} diff --git a/core/runtime/default_allocators_windows.odin b/core/runtime/default_allocators_windows.odin index 15c74ab19..f57f4c86c 100644 --- a/core/runtime/default_allocators_windows.odin +++ b/core/runtime/default_allocators_windows.odin @@ -6,33 +6,33 @@ default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, old_memory: rawptr, old_size: int, loc := #caller_location) -> (data: []byte, err: Allocator_Error) { switch mode { case .Alloc: - data, err = _windows_default_alloc(size, alignment); + data, err = _windows_default_alloc(size, alignment) case .Free: - _windows_default_free(old_memory); + _windows_default_free(old_memory) case .Free_All: // NOTE(tetra): Do nothing. case .Resize: - data, err = _windows_default_resize(old_memory, old_size, size, alignment); + data, err = _windows_default_resize(old_memory, old_size, size, alignment) case .Query_Features: - set := (^Allocator_Mode_Set)(old_memory); + set := (^Allocator_Mode_Set)(old_memory) if set != nil { - set^ = {.Alloc, .Free, .Resize, .Query_Features}; + set^ = {.Alloc, .Free, .Resize, .Query_Features} } case .Query_Info: // Do nothing } - return; + return } default_allocator :: proc() -> Allocator { return Allocator{ procedure = default_allocator_proc, data = nil, - }; + } } diff --git a/core/runtime/default_temporary_allocator.odin b/core/runtime/default_temporary_allocator.odin index ea545f26b..216ed99ff 100644 --- a/core/runtime/default_temporary_allocator.odin +++ b/core/runtime/default_temporary_allocator.odin @@ -2,11 +2,11 @@ package runtime @(private) byte_slice :: #force_inline proc "contextless" (data: rawptr, len: int) -> []byte { - return transmute([]u8)Raw_Slice{data=data, len=max(len, 0)}; + return transmute([]u8)Raw_Slice{data=data, len=max(len, 0)} } -DEFAULT_TEMP_ALLOCATOR_BACKING_SIZE: int : #config(DEFAULT_TEMP_ALLOCATOR_BACKING_SIZE, 1<<22); +DEFAULT_TEMP_ALLOCATOR_BACKING_SIZE: int : #config(DEFAULT_TEMP_ALLOCATOR_BACKING_SIZE, 1<<22) Default_Temp_Allocator :: struct { @@ -18,179 +18,179 @@ Default_Temp_Allocator :: struct { } default_temp_allocator_init :: proc(s: ^Default_Temp_Allocator, size: int, backup_allocator := context.allocator) { - s.data = make_aligned([]byte, size, 2*align_of(rawptr), backup_allocator); - s.curr_offset = 0; - s.prev_allocation = nil; - s.backup_allocator = backup_allocator; - s.leaked_allocations.allocator = backup_allocator; + s.data = make_aligned([]byte, size, 2*align_of(rawptr), backup_allocator) + s.curr_offset = 0 + s.prev_allocation = nil + s.backup_allocator = backup_allocator + s.leaked_allocations.allocator = backup_allocator } default_temp_allocator_destroy :: proc(s: ^Default_Temp_Allocator) { if s == nil { - return; + return } for ptr in s.leaked_allocations { - free(raw_data(ptr), s.backup_allocator); + free(raw_data(ptr), s.backup_allocator) } - delete(s.leaked_allocations); - delete(s.data, s.backup_allocator); - s^ = {}; + delete(s.leaked_allocations) + delete(s.data, s.backup_allocator) + s^ = {} } @(private) default_temp_allocator_alloc :: proc(s: ^Default_Temp_Allocator, size, alignment: int, loc := #caller_location) -> ([]byte, Allocator_Error) { - size := size; - size = align_forward_int(size, alignment); + size := size + size = align_forward_int(size, alignment) switch { case s.curr_offset+size <= len(s.data): - start := uintptr(raw_data(s.data)); - ptr := start + uintptr(s.curr_offset); - ptr = align_forward_uintptr(ptr, uintptr(alignment)); - mem_zero(rawptr(ptr), size); + start := uintptr(raw_data(s.data)) + ptr := start + uintptr(s.curr_offset) + ptr = align_forward_uintptr(ptr, uintptr(alignment)) + mem_zero(rawptr(ptr), size) - s.prev_allocation = rawptr(ptr); - offset := int(ptr - start); - s.curr_offset = offset + size; - return byte_slice(rawptr(ptr), size), .None; + s.prev_allocation = rawptr(ptr) + offset := int(ptr - start) + s.curr_offset = offset + size + return byte_slice(rawptr(ptr), size), .None case size <= len(s.data): - start := uintptr(raw_data(s.data)); - ptr := align_forward_uintptr(start, uintptr(alignment)); - mem_zero(rawptr(ptr), size); + start := uintptr(raw_data(s.data)) + ptr := align_forward_uintptr(start, uintptr(alignment)) + mem_zero(rawptr(ptr), size) - s.prev_allocation = rawptr(ptr); - offset := int(ptr - start); - s.curr_offset = offset + size; - return byte_slice(rawptr(ptr), size), .None; + s.prev_allocation = rawptr(ptr) + offset := int(ptr - start) + s.curr_offset = offset + size + return byte_slice(rawptr(ptr), size), .None } - a := s.backup_allocator; + a := s.backup_allocator if a.procedure == nil { - a = context.allocator; - s.backup_allocator = a; + a = context.allocator + s.backup_allocator = a } - data, err := mem_alloc_bytes(size, alignment, a, loc); + data, err := mem_alloc_bytes(size, alignment, a, loc) if err != nil { - return data, err; + return data, err } if s.leaked_allocations == nil { - s.leaked_allocations = make([dynamic][]byte, a); + s.leaked_allocations = make([dynamic][]byte, a) } - append(&s.leaked_allocations, data); + append(&s.leaked_allocations, data) // TODO(bill): Should leaks be notified about? if logger := context.logger; logger.lowest_level <= .Warning { if logger.procedure != nil { - logger.procedure(logger.data, .Warning, "default temp allocator resorted to backup_allocator" , logger.options, loc); + logger.procedure(logger.data, .Warning, "default temp allocator resorted to backup_allocator" , logger.options, loc) } } - return data, .None; + return data, .None } @(private) default_temp_allocator_free :: proc(s: ^Default_Temp_Allocator, old_memory: rawptr, loc := #caller_location) -> Allocator_Error { if old_memory == nil { - return .None; + return .None } - start := uintptr(raw_data(s.data)); - end := start + uintptr(len(s.data)); - old_ptr := uintptr(old_memory); + start := uintptr(raw_data(s.data)) + end := start + uintptr(len(s.data)) + old_ptr := uintptr(old_memory) if s.prev_allocation == old_memory { - s.curr_offset = int(uintptr(s.prev_allocation) - start); - s.prev_allocation = nil; - return .None; + s.curr_offset = int(uintptr(s.prev_allocation) - start) + s.prev_allocation = nil + return .None } if start <= old_ptr && old_ptr < end { // NOTE(bill): Cannot free this pointer but it is valid - return .None; + return .None } if len(s.leaked_allocations) != 0 { for data, i in s.leaked_allocations { - ptr := raw_data(data); + ptr := raw_data(data) if ptr == old_memory { - free(ptr, s.backup_allocator); - ordered_remove(&s.leaked_allocations, i); - return .None; + free(ptr, s.backup_allocator) + ordered_remove(&s.leaked_allocations, i) + return .None } } } - return .Invalid_Pointer; + return .Invalid_Pointer // panic("invalid pointer passed to default_temp_allocator"); } @(private) default_temp_allocator_free_all :: proc(s: ^Default_Temp_Allocator, loc := #caller_location) { - s.curr_offset = 0; - s.prev_allocation = nil; + s.curr_offset = 0 + s.prev_allocation = nil for data in s.leaked_allocations { - free(raw_data(data), s.backup_allocator); + free(raw_data(data), s.backup_allocator) } - clear(&s.leaked_allocations); + clear(&s.leaked_allocations) } @(private) default_temp_allocator_resize :: proc(s: ^Default_Temp_Allocator, old_memory: rawptr, old_size, size, alignment: int, loc := #caller_location) -> ([]byte, Allocator_Error) { - begin := uintptr(raw_data(s.data)); - end := begin + uintptr(len(s.data)); - old_ptr := uintptr(old_memory); + begin := uintptr(raw_data(s.data)) + end := begin + uintptr(len(s.data)) + old_ptr := uintptr(old_memory) if old_memory == s.prev_allocation && old_ptr & uintptr(alignment)-1 == 0 { if old_ptr+uintptr(size) < end { - s.curr_offset = int(old_ptr-begin)+size; - return byte_slice(old_memory, size), .None; + s.curr_offset = int(old_ptr-begin)+size + return byte_slice(old_memory, size), .None } } - data, err := default_temp_allocator_alloc(s, size, alignment, loc); + data, err := default_temp_allocator_alloc(s, size, alignment, loc) if err == .None { - copy(data, byte_slice(old_memory, old_size)); - err = default_temp_allocator_free(s, old_memory, loc); + copy(data, byte_slice(old_memory, old_size)) + err = default_temp_allocator_free(s, old_memory, loc) } - return data, err; + return data, err } default_temp_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, loc := #caller_location) -> (data: []byte, err: Allocator_Error) { - s := (^Default_Temp_Allocator)(allocator_data); + s := (^Default_Temp_Allocator)(allocator_data) if s.data == nil { - default_temp_allocator_init(s, DEFAULT_TEMP_ALLOCATOR_BACKING_SIZE, default_allocator()); + default_temp_allocator_init(s, DEFAULT_TEMP_ALLOCATOR_BACKING_SIZE, default_allocator()) } switch mode { case .Alloc: - data, err = default_temp_allocator_alloc(s, size, alignment, loc); + data, err = default_temp_allocator_alloc(s, size, alignment, loc) case .Free: - err = default_temp_allocator_free(s, old_memory, loc); + err = default_temp_allocator_free(s, old_memory, loc) case .Free_All: - default_temp_allocator_free_all(s, loc); + default_temp_allocator_free_all(s, loc) case .Resize: - data, err = default_temp_allocator_resize(s, old_memory, old_size, size, alignment, loc); + data, err = default_temp_allocator_resize(s, old_memory, old_size, size, alignment, loc) case .Query_Features: - set := (^Allocator_Mode_Set)(old_memory); + set := (^Allocator_Mode_Set)(old_memory) if set != nil { - set^ = {.Alloc, .Free, .Free_All, .Resize, .Query_Features}; + set^ = {.Alloc, .Free, .Free_All, .Resize, .Query_Features} } case .Query_Info: // Nothing to give } - return; + return } default_temp_allocator :: proc(allocator: ^Default_Temp_Allocator) -> Allocator { return Allocator{ procedure = default_temp_allocator_proc, data = allocator, - }; + } } diff --git a/core/runtime/dynamic_array_internal.odin b/core/runtime/dynamic_array_internal.odin index 340f3be5e..6f800de7a 100644 --- a/core/runtime/dynamic_array_internal.odin +++ b/core/runtime/dynamic_array_internal.odin @@ -1,103 +1,103 @@ package runtime __dynamic_array_make :: proc(array_: rawptr, elem_size, elem_align: int, len, cap: int, loc := #caller_location) { - array := (^Raw_Dynamic_Array)(array_); - array.allocator = context.allocator; - assert(array.allocator.procedure != nil); + array := (^Raw_Dynamic_Array)(array_) + array.allocator = context.allocator + assert(array.allocator.procedure != nil) if cap > 0 { - __dynamic_array_reserve(array_, elem_size, elem_align, cap, loc); - array.len = len; + __dynamic_array_reserve(array_, elem_size, elem_align, cap, loc) + array.len = len } } __dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, cap: int, loc := #caller_location) -> bool { - array := (^Raw_Dynamic_Array)(array_); + array := (^Raw_Dynamic_Array)(array_) // NOTE(tetra, 2020-01-26): We set the allocator before earlying-out below, because user code is usually written // assuming that appending/reserving will set the allocator, if it is not already set. if array.allocator.procedure == nil { - array.allocator = context.allocator; + array.allocator = context.allocator } - assert(array.allocator.procedure != nil); + assert(array.allocator.procedure != nil) if cap <= array.cap { - return true; + return true } - old_size := array.cap * elem_size; - new_size := cap * elem_size; - allocator := array.allocator; + old_size := array.cap * elem_size + new_size := cap * elem_size + allocator := array.allocator - new_data, err := allocator.procedure(allocator.data, .Resize, new_size, elem_align, array.data, old_size, loc); + new_data, err := allocator.procedure(allocator.data, .Resize, new_size, elem_align, array.data, old_size, loc) if err != nil { - return false; + return false } if new_data != nil || elem_size == 0 { - array.data = raw_data(new_data); - array.cap = min(cap, len(new_data)/elem_size); - return true; + array.data = raw_data(new_data) + array.cap = min(cap, len(new_data)/elem_size) + return true } - return false; + return false } __dynamic_array_resize :: proc(array_: rawptr, elem_size, elem_align: int, len: int, loc := #caller_location) -> bool { - array := (^Raw_Dynamic_Array)(array_); + array := (^Raw_Dynamic_Array)(array_) - ok := __dynamic_array_reserve(array_, elem_size, elem_align, len, loc); + ok := __dynamic_array_reserve(array_, elem_size, elem_align, len, loc) if ok { - array.len = len; + array.len = len } - return ok; + return ok } __dynamic_array_append :: proc(array_: rawptr, elem_size, elem_align: int, items: rawptr, item_count: int, loc := #caller_location) -> int { - array := (^Raw_Dynamic_Array)(array_); + array := (^Raw_Dynamic_Array)(array_) if items == nil { - return 0; + return 0 } if item_count <= 0 { - return 0; + return 0 } - ok := true; + ok := true if array.cap <= array.len+item_count { - cap := 2 * array.cap + max(8, item_count); - ok = __dynamic_array_reserve(array, elem_size, elem_align, cap, loc); + cap := 2 * array.cap + max(8, item_count) + ok = __dynamic_array_reserve(array, elem_size, elem_align, cap, loc) } // TODO(bill): Better error handling for failed reservation if !ok { - return array.len; + return array.len } - assert(array.data != nil); - data := uintptr(array.data) + uintptr(elem_size*array.len); + assert(array.data != nil) + data := uintptr(array.data) + uintptr(elem_size*array.len) - mem_copy(rawptr(data), items, elem_size * item_count); - array.len += item_count; - return array.len; + mem_copy(rawptr(data), items, elem_size * item_count) + array.len += item_count + return array.len } __dynamic_array_append_nothing :: proc(array_: rawptr, elem_size, elem_align: int, loc := #caller_location) -> int { - array := (^Raw_Dynamic_Array)(array_); + array := (^Raw_Dynamic_Array)(array_) - ok := true; + ok := true if array.cap <= array.len+1 { - cap := 2 * array.cap + max(8, 1); - ok = __dynamic_array_reserve(array, elem_size, elem_align, cap, loc); + cap := 2 * array.cap + max(8, 1) + ok = __dynamic_array_reserve(array, elem_size, elem_align, cap, loc) } // TODO(bill): Better error handling for failed reservation if !ok { - return array.len; + return array.len } - assert(array.data != nil); - data := uintptr(array.data) + uintptr(elem_size*array.len); - mem_zero(rawptr(data), elem_size); - array.len += 1; - return array.len; + assert(array.data != nil) + data := uintptr(array.data) + uintptr(elem_size*array.len) + mem_zero(rawptr(data), elem_size) + array.len += 1 + return array.len } diff --git a/core/runtime/dynamic_map_internal.odin b/core/runtime/dynamic_map_internal.odin index 6e54ba441..9d8604bc0 100644 --- a/core/runtime/dynamic_map_internal.odin +++ b/core/runtime/dynamic_map_internal.odin @@ -1,9 +1,9 @@ package runtime import "core:intrinsics" -_ :: intrinsics; +_ :: intrinsics -INITIAL_MAP_CAP :: 16; +INITIAL_MAP_CAP :: 16 // Temporary data structure for comparing hashes and keys Map_Hash :: struct { @@ -12,16 +12,16 @@ Map_Hash :: struct { } __get_map_hash :: proc "contextless" (k: ^$K) -> (map_hash: Map_Hash) { - hasher := intrinsics.type_hasher_proc(K); - map_hash.key_ptr = k; - map_hash.hash = hasher(k, 0); - return; + hasher := intrinsics.type_hasher_proc(K) + map_hash.key_ptr = k + map_hash.hash = hasher(k, 0) + return } __get_map_hash_from_entry :: proc "contextless" (h: Map_Header, entry: ^Map_Entry_Header) -> (hash: Map_Hash) { - hash.hash = entry.hash; - hash.key_ptr = rawptr(uintptr(entry) + h.key_offset); - return; + hash.hash = entry.hash + hash.key_ptr = rawptr(uintptr(entry) + h.key_offset) + return } @@ -55,48 +55,48 @@ Map_Header :: struct { value_size: int, } -INITIAL_HASH_SEED :: 0xcbf29ce484222325; +INITIAL_HASH_SEED :: 0xcbf29ce484222325 _fnv64a :: proc "contextless" (data: []byte, seed: u64 = INITIAL_HASH_SEED) -> u64 { - h: u64 = seed; + h: u64 = seed for b in data { - h = (h ~ u64(b)) * 0x100000001b3; + h = (h ~ u64(b)) * 0x100000001b3 } - return h; + return h } default_hash :: #force_inline proc "contextless" (data: []byte) -> uintptr { - return uintptr(_fnv64a(data)); + return uintptr(_fnv64a(data)) } default_hash_string :: #force_inline proc "contextless" (s: string) -> uintptr { - return default_hash(transmute([]byte)(s)); + return default_hash(transmute([]byte)(s)) } default_hash_ptr :: #force_inline proc "contextless" (data: rawptr, size: int) -> uintptr { - s := Raw_Slice{data, size}; - return default_hash(transmute([]byte)(s)); + s := Raw_Slice{data, size} + return default_hash(transmute([]byte)(s)) } @(private) _default_hasher_const :: #force_inline proc "contextless" (data: rawptr, seed: uintptr, $N: uint) -> uintptr where N <= 16 { - h := u64(seed) + 0xcbf29ce484222325; - p := uintptr(data); + h := u64(seed) + 0xcbf29ce484222325 + p := uintptr(data) #unroll for _ in 0..<N { - b := u64((^byte)(p)^); - h = (h ~ b) * 0x100000001b3; - p += 1; + b := u64((^byte)(p)^) + h = (h ~ b) * 0x100000001b3 + p += 1 } - return uintptr(h); + return uintptr(h) } default_hasher_n :: #force_inline proc "contextless" (data: rawptr, seed: uintptr, N: int) -> uintptr { - h := u64(seed) + 0xcbf29ce484222325; - p := uintptr(data); + h := u64(seed) + 0xcbf29ce484222325 + p := uintptr(data) for _ in 0..<N { - b := u64((^byte)(p)^); - h = (h ~ b) * 0x100000001b3; - p += 1; + b := u64((^byte)(p)^) + h = (h ~ b) * 0x100000001b3 + p += 1 } - return uintptr(h); + return uintptr(h) } // NOTE(bill): There are loads of predefined ones to improve optimizations for small types @@ -119,270 +119,270 @@ default_hasher15 :: proc "contextless" (data: rawptr, seed: uintptr) -> uintptr default_hasher16 :: proc "contextless" (data: rawptr, seed: uintptr) -> uintptr { return #force_inline _default_hasher_const(data, seed, 16); } default_hasher_string :: proc "contextless" (data: rawptr, seed: uintptr) -> uintptr { - h := u64(seed) + 0xcbf29ce484222325; - str := (^[]byte)(data)^; + h := u64(seed) + 0xcbf29ce484222325 + str := (^[]byte)(data)^ for b in str { - h = (h ~ u64(b)) * 0x100000001b3; + h = (h ~ u64(b)) * 0x100000001b3 } - return uintptr(h); + return uintptr(h) } default_hasher_cstring :: proc "contextless" (data: rawptr, seed: uintptr) -> uintptr { - h := u64(seed) + 0xcbf29ce484222325; - ptr := (^uintptr)(data)^; + h := u64(seed) + 0xcbf29ce484222325 + ptr := (^uintptr)(data)^ for (^byte)(ptr)^ != 0 { - b := (^byte)(ptr)^; - h = (h ~ u64(b)) * 0x100000001b3; - ptr += 1; + b := (^byte)(ptr)^ + h = (h ~ u64(b)) * 0x100000001b3 + ptr += 1 } - return uintptr(h); + return uintptr(h) } __get_map_header :: proc "contextless" (m: ^$T/map[$K]$V) -> Map_Header { - header := Map_Header{m = (^Raw_Map)(m)}; + header := Map_Header{m = (^Raw_Map)(m)} Entry :: struct { hash: uintptr, next: int, key: K, value: V, - }; + } - header.equal = intrinsics.type_equal_proc(K); + header.equal = intrinsics.type_equal_proc(K) - header.entry_size = size_of(Entry); - header.entry_align = align_of(Entry); + header.entry_size = size_of(Entry) + header.entry_align = align_of(Entry) - header.key_offset = offset_of(Entry, key); - header.key_size = size_of(K); + header.key_offset = offset_of(Entry, key) + header.key_size = size_of(K) - header.value_offset = offset_of(Entry, value); - header.value_size = size_of(V); + header.value_offset = offset_of(Entry, value) + header.value_size = size_of(V) - return header; + return header } __slice_resize :: proc(array_: ^$T/[]$E, new_count: int, allocator: Allocator, loc := #caller_location) -> bool { - array := (^Raw_Slice)(array_); + array := (^Raw_Slice)(array_) if new_count < array.len { - return true; + return true } - assert(allocator.procedure != nil); + assert(allocator.procedure != nil) - old_size := array.len*size_of(T); - new_size := new_count*size_of(T); + old_size := array.len*size_of(T) + new_size := new_count*size_of(T) - new_data, err := mem_resize(array.data, old_size, new_size, align_of(T), allocator, loc); + new_data, err := mem_resize(array.data, old_size, new_size, align_of(T), allocator, loc) if new_data == nil || err != nil { - return false; + return false } - array.data = new_data; - array.len = new_count; - return true; + array.data = new_data + array.len = new_count + return true } __dynamic_map_reserve :: proc(using header: Map_Header, cap: int, loc := #caller_location) { - __dynamic_array_reserve(&m.entries, entry_size, entry_align, cap, loc); + __dynamic_array_reserve(&m.entries, entry_size, entry_align, cap, loc) - old_len := len(m.hashes); - __slice_resize(&m.hashes, cap, m.entries.allocator, loc); + old_len := len(m.hashes) + __slice_resize(&m.hashes, cap, m.entries.allocator, loc) for i in old_len..<len(m.hashes) { - m.hashes[i] = -1; + m.hashes[i] = -1 } } __dynamic_map_rehash :: proc(using header: Map_Header, new_count: int, loc := #caller_location) #no_bounds_check { - c := context; + c := context if m.entries.allocator.procedure != nil { - c.allocator = m.entries.allocator; + c.allocator = m.entries.allocator } - context = c; + context = c - nm := Raw_Map{}; - nm.entries.allocator = m.entries.allocator; - nm.hashes = m.hashes; + nm := Raw_Map{} + nm.entries.allocator = m.entries.allocator + nm.hashes = m.hashes - new_header: Map_Header = header; - new_header.m = &nm; + new_header: Map_Header = header + new_header.m = &nm - new_count := new_count; - new_count = max(new_count, 2*m.entries.len); + new_count := new_count + new_count = max(new_count, 2*m.entries.len) - __slice_resize(&nm.hashes, new_count, m.entries.allocator, loc); + __slice_resize(&nm.hashes, new_count, m.entries.allocator, loc) for i in 0 ..< new_count { - nm.hashes[i] = -1; + nm.hashes[i] = -1 } - __dynamic_array_reserve(&nm.entries, entry_size, entry_align, m.entries.len, loc); + __dynamic_array_reserve(&nm.entries, entry_size, entry_align, m.entries.len, loc) for i in 0 ..< m.entries.len { if len(nm.hashes) == 0 { - __dynamic_map_grow(new_header, loc); + __dynamic_map_grow(new_header, loc) } - entry_header := __dynamic_map_get_entry(header, i); - entry_hash := __get_map_hash_from_entry(header, entry_header); + entry_header := __dynamic_map_get_entry(header, i) + entry_hash := __get_map_hash_from_entry(header, entry_header) - fr := __dynamic_map_find(new_header, entry_hash); - j := __dynamic_map_add_entry(new_header, entry_hash, loc); + fr := __dynamic_map_find(new_header, entry_hash) + j := __dynamic_map_add_entry(new_header, entry_hash, loc) if fr.entry_prev < 0 { - nm.hashes[fr.hash_index] = j; + nm.hashes[fr.hash_index] = j } else { - e := __dynamic_map_get_entry(new_header, fr.entry_prev); - e.next = j; + e := __dynamic_map_get_entry(new_header, fr.entry_prev) + e.next = j } - e := __dynamic_map_get_entry(new_header, j); - __dynamic_map_copy_entry(header, e, entry_header); - e.next = fr.entry_index; + e := __dynamic_map_get_entry(new_header, j) + __dynamic_map_copy_entry(header, e, entry_header) + e.next = fr.entry_index if __dynamic_map_full(new_header) { - __dynamic_map_grow(new_header, loc); + __dynamic_map_grow(new_header, loc) } } - free(m.entries.data, m.entries.allocator, loc); - header.m^ = nm; + free(m.entries.data, m.entries.allocator, loc) + header.m^ = nm } __dynamic_map_get :: proc(h: Map_Header, hash: Map_Hash) -> rawptr { - index := __dynamic_map_find(h, hash).entry_index; + index := __dynamic_map_find(h, hash).entry_index if index >= 0 { - data := uintptr(__dynamic_map_get_entry(h, index)); - return rawptr(data + h.value_offset); + data := uintptr(__dynamic_map_get_entry(h, index)) + return rawptr(data + h.value_offset) } - return nil; + return nil } __dynamic_map_set :: proc(h: Map_Header, hash: Map_Hash, value: rawptr, loc := #caller_location) -> ^Map_Entry_Header #no_bounds_check { - index: int; - assert(value != nil); + index: int + assert(value != nil) if len(h.m.hashes) == 0 { - __dynamic_map_reserve(h, INITIAL_MAP_CAP, loc); - __dynamic_map_grow(h, loc); + __dynamic_map_reserve(h, INITIAL_MAP_CAP, loc) + __dynamic_map_grow(h, loc) } - fr := __dynamic_map_find(h, hash); + fr := __dynamic_map_find(h, hash) if fr.entry_index >= 0 { - index = fr.entry_index; + index = fr.entry_index } else { - index = __dynamic_map_add_entry(h, hash, loc); + index = __dynamic_map_add_entry(h, hash, loc) if fr.entry_prev >= 0 { - entry := __dynamic_map_get_entry(h, fr.entry_prev); - entry.next = index; + entry := __dynamic_map_get_entry(h, fr.entry_prev) + entry.next = index } else { - h.m.hashes[fr.hash_index] = index; + h.m.hashes[fr.hash_index] = index } } - e := __dynamic_map_get_entry(h, index); - e.hash = hash.hash; + e := __dynamic_map_get_entry(h, index) + e.hash = hash.hash - key := rawptr(uintptr(e) + h.key_offset); - mem_copy(key, hash.key_ptr, h.key_size); + key := rawptr(uintptr(e) + h.key_offset) + mem_copy(key, hash.key_ptr, h.key_size) - val := rawptr(uintptr(e) + h.value_offset); - mem_copy(val, value, h.value_size); + val := rawptr(uintptr(e) + h.value_offset) + mem_copy(val, value, h.value_size) if __dynamic_map_full(h) { - __dynamic_map_grow(h, loc); - index = __dynamic_map_find(h, hash).entry_index; - assert(index >= 0); + __dynamic_map_grow(h, loc) + index = __dynamic_map_find(h, hash).entry_index + assert(index >= 0) } - return __dynamic_map_get_entry(h, index); + return __dynamic_map_get_entry(h, index) } __dynamic_map_grow :: proc(using h: Map_Header, loc := #caller_location) { // TODO(bill): Determine an efficient growing rate - new_count := max(4*m.entries.cap + 7, INITIAL_MAP_CAP); - __dynamic_map_rehash(h, new_count, loc); + new_count := max(4*m.entries.cap + 7, INITIAL_MAP_CAP) + __dynamic_map_rehash(h, new_count, loc) } __dynamic_map_full :: #force_inline proc "contextless" (using h: Map_Header) -> bool { - return int(0.75 * f64(len(m.hashes))) <= m.entries.len; + return int(0.75 * f64(len(m.hashes))) <= m.entries.len } __dynamic_map_hash_equal :: proc "contextless" (h: Map_Header, a, b: Map_Hash) -> bool { if a.hash == b.hash { - return h.equal(a.key_ptr, b.key_ptr); + return h.equal(a.key_ptr, b.key_ptr) } - return false; + return false } __dynamic_map_find :: proc(using h: Map_Header, hash: Map_Hash) -> Map_Find_Result #no_bounds_check { - fr := Map_Find_Result{-1, -1, -1}; + fr := Map_Find_Result{-1, -1, -1} if n := uintptr(len(m.hashes)); n > 0 { - fr.hash_index = int(hash.hash % n); - fr.entry_index = m.hashes[fr.hash_index]; + fr.hash_index = int(hash.hash % n) + fr.entry_index = m.hashes[fr.hash_index] for fr.entry_index >= 0 { - entry := __dynamic_map_get_entry(h, fr.entry_index); - entry_hash := __get_map_hash_from_entry(h, entry); + entry := __dynamic_map_get_entry(h, fr.entry_index) + entry_hash := __get_map_hash_from_entry(h, entry) if __dynamic_map_hash_equal(h, entry_hash, hash) { - return fr; + return fr } - fr.entry_prev = fr.entry_index; - fr.entry_index = entry.next; + fr.entry_prev = fr.entry_index + fr.entry_index = entry.next } } - return fr; + return fr } __dynamic_map_add_entry :: proc(using h: Map_Header, hash: Map_Hash, loc := #caller_location) -> int { - prev := m.entries.len; - c := __dynamic_array_append_nothing(&m.entries, entry_size, entry_align, loc); + prev := m.entries.len + c := __dynamic_array_append_nothing(&m.entries, entry_size, entry_align, loc) if c != prev { - end := __dynamic_map_get_entry(h, c-1); - end.hash = hash.hash; - mem_copy(rawptr(uintptr(end) + key_offset), hash.key_ptr, key_size); - end.next = -1; + end := __dynamic_map_get_entry(h, c-1) + end.hash = hash.hash + mem_copy(rawptr(uintptr(end) + key_offset), hash.key_ptr, key_size) + end.next = -1 } - return prev; + return prev } __dynamic_map_delete_key :: proc(using h: Map_Header, hash: Map_Hash) { - fr := __dynamic_map_find(h, hash); + fr := __dynamic_map_find(h, hash) if fr.entry_index >= 0 { - __dynamic_map_erase(h, fr); + __dynamic_map_erase(h, fr) } } __dynamic_map_get_entry :: proc(using h: Map_Header, index: int) -> ^Map_Entry_Header { - assert(0 <= index && index < m.entries.len); - return (^Map_Entry_Header)(uintptr(m.entries.data) + uintptr(index*entry_size)); + assert(0 <= index && index < m.entries.len) + return (^Map_Entry_Header)(uintptr(m.entries.data) + uintptr(index*entry_size)) } __dynamic_map_copy_entry :: proc "contextless" (h: Map_Header, new, old: ^Map_Entry_Header) { - mem_copy(new, old, h.entry_size); + mem_copy(new, old, h.entry_size) } __dynamic_map_erase :: proc(using h: Map_Header, fr: Map_Find_Result) #no_bounds_check { if fr.entry_prev < 0 { - m.hashes[fr.hash_index] = __dynamic_map_get_entry(h, fr.entry_index).next; + m.hashes[fr.hash_index] = __dynamic_map_get_entry(h, fr.entry_index).next } else { - prev := __dynamic_map_get_entry(h, fr.entry_prev); - curr := __dynamic_map_get_entry(h, fr.entry_index); - prev.next = curr.next; + prev := __dynamic_map_get_entry(h, fr.entry_prev) + curr := __dynamic_map_get_entry(h, fr.entry_index) + prev.next = curr.next } if fr.entry_index == m.entries.len-1 { // NOTE(bill): No need to do anything else, just pop } else { - old := __dynamic_map_get_entry(h, fr.entry_index); - end := __dynamic_map_get_entry(h, m.entries.len-1); - __dynamic_map_copy_entry(h, old, end); + old := __dynamic_map_get_entry(h, fr.entry_index) + end := __dynamic_map_get_entry(h, m.entries.len-1) + __dynamic_map_copy_entry(h, old, end) - old_hash := __get_map_hash_from_entry(h, old); + old_hash := __get_map_hash_from_entry(h, old) if last := __dynamic_map_find(h, old_hash); last.entry_prev >= 0 { - last_entry := __dynamic_map_get_entry(h, last.entry_prev); - last_entry.next = fr.entry_index; + last_entry := __dynamic_map_get_entry(h, last.entry_prev) + last_entry.next = fr.entry_index } else { - m.hashes[last.hash_index] = fr.entry_index; + m.hashes[last.hash_index] = fr.entry_index } } - m.entries.len -= 1; + m.entries.len -= 1 } diff --git a/core/runtime/error_checks.odin b/core/runtime/error_checks.odin index fb8ccab64..bdd010b50 100644 --- a/core/runtime/error_checks.odin +++ b/core/runtime/error_checks.odin @@ -2,210 +2,210 @@ package runtime bounds_trap :: proc "contextless" () -> ! { when ODIN_OS == "windows" { - windows_trap_array_bounds(); + windows_trap_array_bounds() } else { - trap(); + trap() } } type_assertion_trap :: proc "contextless" () -> ! { when ODIN_OS == "windows" { - windows_trap_type_assertion(); + windows_trap_type_assertion() } else { - trap(); + trap() } } bounds_check_error :: proc "contextless" (file: string, line, column: i32, index, count: int) { if 0 <= index && index < count { - return; + return } handle_error :: proc "contextless" (file: string, line, column: i32, index, count: int) { - print_caller_location(Source_Code_Location{file, line, column, ""}); - print_string(" Index "); - print_i64(i64(index)); - print_string(" is out of bounds range 0:"); - print_i64(i64(count)); - print_byte('\n'); - bounds_trap(); + print_caller_location(Source_Code_Location{file, line, column, ""}) + print_string(" Index ") + print_i64(i64(index)) + print_string(" is out of bounds range 0:") + print_i64(i64(count)) + print_byte('\n') + bounds_trap() } - handle_error(file, line, column, index, count); + handle_error(file, line, column, index, count) } slice_handle_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int, len: int) -> ! { - print_caller_location(Source_Code_Location{file, line, column, ""}); - print_string(" Invalid slice indices: "); - print_i64(i64(lo)); - print_string(":"); - print_i64(i64(hi)); - print_string(":"); - print_i64(i64(len)); - print_byte('\n'); - bounds_trap(); + print_caller_location(Source_Code_Location{file, line, column, ""}) + print_string(" Invalid slice indices: ") + print_i64(i64(lo)) + print_string(":") + print_i64(i64(hi)) + print_string(":") + print_i64(i64(len)) + print_byte('\n') + bounds_trap() } multi_pointer_slice_handle_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int) -> ! { - print_caller_location(Source_Code_Location{file, line, column, ""}); - print_string(" Invalid slice indices: "); - print_i64(i64(lo)); - print_string(":"); - print_i64(i64(hi)); - print_byte('\n'); - bounds_trap(); + print_caller_location(Source_Code_Location{file, line, column, ""}) + print_string(" Invalid slice indices: ") + print_i64(i64(lo)) + print_string(":") + print_i64(i64(hi)) + print_byte('\n') + bounds_trap() } multi_pointer_slice_expr_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int) { if lo <= hi { - return; + return } - multi_pointer_slice_handle_error(file, line, column, lo, hi); + multi_pointer_slice_handle_error(file, line, column, lo, hi) } slice_expr_error_hi :: proc "contextless" (file: string, line, column: i32, hi: int, len: int) { if 0 <= hi && hi <= len { - return; + return } - slice_handle_error(file, line, column, 0, hi, len); + slice_handle_error(file, line, column, 0, hi, len) } slice_expr_error_lo_hi :: proc "contextless" (file: string, line, column: i32, lo, hi: int, len: int) { if 0 <= lo && lo <= len && lo <= hi && hi <= len { - return; + return } - slice_handle_error(file, line, column, lo, hi, len); + slice_handle_error(file, line, column, lo, hi, len) } dynamic_array_expr_error :: proc "contextless" (file: string, line, column: i32, low, high, max: int) { if 0 <= low && low <= high && high <= max { - return; + return } handle_error :: proc "contextless" (file: string, line, column: i32, low, high, max: int) { - print_caller_location(Source_Code_Location{file, line, column, ""}); - print_string(" Invalid dynamic array values: "); - print_i64(i64(low)); - print_string(":"); - print_i64(i64(high)); - print_string(":"); - print_i64(i64(max)); - print_byte('\n'); - bounds_trap(); + print_caller_location(Source_Code_Location{file, line, column, ""}) + print_string(" Invalid dynamic array values: ") + print_i64(i64(low)) + print_string(":") + print_i64(i64(high)) + print_string(":") + print_i64(i64(max)) + print_byte('\n') + bounds_trap() } - handle_error(file, line, column, low, high, max); + handle_error(file, line, column, low, high, max) } type_assertion_check :: proc "contextless" (ok: bool, file: string, line, column: i32, from, to: typeid) { if ok { - return; + return } handle_error :: proc "contextless" (file: string, line, column: i32, from, to: typeid) { - print_caller_location(Source_Code_Location{file, line, column, ""}); - print_string(" Invalid type assertion from "); - print_typeid(from); - print_string(" to "); - print_typeid(to); - print_byte('\n'); - type_assertion_trap(); + print_caller_location(Source_Code_Location{file, line, column, ""}) + print_string(" Invalid type assertion from ") + print_typeid(from) + print_string(" to ") + print_typeid(to) + print_byte('\n') + type_assertion_trap() } - handle_error(file, line, column, from, to); + handle_error(file, line, column, from, to) } type_assertion_check2 :: proc "contextless" (ok: bool, file: string, line, column: i32, from, to: typeid, from_data: rawptr) { if ok { - return; + return } variant_type :: proc "contextless" (id: typeid, data: rawptr) -> typeid { if id == nil || data == nil { - return id; + return id } - ti := type_info_base(type_info_of(id)); + ti := type_info_base(type_info_of(id)) #partial switch v in ti.variant { case Type_Info_Any: - return (^any)(data).id; + return (^any)(data).id case Type_Info_Union: - tag_ptr := uintptr(data) + v.tag_offset; - idx := 0; + tag_ptr := uintptr(data) + v.tag_offset + idx := 0 switch v.tag_type.size { - case 1: idx = int((^u8)(tag_ptr)^) - 1; - case 2: idx = int((^u16)(tag_ptr)^) - 1; - case 4: idx = int((^u32)(tag_ptr)^) - 1; - case 8: idx = int((^u64)(tag_ptr)^) - 1; - case 16: idx = int((^u128)(tag_ptr)^) - 1; + case 1: idx = int((^u8)(tag_ptr)^) - 1 + case 2: idx = int((^u16)(tag_ptr)^) - 1 + case 4: idx = int((^u32)(tag_ptr)^) - 1 + case 8: idx = int((^u64)(tag_ptr)^) - 1 + case 16: idx = int((^u128)(tag_ptr)^) - 1 } if idx < 0 { - return nil; + return nil } else if idx < len(v.variants) { - return v.variants[idx].id; + return v.variants[idx].id } } - return id; + return id } handle_error :: proc "contextless" (file: string, line, column: i32, from, to: typeid, from_data: rawptr) { - actual := variant_type(from, from_data); + actual := variant_type(from, from_data) - print_caller_location(Source_Code_Location{file, line, column, ""}); - print_string(" Invalid type assertion from "); - print_typeid(from); - print_string(" to "); - print_typeid(to); + print_caller_location(Source_Code_Location{file, line, column, ""}) + print_string(" Invalid type assertion from ") + print_typeid(from) + print_string(" to ") + print_typeid(to) if actual != from { - print_string(", actual type: "); - print_typeid(actual); + print_string(", actual type: ") + print_typeid(actual) } - print_byte('\n'); - type_assertion_trap(); + print_byte('\n') + type_assertion_trap() } - handle_error(file, line, column, from, to, from_data); + handle_error(file, line, column, from, to, from_data) } make_slice_error_loc :: #force_inline proc "contextless" (loc := #caller_location, len: int) { if 0 <= len { - return; + return } handle_error :: proc "contextless" (loc: Source_Code_Location, len: int) { - print_caller_location(loc); - print_string(" Invalid slice length for make: "); - print_i64(i64(len)); - print_byte('\n'); - bounds_trap(); + print_caller_location(loc) + print_string(" Invalid slice length for make: ") + print_i64(i64(len)) + print_byte('\n') + bounds_trap() } - handle_error(loc, len); + handle_error(loc, len) } make_dynamic_array_error_loc :: #force_inline proc "contextless" (using loc := #caller_location, len, cap: int) { if 0 <= len && len <= cap { - return; + return } handle_error :: proc "contextless" (loc: Source_Code_Location, len, cap: int) { - print_caller_location(loc); - print_string(" Invalid dynamic array parameters for make: "); - print_i64(i64(len)); - print_byte(':'); - print_i64(i64(cap)); - print_byte('\n'); - bounds_trap(); + print_caller_location(loc) + print_string(" Invalid dynamic array parameters for make: ") + print_i64(i64(len)) + print_byte(':') + print_i64(i64(cap)) + print_byte('\n') + bounds_trap() } - handle_error(loc, len, cap); + handle_error(loc, len, cap) } make_map_expr_error_loc :: #force_inline proc "contextless" (loc := #caller_location, cap: int) { if 0 <= cap { - return; + return } handle_error :: proc "contextless" (loc: Source_Code_Location, cap: int) { - print_caller_location(loc); - print_string(" Invalid map capacity for make: "); - print_i64(i64(cap)); - print_byte('\n'); - bounds_trap(); + print_caller_location(loc) + print_string(" Invalid map capacity for make: ") + print_i64(i64(cap)) + print_byte('\n') + bounds_trap() } - handle_error(loc, cap); + handle_error(loc, cap) } @@ -213,17 +213,17 @@ make_map_expr_error_loc :: #force_inline proc "contextless" (loc := #caller_loca bounds_check_error_loc :: #force_inline proc "contextless" (using loc := #caller_location, index, count: int) { - bounds_check_error(file_path, line, column, index, count); + bounds_check_error(file_path, line, column, index, count) } slice_expr_error_hi_loc :: #force_inline proc "contextless" (using loc := #caller_location, hi: int, len: int) { - slice_expr_error_hi(file_path, line, column, hi, len); + slice_expr_error_hi(file_path, line, column, hi, len) } slice_expr_error_lo_hi_loc :: #force_inline proc "contextless" (using loc := #caller_location, lo, hi: int, len: int) { - slice_expr_error_lo_hi(file_path, line, column, lo, hi, len); + slice_expr_error_lo_hi(file_path, line, column, lo, hi, len) } dynamic_array_expr_error_loc :: #force_inline proc "contextless" (using loc := #caller_location, low, high, max: int) { - dynamic_array_expr_error(file_path, line, column, low, high, max); + dynamic_array_expr_error(file_path, line, column, low, high, max) } diff --git a/core/runtime/internal.odin b/core/runtime/internal.odin index 143a8c518..b54e8dc5d 100644 --- a/core/runtime/internal.odin +++ b/core/runtime/internal.odin @@ -3,276 +3,276 @@ package runtime import "core:intrinsics" bswap_16 :: proc "none" (x: u16) -> u16 { - return x>>8 | x<<8; + return x>>8 | x<<8 } bswap_32 :: proc "none" (x: u32) -> u32 { - return x>>24 | (x>>8)&0xff00 | (x<<8)&0xff0000 | x<<24; + return x>>24 | (x>>8)&0xff00 | (x<<8)&0xff0000 | x<<24 } bswap_64 :: proc "none" (x: u64) -> u64 { - z := x; - z = (z & 0x00000000ffffffff) << 32 | (z & 0xffffffff00000000) >> 32; - z = (z & 0x0000ffff0000ffff) << 16 | (z & 0xffff0000ffff0000) >> 16; - z = (z & 0x00ff00ff00ff00ff) << 8 | (z & 0xff00ff00ff00ff00) >> 8; - return z; + z := x + z = (z & 0x00000000ffffffff) << 32 | (z & 0xffffffff00000000) >> 32 + z = (z & 0x0000ffff0000ffff) << 16 | (z & 0xffff0000ffff0000) >> 16 + z = (z & 0x00ff00ff00ff00ff) << 8 | (z & 0xff00ff00ff00ff00) >> 8 + return z } bswap_128 :: proc "none" (x: u128) -> u128 { - z := transmute([4]u32)x; - z[0] = bswap_32(z[3]); - z[1] = bswap_32(z[2]); - z[2] = bswap_32(z[1]); - z[3] = bswap_32(z[0]); - return transmute(u128)z; + z := transmute([4]u32)x + z[0] = bswap_32(z[3]) + z[1] = bswap_32(z[2]) + z[2] = bswap_32(z[1]) + z[3] = bswap_32(z[0]) + return transmute(u128)z } bswap_f16 :: proc "none" (f: f16) -> f16 { - x := transmute(u16)f; - z := bswap_16(x); - return transmute(f16)z; + x := transmute(u16)f + z := bswap_16(x) + return transmute(f16)z } bswap_f32 :: proc "none" (f: f32) -> f32 { - x := transmute(u32)f; - z := bswap_32(x); - return transmute(f32)z; + x := transmute(u32)f + z := bswap_32(x) + return transmute(f32)z } bswap_f64 :: proc "none" (f: f64) -> f64 { - x := transmute(u64)f; - z := bswap_64(x); - return transmute(f64)z; + x := transmute(u64)f + z := bswap_64(x) + return transmute(f64)z } ptr_offset :: #force_inline proc "contextless" (ptr: $P/^$T, n: int) -> P { - new := int(uintptr(ptr)) + size_of(T)*n; - return P(uintptr(new)); + new := int(uintptr(ptr)) + size_of(T)*n + return P(uintptr(new)) } is_power_of_two_int :: #force_inline proc(x: int) -> bool { if x <= 0 { - return false; + return false } - return (x & (x-1)) == 0; + return (x & (x-1)) == 0 } align_forward_int :: #force_inline proc(ptr, align: int) -> int { - assert(is_power_of_two_int(align)); + assert(is_power_of_two_int(align)) - p := ptr; - modulo := p & (align-1); + p := ptr + modulo := p & (align-1) if modulo != 0 { - p += align - modulo; + p += align - modulo } - return p; + return p } is_power_of_two_uintptr :: #force_inline proc(x: uintptr) -> bool { if x <= 0 { - return false; + return false } - return (x & (x-1)) == 0; + return (x & (x-1)) == 0 } align_forward_uintptr :: #force_inline proc(ptr, align: uintptr) -> uintptr { - assert(is_power_of_two_uintptr(align)); + assert(is_power_of_two_uintptr(align)) - p := ptr; - modulo := p & (align-1); + p := ptr + modulo := p & (align-1) if modulo != 0 { - p += align - modulo; + p += align - modulo } - return p; + return p } mem_zero :: proc "contextless" (data: rawptr, len: int) -> rawptr { if data == nil { - return nil; + return nil } if len < 0 { - return data; + return data } - intrinsics.mem_zero(data, len); - return data; + intrinsics.mem_zero(data, len) + return data } mem_copy :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr { if src == nil { - return dst; + return dst } // NOTE(bill): This _must_ be implemented like C's memmove - intrinsics.mem_copy(dst, src, len); - return dst; + intrinsics.mem_copy(dst, src, len) + return dst } mem_copy_non_overlapping :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr { if src == nil { - return dst; + return dst } // NOTE(bill): This _must_ be implemented like C's memcpy - intrinsics.mem_copy_non_overlapping(dst, src, len); - return dst; + intrinsics.mem_copy_non_overlapping(dst, src, len) + return dst } -DEFAULT_ALIGNMENT :: 2*align_of(rawptr); +DEFAULT_ALIGNMENT :: 2*align_of(rawptr) mem_alloc_bytes :: #force_inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) { if size == 0 { - return nil, nil; + return nil, nil } if allocator.procedure == nil { - return nil, nil; + return nil, nil } - return allocator.procedure(allocator.data, .Alloc, size, alignment, nil, 0, loc); + return allocator.procedure(allocator.data, .Alloc, size, alignment, nil, 0, loc) } mem_alloc :: #force_inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (rawptr, Allocator_Error) { if size == 0 { - return nil, nil; + return nil, nil } if allocator.procedure == nil { - return nil, nil; + return nil, nil } - data, err := allocator.procedure(allocator.data, .Alloc, size, alignment, nil, 0, loc); - return raw_data(data), err; + data, err := allocator.procedure(allocator.data, .Alloc, size, alignment, nil, 0, loc) + return raw_data(data), err } mem_free :: #force_inline proc(ptr: rawptr, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { if ptr == nil { - return .None; + return .None } if allocator.procedure == nil { - return .None; + return .None } - _, err := allocator.procedure(allocator.data, .Free, 0, 0, ptr, 0, loc); - return err; + _, err := allocator.procedure(allocator.data, .Free, 0, 0, ptr, 0, loc) + return err } mem_free_all :: #force_inline proc(allocator := context.allocator, loc := #caller_location) -> (err: Allocator_Error) { if allocator.procedure != nil { - _, err = allocator.procedure(allocator.data, .Free_All, 0, 0, nil, 0, loc); + _, err = allocator.procedure(allocator.data, .Free_All, 0, 0, nil, 0, loc) } - return; + return } mem_resize :: #force_inline proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (new_ptr: rawptr, err: Allocator_Error) { - new_data: []byte; + new_data: []byte switch { case allocator.procedure == nil: - return; + return case new_size == 0: - new_data, err = allocator.procedure(allocator.data, .Free, 0, 0, ptr, 0, loc); + new_data, err = allocator.procedure(allocator.data, .Free, 0, 0, ptr, 0, loc) case ptr == nil: - new_data, err = allocator.procedure(allocator.data, .Alloc, new_size, alignment, nil, 0, loc); + new_data, err = allocator.procedure(allocator.data, .Alloc, new_size, alignment, nil, 0, loc) case: - new_data, err = allocator.procedure(allocator.data, .Resize, new_size, alignment, ptr, old_size, loc); + new_data, err = allocator.procedure(allocator.data, .Resize, new_size, alignment, ptr, old_size, loc) } - new_ptr = raw_data(new_data); - return; + new_ptr = raw_data(new_data) + return } memory_equal :: proc "contextless" (a, b: rawptr, n: int) -> bool { - return memory_compare(a, b, n) == 0; + return memory_compare(a, b, n) == 0 } memory_compare :: proc "contextless" (a, b: rawptr, n: int) -> int #no_bounds_check { switch { - case a == b: return 0; - case a == nil: return -1; - case b == nil: return +1; + case a == b: return 0 + case a == nil: return -1 + case b == nil: return +1 } - x := uintptr(a); - y := uintptr(b); - n := uintptr(n); + x := uintptr(a) + y := uintptr(b) + n := uintptr(n) - SU :: size_of(uintptr); - fast := n/SU + 1; - offset := (fast-1)*SU; - curr_block := uintptr(0); + SU :: size_of(uintptr) + fast := n/SU + 1 + offset := (fast-1)*SU + curr_block := uintptr(0) if n < SU { - fast = 0; + fast = 0 } for /**/; curr_block < fast; curr_block += 1 { - va := (^uintptr)(x + curr_block * size_of(uintptr))^; - vb := (^uintptr)(y + curr_block * size_of(uintptr))^; + va := (^uintptr)(x + curr_block * size_of(uintptr))^ + vb := (^uintptr)(y + curr_block * size_of(uintptr))^ if va ~ vb != 0 { for pos := curr_block*SU; pos < n; pos += 1 { - a := (^byte)(x+pos)^; - b := (^byte)(y+pos)^; + a := (^byte)(x+pos)^ + b := (^byte)(y+pos)^ if a ~ b != 0 { - return -1 if (int(a) - int(b)) < 0 else +1; + return -1 if (int(a) - int(b)) < 0 else +1 } } } } for /**/; offset < n; offset += 1 { - a := (^byte)(x+offset)^; - b := (^byte)(y+offset)^; + a := (^byte)(x+offset)^ + b := (^byte)(y+offset)^ if a ~ b != 0 { - return -1 if (int(a) - int(b)) < 0 else +1; + return -1 if (int(a) - int(b)) < 0 else +1 } } - return 0; + return 0 } memory_compare_zero :: proc "contextless" (a: rawptr, n: int) -> int #no_bounds_check { - x := uintptr(a); - n := uintptr(n); + x := uintptr(a) + n := uintptr(n) - SU :: size_of(uintptr); - fast := n/SU + 1; - offset := (fast-1)*SU; - curr_block := uintptr(0); + SU :: size_of(uintptr) + fast := n/SU + 1 + offset := (fast-1)*SU + curr_block := uintptr(0) if n < SU { - fast = 0; + fast = 0 } for /**/; curr_block < fast; curr_block += 1 { - va := (^uintptr)(x + curr_block * size_of(uintptr))^; + va := (^uintptr)(x + curr_block * size_of(uintptr))^ if va ~ 0 != 0 { for pos := curr_block*SU; pos < n; pos += 1 { - a := (^byte)(x+pos)^; + a := (^byte)(x+pos)^ if a ~ 0 != 0 { - return -1 if int(a) < 0 else +1; + return -1 if int(a) < 0 else +1 } } } } for /**/; offset < n; offset += 1 { - a := (^byte)(x+offset)^; + a := (^byte)(x+offset)^ if a ~ 0 != 0 { - return -1 if int(a) < 0 else +1; + return -1 if int(a) < 0 else +1 } } - return 0; + return 0 } string_eq :: proc "contextless" (a, b: string) -> bool { - x := transmute(Raw_String)a; - y := transmute(Raw_String)b; + x := transmute(Raw_String)a + y := transmute(Raw_String)b switch { - case x.len != y.len: return false; - case x.len == 0: return true; - case x.data == y.data: return true; + case x.len != y.len: return false + case x.len == 0: return true + case x.data == y.data: return true } - return string_cmp(a, b) == 0; + return string_cmp(a, b) == 0 } string_cmp :: proc "contextless" (a, b: string) -> int { - x := transmute(Raw_String)a; - y := transmute(Raw_String)b; - return memory_compare(x.data, y.data, min(x.len, y.len)); + x := transmute(Raw_String)a + y := transmute(Raw_String)b + return memory_compare(x.data, y.data, min(x.len, y.len)) } string_ne :: #force_inline proc "contextless" (a, b: string) -> bool { return !string_eq(a, b); } @@ -282,21 +282,21 @@ string_le :: #force_inline proc "contextless" (a, b: string) -> bool { return st string_ge :: #force_inline proc "contextless" (a, b: string) -> bool { return string_cmp(a, b) >= 0; } cstring_len :: proc "contextless" (s: cstring) -> int { - p0 := uintptr((^byte)(s)); - p := p0; + p0 := uintptr((^byte)(s)) + p := p0 for p != 0 && (^byte)(p)^ != 0 { - p += 1; + p += 1 } - return int(p - p0); + return int(p - p0) } cstring_to_string :: proc "contextless" (s: cstring) -> string { if s == nil { - return ""; + return "" } - ptr := (^byte)(s); - n := cstring_len(s); - return transmute(string)Raw_String{ptr, n}; + ptr := (^byte)(s) + n := cstring_len(s) + return transmute(string)Raw_String{ptr, n} } @@ -341,8 +341,8 @@ string_decode_rune :: #force_inline proc "contextless" (s: string) -> (rune, int 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, // 0xd0-0xdf 0x13, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x23, 0x03, 0x03, // 0xe0-0xef 0x34, 0x04, 0x04, 0x04, 0x44, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, // 0xf0-0xff - }; - Accept_Range :: struct {lo, hi: u8}; + } + Accept_Range :: struct {lo, hi: u8} @static accept_ranges := [5]Accept_Range{ {0x80, 0xbf}, @@ -350,416 +350,416 @@ string_decode_rune :: #force_inline proc "contextless" (s: string) -> (rune, int {0x80, 0x9f}, {0x90, 0xbf}, {0x80, 0x8f}, - }; + } - MASKX :: 0b0011_1111; - MASK2 :: 0b0001_1111; - MASK3 :: 0b0000_1111; - MASK4 :: 0b0000_0111; + MASKX :: 0b0011_1111 + MASK2 :: 0b0001_1111 + MASK3 :: 0b0000_1111 + MASK4 :: 0b0000_0111 - LOCB :: 0b1000_0000; - HICB :: 0b1011_1111; + LOCB :: 0b1000_0000 + HICB :: 0b1011_1111 - RUNE_ERROR :: '\ufffd'; + RUNE_ERROR :: '\ufffd' - n := len(s); + n := len(s) if n < 1 { - return RUNE_ERROR, 0; + return RUNE_ERROR, 0 } - s0 := s[0]; - x := accept_sizes[s0]; + s0 := s[0] + x := accept_sizes[s0] if x >= 0xF0 { - mask := rune(x) << 31 >> 31; // NOTE(bill): Create 0x0000 or 0xffff. - return rune(s[0])&~mask | RUNE_ERROR&mask, 1; + mask := rune(x) << 31 >> 31 // NOTE(bill): Create 0x0000 or 0xffff. + return rune(s[0])&~mask | RUNE_ERROR&mask, 1 } - sz := x & 7; - accept := accept_ranges[x>>4]; + sz := x & 7 + accept := accept_ranges[x>>4] if n < int(sz) { - return RUNE_ERROR, 1; + return RUNE_ERROR, 1 } - b1 := s[1]; + b1 := s[1] if b1 < accept.lo || accept.hi < b1 { - return RUNE_ERROR, 1; + return RUNE_ERROR, 1 } if sz == 2 { - return rune(s0&MASK2)<<6 | rune(b1&MASKX), 2; + return rune(s0&MASK2)<<6 | rune(b1&MASKX), 2 } - b2 := s[2]; + b2 := s[2] if b2 < LOCB || HICB < b2 { - return RUNE_ERROR, 1; + return RUNE_ERROR, 1 } if sz == 3 { - return rune(s0&MASK3)<<12 | rune(b1&MASKX)<<6 | rune(b2&MASKX), 3; + return rune(s0&MASK3)<<12 | rune(b1&MASKX)<<6 | rune(b2&MASKX), 3 } - b3 := s[3]; + b3 := s[3] if b3 < LOCB || HICB < b3 { - return RUNE_ERROR, 1; + return RUNE_ERROR, 1 } - return rune(s0&MASK4)<<18 | rune(b1&MASKX)<<12 | rune(b2&MASKX)<<6 | rune(b3&MASKX), 4; + return rune(s0&MASK4)<<18 | rune(b1&MASKX)<<12 | rune(b2&MASKX)<<6 | rune(b3&MASKX), 4 } abs_f16 :: #force_inline proc "contextless" (x: f16) -> f16 { - return -x if x < 0 else x; + return -x if x < 0 else x } abs_f32 :: #force_inline proc "contextless" (x: f32) -> f32 { - return -x if x < 0 else x; + return -x if x < 0 else x } abs_f64 :: #force_inline proc "contextless" (x: f64) -> f64 { - return -x if x < 0 else x; + return -x if x < 0 else x } min_f16 :: #force_inline proc "contextless" (a, b: f16) -> f16 { - return a if a < b else b; + return a if a < b else b } min_f32 :: #force_inline proc "contextless" (a, b: f32) -> f32 { - return a if a < b else b; + return a if a < b else b } min_f64 :: #force_inline proc "contextless" (a, b: f64) -> f64 { - return a if a < b else b; + return a if a < b else b } max_f16 :: #force_inline proc "contextless" (a, b: f16) -> f16 { - return a if a > b else b; + return a if a > b else b } max_f32 :: #force_inline proc "contextless" (a, b: f32) -> f32 { - return a if a > b else b; + return a if a > b else b } max_f64 :: #force_inline proc "contextless" (a, b: f64) -> f64 { - return a if a > b else b; + return a if a > b else b } abs_complex32 :: #force_inline proc "contextless" (x: complex32) -> f16 { - r, i := real(x), imag(x); - return f16(intrinsics.sqrt(f32(r*r + i*i))); + r, i := real(x), imag(x) + return f16(intrinsics.sqrt(f32(r*r + i*i))) } abs_complex64 :: #force_inline proc "contextless" (x: complex64) -> f32 { - r, i := real(x), imag(x); - return intrinsics.sqrt(r*r + i*i); + r, i := real(x), imag(x) + return intrinsics.sqrt(r*r + i*i) } abs_complex128 :: #force_inline proc "contextless" (x: complex128) -> f64 { - r, i := real(x), imag(x); - return intrinsics.sqrt(r*r + i*i); + r, i := real(x), imag(x) + return intrinsics.sqrt(r*r + i*i) } abs_quaternion64 :: #force_inline proc "contextless" (x: quaternion64) -> f16 { - r, i, j, k := real(x), imag(x), jmag(x), kmag(x); - return f16(intrinsics.sqrt(f32(r*r + i*i + j*j + k*k))); + r, i, j, k := real(x), imag(x), jmag(x), kmag(x) + return f16(intrinsics.sqrt(f32(r*r + i*i + j*j + k*k))) } abs_quaternion128 :: #force_inline proc "contextless" (x: quaternion128) -> f32 { - r, i, j, k := real(x), imag(x), jmag(x), kmag(x); - return intrinsics.sqrt(r*r + i*i + j*j + k*k); + r, i, j, k := real(x), imag(x), jmag(x), kmag(x) + return intrinsics.sqrt(r*r + i*i + j*j + k*k) } abs_quaternion256 :: #force_inline proc "contextless" (x: quaternion256) -> f64 { - r, i, j, k := real(x), imag(x), jmag(x), kmag(x); - return intrinsics.sqrt(r*r + i*i + j*j + k*k); + r, i, j, k := real(x), imag(x), jmag(x), kmag(x) + return intrinsics.sqrt(r*r + i*i + j*j + k*k) } quo_complex32 :: proc "contextless" (n, m: complex32) -> complex32 { - e, f: f16; + e, f: f16 if abs(real(m)) >= abs(imag(m)) { - ratio := imag(m) / real(m); - denom := real(m) + ratio*imag(m); - e = (real(n) + imag(n)*ratio) / denom; - f = (imag(n) - real(n)*ratio) / denom; + ratio := imag(m) / real(m) + denom := real(m) + ratio*imag(m) + e = (real(n) + imag(n)*ratio) / denom + f = (imag(n) - real(n)*ratio) / denom } else { - ratio := real(m) / imag(m); - denom := imag(m) + ratio*real(m); - e = (real(n)*ratio + imag(n)) / denom; - f = (imag(n)*ratio - real(n)) / denom; + ratio := real(m) / imag(m) + denom := imag(m) + ratio*real(m) + e = (real(n)*ratio + imag(n)) / denom + f = (imag(n)*ratio - real(n)) / denom } - return complex(e, f); + return complex(e, f) } quo_complex64 :: proc "contextless" (n, m: complex64) -> complex64 { - e, f: f32; + e, f: f32 if abs(real(m)) >= abs(imag(m)) { - ratio := imag(m) / real(m); - denom := real(m) + ratio*imag(m); - e = (real(n) + imag(n)*ratio) / denom; - f = (imag(n) - real(n)*ratio) / denom; + ratio := imag(m) / real(m) + denom := real(m) + ratio*imag(m) + e = (real(n) + imag(n)*ratio) / denom + f = (imag(n) - real(n)*ratio) / denom } else { - ratio := real(m) / imag(m); - denom := imag(m) + ratio*real(m); - e = (real(n)*ratio + imag(n)) / denom; - f = (imag(n)*ratio - real(n)) / denom; + ratio := real(m) / imag(m) + denom := imag(m) + ratio*real(m) + e = (real(n)*ratio + imag(n)) / denom + f = (imag(n)*ratio - real(n)) / denom } - return complex(e, f); + return complex(e, f) } quo_complex128 :: proc "contextless" (n, m: complex128) -> complex128 { - e, f: f64; + e, f: f64 if abs(real(m)) >= abs(imag(m)) { - ratio := imag(m) / real(m); - denom := real(m) + ratio*imag(m); - e = (real(n) + imag(n)*ratio) / denom; - f = (imag(n) - real(n)*ratio) / denom; + ratio := imag(m) / real(m) + denom := real(m) + ratio*imag(m) + e = (real(n) + imag(n)*ratio) / denom + f = (imag(n) - real(n)*ratio) / denom } else { - ratio := real(m) / imag(m); - denom := imag(m) + ratio*real(m); - e = (real(n)*ratio + imag(n)) / denom; - f = (imag(n)*ratio - real(n)) / denom; + ratio := real(m) / imag(m) + denom := imag(m) + ratio*real(m) + e = (real(n)*ratio + imag(n)) / denom + f = (imag(n)*ratio - real(n)) / denom } - return complex(e, f); + return complex(e, f) } mul_quaternion64 :: proc "contextless" (q, r: quaternion64) -> quaternion64 { - q0, q1, q2, q3 := real(q), imag(q), jmag(q), kmag(q); - r0, r1, r2, r3 := real(r), imag(r), jmag(r), kmag(r); + q0, q1, q2, q3 := real(q), imag(q), jmag(q), kmag(q) + r0, r1, r2, r3 := real(r), imag(r), jmag(r), kmag(r) - t0 := r0*q0 - r1*q1 - r2*q2 - r3*q3; - t1 := r0*q1 + r1*q0 - r2*q3 + r3*q2; - t2 := r0*q2 + r1*q3 + r2*q0 - r3*q1; - t3 := r0*q3 - r1*q2 + r2*q1 + r3*q0; + t0 := r0*q0 - r1*q1 - r2*q2 - r3*q3 + t1 := r0*q1 + r1*q0 - r2*q3 + r3*q2 + t2 := r0*q2 + r1*q3 + r2*q0 - r3*q1 + t3 := r0*q3 - r1*q2 + r2*q1 + r3*q0 - return quaternion(t0, t1, t2, t3); + return quaternion(t0, t1, t2, t3) } mul_quaternion128 :: proc "contextless" (q, r: quaternion128) -> quaternion128 { - q0, q1, q2, q3 := real(q), imag(q), jmag(q), kmag(q); - r0, r1, r2, r3 := real(r), imag(r), jmag(r), kmag(r); + q0, q1, q2, q3 := real(q), imag(q), jmag(q), kmag(q) + r0, r1, r2, r3 := real(r), imag(r), jmag(r), kmag(r) - t0 := r0*q0 - r1*q1 - r2*q2 - r3*q3; - t1 := r0*q1 + r1*q0 - r2*q3 + r3*q2; - t2 := r0*q2 + r1*q3 + r2*q0 - r3*q1; - t3 := r0*q3 - r1*q2 + r2*q1 + r3*q0; + t0 := r0*q0 - r1*q1 - r2*q2 - r3*q3 + t1 := r0*q1 + r1*q0 - r2*q3 + r3*q2 + t2 := r0*q2 + r1*q3 + r2*q0 - r3*q1 + t3 := r0*q3 - r1*q2 + r2*q1 + r3*q0 - return quaternion(t0, t1, t2, t3); + return quaternion(t0, t1, t2, t3) } mul_quaternion256 :: proc "contextless" (q, r: quaternion256) -> quaternion256 { - q0, q1, q2, q3 := real(q), imag(q), jmag(q), kmag(q); - r0, r1, r2, r3 := real(r), imag(r), jmag(r), kmag(r); + q0, q1, q2, q3 := real(q), imag(q), jmag(q), kmag(q) + r0, r1, r2, r3 := real(r), imag(r), jmag(r), kmag(r) - t0 := r0*q0 - r1*q1 - r2*q2 - r3*q3; - t1 := r0*q1 + r1*q0 - r2*q3 + r3*q2; - t2 := r0*q2 + r1*q3 + r2*q0 - r3*q1; - t3 := r0*q3 - r1*q2 + r2*q1 + r3*q0; + t0 := r0*q0 - r1*q1 - r2*q2 - r3*q3 + t1 := r0*q1 + r1*q0 - r2*q3 + r3*q2 + t2 := r0*q2 + r1*q3 + r2*q0 - r3*q1 + t3 := r0*q3 - r1*q2 + r2*q1 + r3*q0 - return quaternion(t0, t1, t2, t3); + return quaternion(t0, t1, t2, t3) } quo_quaternion64 :: proc "contextless" (q, r: quaternion64) -> quaternion64 { - q0, q1, q2, q3 := real(q), imag(q), jmag(q), kmag(q); - r0, r1, r2, r3 := real(r), imag(r), jmag(r), kmag(r); + q0, q1, q2, q3 := real(q), imag(q), jmag(q), kmag(q) + r0, r1, r2, r3 := real(r), imag(r), jmag(r), kmag(r) - invmag2 := 1.0 / (r0*r0 + r1*r1 + r2*r2 + r3*r3); + invmag2 := 1.0 / (r0*r0 + r1*r1 + r2*r2 + r3*r3) - t0 := (r0*q0 + r1*q1 + r2*q2 + r3*q3) * invmag2; - t1 := (r0*q1 - r1*q0 - r2*q3 - r3*q2) * invmag2; - t2 := (r0*q2 - r1*q3 - r2*q0 + r3*q1) * invmag2; - t3 := (r0*q3 + r1*q2 + r2*q1 - r3*q0) * invmag2; + t0 := (r0*q0 + r1*q1 + r2*q2 + r3*q3) * invmag2 + t1 := (r0*q1 - r1*q0 - r2*q3 - r3*q2) * invmag2 + t2 := (r0*q2 - r1*q3 - r2*q0 + r3*q1) * invmag2 + t3 := (r0*q3 + r1*q2 + r2*q1 - r3*q0) * invmag2 - return quaternion(t0, t1, t2, t3); + return quaternion(t0, t1, t2, t3) } quo_quaternion128 :: proc "contextless" (q, r: quaternion128) -> quaternion128 { - q0, q1, q2, q3 := real(q), imag(q), jmag(q), kmag(q); - r0, r1, r2, r3 := real(r), imag(r), jmag(r), kmag(r); + q0, q1, q2, q3 := real(q), imag(q), jmag(q), kmag(q) + r0, r1, r2, r3 := real(r), imag(r), jmag(r), kmag(r) - invmag2 := 1.0 / (r0*r0 + r1*r1 + r2*r2 + r3*r3); + invmag2 := 1.0 / (r0*r0 + r1*r1 + r2*r2 + r3*r3) - t0 := (r0*q0 + r1*q1 + r2*q2 + r3*q3) * invmag2; - t1 := (r0*q1 - r1*q0 - r2*q3 - r3*q2) * invmag2; - t2 := (r0*q2 - r1*q3 - r2*q0 + r3*q1) * invmag2; - t3 := (r0*q3 + r1*q2 + r2*q1 - r3*q0) * invmag2; + t0 := (r0*q0 + r1*q1 + r2*q2 + r3*q3) * invmag2 + t1 := (r0*q1 - r1*q0 - r2*q3 - r3*q2) * invmag2 + t2 := (r0*q2 - r1*q3 - r2*q0 + r3*q1) * invmag2 + t3 := (r0*q3 + r1*q2 + r2*q1 - r3*q0) * invmag2 - return quaternion(t0, t1, t2, t3); + return quaternion(t0, t1, t2, t3) } quo_quaternion256 :: proc "contextless" (q, r: quaternion256) -> quaternion256 { - q0, q1, q2, q3 := real(q), imag(q), jmag(q), kmag(q); - r0, r1, r2, r3 := real(r), imag(r), jmag(r), kmag(r); + q0, q1, q2, q3 := real(q), imag(q), jmag(q), kmag(q) + r0, r1, r2, r3 := real(r), imag(r), jmag(r), kmag(r) - invmag2 := 1.0 / (r0*r0 + r1*r1 + r2*r2 + r3*r3); + invmag2 := 1.0 / (r0*r0 + r1*r1 + r2*r2 + r3*r3) - t0 := (r0*q0 + r1*q1 + r2*q2 + r3*q3) * invmag2; - t1 := (r0*q1 - r1*q0 - r2*q3 - r3*q2) * invmag2; - t2 := (r0*q2 - r1*q3 - r2*q0 + r3*q1) * invmag2; - t3 := (r0*q3 + r1*q2 + r2*q1 - r3*q0) * invmag2; + t0 := (r0*q0 + r1*q1 + r2*q2 + r3*q3) * invmag2 + t1 := (r0*q1 - r1*q0 - r2*q3 - r3*q2) * invmag2 + t2 := (r0*q2 - r1*q3 - r2*q0 + r3*q1) * invmag2 + t3 := (r0*q3 + r1*q2 + r2*q1 - r3*q0) * invmag2 - return quaternion(t0, t1, t2, t3); + return quaternion(t0, t1, t2, t3) } @(link_name="__truncsfhf2") truncsfhf2 :: proc "c" (value: f32) -> u16 { - v: struct #raw_union { i: u32, f: f32 }; - i, s, e, m: i32; + v: struct #raw_union { i: u32, f: f32 } + i, s, e, m: i32 - v.f = value; - i = i32(v.i); + v.f = value + i = i32(v.i) - s = (i >> 16) & 0x00008000; - e = ((i >> 23) & 0x000000ff) - (127 - 15); - m = i & 0x007fffff; + s = (i >> 16) & 0x00008000 + e = ((i >> 23) & 0x000000ff) - (127 - 15) + m = i & 0x007fffff if e <= 0 { if e < -10 { - return u16(s); + return u16(s) } - m = (m | 0x00800000) >> u32(1 - e); + m = (m | 0x00800000) >> u32(1 - e) if m & 0x00001000 != 0 { - m += 0x00002000; + m += 0x00002000 } - return u16(s | (m >> 13)); + return u16(s | (m >> 13)) } else if e == 0xff - (127 - 15) { if m == 0 { - return u16(s | 0x7c00); /* NOTE(bill): infinity */ + return u16(s | 0x7c00) /* NOTE(bill): infinity */ } else { /* NOTE(bill): NAN */ - m >>= 13; - return u16(s | 0x7c00 | m | i32(m == 0)); + m >>= 13 + return u16(s | 0x7c00 | m | i32(m == 0)) } } else { if m & 0x00001000 != 0 { - m += 0x00002000; + m += 0x00002000 if (m & 0x00800000) != 0 { - m = 0; - e += 1; + m = 0 + e += 1 } } if e > 30 { - f := i64(1e12); + f := i64(1e12) for j := 0; j < 10; j += 1 { /* NOTE(bill): Cause overflow */ - g := intrinsics.volatile_load(&f); - g *= g; - intrinsics.volatile_store(&f, g); + g := intrinsics.volatile_load(&f) + g *= g + intrinsics.volatile_store(&f, g) } - return u16(s | 0x7c00); + return u16(s | 0x7c00) } - return u16(s | (e << 10) | (m >> 13)); + return u16(s | (e << 10) | (m >> 13)) } } @(link_name="__truncdfhf2") truncdfhf2 :: proc "c" (value: f64) -> u16 { - return truncsfhf2(f32(value)); + return truncsfhf2(f32(value)) } @(link_name="__gnu_h2f_ieee") gnu_h2f_ieee :: proc "c" (value: u16) -> f32 { - fp32 :: struct #raw_union { u: u32, f: f32 }; + fp32 :: struct #raw_union { u: u32, f: f32 } - v: fp32; - magic, inf_or_nan: fp32; - magic.u = u32((254 - 15) << 23); - inf_or_nan.u = u32((127 + 16) << 23); + v: fp32 + magic, inf_or_nan: fp32 + magic.u = u32((254 - 15) << 23) + inf_or_nan.u = u32((127 + 16) << 23) - v.u = u32(value & 0x7fff) << 13; - v.f *= magic.f; + v.u = u32(value & 0x7fff) << 13 + v.f *= magic.f if v.f >= inf_or_nan.f { - v.u |= 255 << 23; + v.u |= 255 << 23 } - v.u |= u32(value & 0x8000) << 16; - return v.f; + v.u |= u32(value & 0x8000) << 16 + return v.f } @(link_name="__gnu_f2h_ieee") gnu_f2h_ieee :: proc "c" (value: f32) -> u16 { - return truncsfhf2(value); + return truncsfhf2(value) } @(link_name="__extendhfsf2") extendhfsf2 :: proc "c" (value: u16) -> f32 { - return gnu_h2f_ieee(value); + return gnu_h2f_ieee(value) } @(link_name="__floattidf") floattidf :: proc(a: i128) -> f64 { - DBL_MANT_DIG :: 53; + DBL_MANT_DIG :: 53 if a == 0 { - return 0.0; - } - a := a; - N :: size_of(i128) * 8; - s := a >> (N-1); - a = (a ~ s) - s; - sd: = N - intrinsics.count_leading_zeros(a); // number of significant digits - e := u32(sd - 1); // exponent + return 0.0 + } + a := a + N :: size_of(i128) * 8 + s := a >> (N-1) + a = (a ~ s) - s + sd: = N - intrinsics.count_leading_zeros(a) // number of significant digits + e := u32(sd - 1) // exponent if sd > DBL_MANT_DIG { switch sd { case DBL_MANT_DIG + 1: - a <<= 1; + a <<= 1 case DBL_MANT_DIG + 2: // okay case: a = i128(u128(a) >> u128(sd - (DBL_MANT_DIG+2))) | - i128(u128(a) & (~u128(0) >> u128(N + DBL_MANT_DIG+2 - sd)) != 0); + i128(u128(a) & (~u128(0) >> u128(N + DBL_MANT_DIG+2 - sd)) != 0) }; - a |= i128((a & 4) != 0); - a += 1; - a >>= 2; + a |= i128((a & 4) != 0) + a += 1 + a >>= 2 if a & (1 << DBL_MANT_DIG) != 0 { - a >>= 1; - e += 1; + a >>= 1 + e += 1 } } else { - a <<= u128(DBL_MANT_DIG - sd); + a <<= u128(DBL_MANT_DIG - sd) } - fb: [2]u32; + fb: [2]u32 fb[0] = (u32(s) & 0x80000000) | // sign ((e + 1023) << 20) | // exponent - u32((u64(a) >> 32) & 0x000FFFFF); // mantissa-high - fb[1] = u32(a); // mantissa-low - return transmute(f64)fb; + u32((u64(a) >> 32) & 0x000FFFFF) // mantissa-high + fb[1] = u32(a) // mantissa-low + return transmute(f64)fb } @(link_name="__floattidf_unsigned") floattidf_unsigned :: proc(a: u128) -> f64 { - DBL_MANT_DIG :: 53; + DBL_MANT_DIG :: 53 if a == 0 { - return 0.0; + return 0.0 } - a := a; - N :: size_of(u128) * 8; - sd: = N - intrinsics.count_leading_zeros(a); // number of significant digits - e := u32(sd - 1); // exponent + a := a + N :: size_of(u128) * 8 + sd: = N - intrinsics.count_leading_zeros(a) // number of significant digits + e := u32(sd - 1) // exponent if sd > DBL_MANT_DIG { switch sd { case DBL_MANT_DIG + 1: - a <<= 1; + a <<= 1 case DBL_MANT_DIG + 2: // okay case: a = u128(u128(a) >> u128(sd - (DBL_MANT_DIG+2))) | - u128(u128(a) & (~u128(0) >> u128(N + DBL_MANT_DIG+2 - sd)) != 0); + u128(u128(a) & (~u128(0) >> u128(N + DBL_MANT_DIG+2 - sd)) != 0) }; - a |= u128((a & 4) != 0); - a += 1; - a >>= 2; + a |= u128((a & 4) != 0) + a += 1 + a >>= 2 if a & (1 << DBL_MANT_DIG) != 0 { - a >>= 1; - e += 1; + a >>= 1 + e += 1 } } else { - a <<= u128(DBL_MANT_DIG - sd); + a <<= u128(DBL_MANT_DIG - sd) } - fb: [2]u32; + fb: [2]u32 fb[0] = (0) | // sign ((e + 1023) << 20) | // exponent - u32((u64(a) >> 32) & 0x000FFFFF); // mantissa-high - fb[1] = u32(a); // mantissa-low - return transmute(f64)fb; + u32((u64(a) >> 32) & 0x000FFFFF) // mantissa-high + fb[1] = u32(a) // mantissa-low + return transmute(f64)fb } diff --git a/core/runtime/internal_windows.odin b/core/runtime/internal_windows.odin index cf7203aa4..4b932cd5f 100644 --- a/core/runtime/internal_windows.odin +++ b/core/runtime/internal_windows.odin @@ -4,86 +4,86 @@ import "core:intrinsics" @(link_name="__umodti3") umodti3 :: proc "c" (a, b: u128) -> u128 { - r: u128 = ---; - _ = udivmod128(a, b, &r); - return r; + r: u128 = --- + _ = udivmod128(a, b, &r) + return r } @(link_name="__udivmodti4") udivmodti4 :: proc "c" (a, b: u128, rem: ^u128) -> u128 { - return udivmod128(a, b, rem); + return udivmod128(a, b, rem) } @(link_name="__udivti3") udivti3 :: proc "c" (a, b: u128) -> u128 { - return udivmodti4(a, b, nil); + return udivmodti4(a, b, nil) } @(link_name="__modti3") modti3 :: proc "c" (a, b: i128) -> i128 { - s_a := a >> (128 - 1); - s_b := b >> (128 - 1); - an := (a ~ s_a) - s_a; - bn := (b ~ s_b) - s_b; - - r: u128 = ---; - _ = udivmod128(transmute(u128)an, transmute(u128)bn, &r); - return (transmute(i128)r ~ s_a) - s_a; + s_a := a >> (128 - 1) + s_b := b >> (128 - 1) + an := (a ~ s_a) - s_a + bn := (b ~ s_b) - s_b + + r: u128 = --- + _ = udivmod128(transmute(u128)an, transmute(u128)bn, &r) + return (transmute(i128)r ~ s_a) - s_a } @(link_name="__divmodti4") divmodti4 :: proc "c" (a, b: i128, rem: ^i128) -> i128 { - u := udivmod128(transmute(u128)a, transmute(u128)b, cast(^u128)rem); - return transmute(i128)u; + u := udivmod128(transmute(u128)a, transmute(u128)b, cast(^u128)rem) + return transmute(i128)u } @(link_name="__divti3") divti3 :: proc "c" (a, b: i128) -> i128 { - u := udivmodti4(transmute(u128)a, transmute(u128)b, nil); - return transmute(i128)u; + u := udivmodti4(transmute(u128)a, transmute(u128)b, nil) + return transmute(i128)u } @(link_name="__fixdfti") fixdfti :: proc(a: u64) -> i128 { - significandBits :: 52; - typeWidth :: (size_of(u64)*8); - exponentBits :: (typeWidth - significandBits - 1); - maxExponent :: ((1 << exponentBits) - 1); - exponentBias :: (maxExponent >> 1); - - implicitBit :: (u64(1) << significandBits); - significandMask :: (implicitBit - 1); - signBit :: (u64(1) << (significandBits + exponentBits)); - absMask :: (signBit - 1); - exponentMask :: (absMask ~ significandMask); + significandBits :: 52 + typeWidth :: (size_of(u64)*8) + exponentBits :: (typeWidth - significandBits - 1) + maxExponent :: ((1 << exponentBits) - 1) + exponentBias :: (maxExponent >> 1) + + implicitBit :: (u64(1) << significandBits) + significandMask :: (implicitBit - 1) + signBit :: (u64(1) << (significandBits + exponentBits)) + absMask :: (signBit - 1) + exponentMask :: (absMask ~ significandMask) // Break a into sign, exponent, significand - aRep := a; - aAbs := aRep & absMask; - sign := i128(-1 if aRep & signBit != 0 else 1); - exponent := (aAbs >> significandBits) - exponentBias; - significand := (aAbs & significandMask) | implicitBit; + aRep := a + aAbs := aRep & absMask + sign := i128(-1 if aRep & signBit != 0 else 1) + exponent := (aAbs >> significandBits) - exponentBias + significand := (aAbs & significandMask) | implicitBit // If exponent is negative, the result is zero. if exponent < 0 { - return 0; + return 0 } // If the value is too large for the integer type, saturate. if exponent >= size_of(i128) * 8 { - return max(i128) if sign == 1 else min(i128); + return max(i128) if sign == 1 else min(i128) } // If 0 <= exponent < significandBits, right shift to get the result. // Otherwise, shift left. if exponent < significandBits { - return sign * i128(significand >> (significandBits - exponent)); + return sign * i128(significand >> (significandBits - exponent)) } else { - return sign * (i128(significand) << (exponent - significandBits)); + return sign * (i128(significand) << (exponent - significandBits)) } } diff --git a/core/runtime/os_specific.odin b/core/runtime/os_specific.odin index 0f0e77dad..022d315d4 100644 --- a/core/runtime/os_specific.odin +++ b/core/runtime/os_specific.odin @@ -1,7 +1,7 @@ package runtime -_OS_Errno :: distinct int; +_OS_Errno :: distinct int os_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) { - return _os_write(data); + return _os_write(data) } diff --git a/core/runtime/os_specific_windows.odin b/core/runtime/os_specific_windows.odin index 1b66fda49..425071f85 100644 --- a/core/runtime/os_specific_windows.odin +++ b/core/runtime/os_specific_windows.odin @@ -26,59 +26,59 @@ foreign kernel32 { _os_write :: proc "contextless" (data: []byte) -> (n: int, err: _OS_Errno) #no_bounds_check { if len(data) == 0 { - return 0, 0; + return 0, 0 } - STD_ERROR_HANDLE :: ~u32(0) -12 + 1; - HANDLE_FLAG_INHERIT :: 0x00000001; - MAX_RW :: 1<<30; + STD_ERROR_HANDLE :: ~u32(0) -12 + 1 + HANDLE_FLAG_INHERIT :: 0x00000001 + MAX_RW :: 1<<30 - h := GetStdHandle(STD_ERROR_HANDLE); + h := GetStdHandle(STD_ERROR_HANDLE) when size_of(uintptr) == 8 { - SetHandleInformation(h, HANDLE_FLAG_INHERIT, 0); + SetHandleInformation(h, HANDLE_FLAG_INHERIT, 0) } - single_write_length: u32; - total_write: i64; - length := i64(len(data)); + single_write_length: u32 + total_write: i64 + length := i64(len(data)) for total_write < length { - remaining := length - total_write; - to_write := u32(min(i32(remaining), MAX_RW)); + remaining := length - total_write + to_write := u32(min(i32(remaining), MAX_RW)) - e := WriteFile(h, &data[total_write], to_write, &single_write_length, nil); + e := WriteFile(h, &data[total_write], to_write, &single_write_length, nil) if single_write_length <= 0 || !e { - err = _OS_Errno(GetLastError()); - n = int(total_write); - return; + err = _OS_Errno(GetLastError()) + n = int(total_write) + return } - total_write += i64(single_write_length); + total_write += i64(single_write_length) } - n = int(total_write); - return; + n = int(total_write) + return } heap_alloc :: proc "contextless" (size: int) -> rawptr { - HEAP_ZERO_MEMORY :: 0x00000008; - return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, uint(size)); + HEAP_ZERO_MEMORY :: 0x00000008 + return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, uint(size)) } heap_resize :: proc "contextless" (ptr: rawptr, new_size: int) -> rawptr { if new_size == 0 { - heap_free(ptr); - return nil; + heap_free(ptr) + return nil } if ptr == nil { - return heap_alloc(new_size); + return heap_alloc(new_size) } - HEAP_ZERO_MEMORY :: 0x00000008; - return HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ptr, uint(new_size)); + HEAP_ZERO_MEMORY :: 0x00000008 + return HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ptr, uint(new_size)) } heap_free :: proc "contextless" (ptr: rawptr) { if ptr == nil { - return; + return } - HeapFree(GetProcessHeap(), 0, ptr); + HeapFree(GetProcessHeap(), 0, ptr) } @@ -93,46 +93,46 @@ heap_free :: proc "contextless" (ptr: rawptr) { _windows_default_alloc_or_resize :: proc "contextless" (size, alignment: int, old_ptr: rawptr = nil) -> ([]byte, Allocator_Error) { if size == 0 { - _windows_default_free(old_ptr); - return nil, nil; + _windows_default_free(old_ptr) + return nil, nil } - a := max(alignment, align_of(rawptr)); - space := size + a - 1; + a := max(alignment, align_of(rawptr)) + space := size + a - 1 - allocated_mem: rawptr; + allocated_mem: rawptr if old_ptr != nil { - original_old_ptr := intrinsics.ptr_offset((^rawptr)(old_ptr), -1)^; - allocated_mem = heap_resize(original_old_ptr, space+size_of(rawptr)); + original_old_ptr := intrinsics.ptr_offset((^rawptr)(old_ptr), -1)^ + allocated_mem = heap_resize(original_old_ptr, space+size_of(rawptr)) } else { - allocated_mem = heap_alloc(space+size_of(rawptr)); + allocated_mem = heap_alloc(space+size_of(rawptr)) } - aligned_mem := rawptr(intrinsics.ptr_offset((^u8)(allocated_mem), size_of(rawptr))); + aligned_mem := rawptr(intrinsics.ptr_offset((^u8)(allocated_mem), size_of(rawptr))) - ptr := uintptr(aligned_mem); - aligned_ptr := (ptr - 1 + uintptr(a)) & -uintptr(a); - diff := int(aligned_ptr - ptr); + ptr := uintptr(aligned_mem) + aligned_ptr := (ptr - 1 + uintptr(a)) & -uintptr(a) + diff := int(aligned_ptr - ptr) if (size + diff) > space { - return nil, .Out_Of_Memory; + return nil, .Out_Of_Memory } - aligned_mem = rawptr(aligned_ptr); - intrinsics.ptr_offset((^rawptr)(aligned_mem), -1)^ = allocated_mem; + aligned_mem = rawptr(aligned_ptr) + intrinsics.ptr_offset((^rawptr)(aligned_mem), -1)^ = allocated_mem - return byte_slice(aligned_mem, size), nil; + return byte_slice(aligned_mem, size), nil } _windows_default_alloc :: proc "contextless" (size, alignment: int) -> ([]byte, Allocator_Error) { - return _windows_default_alloc_or_resize(size, alignment, nil); + return _windows_default_alloc_or_resize(size, alignment, nil) } _windows_default_free :: proc "contextless" (ptr: rawptr) { if ptr != nil { - heap_free(intrinsics.ptr_offset((^rawptr)(ptr), -1)^); + heap_free(intrinsics.ptr_offset((^rawptr)(ptr), -1)^) } } _windows_default_resize :: proc "contextless" (p: rawptr, old_size: int, new_size: int, new_alignment: int) -> ([]byte, Allocator_Error) { - return _windows_default_alloc_or_resize(new_size, new_alignment, p); + return _windows_default_alloc_or_resize(new_size, new_alignment, p) } diff --git a/core/runtime/print.odin b/core/runtime/print.odin index 5a3abcf2f..717a3018d 100644 --- a/core/runtime/print.odin +++ b/core/runtime/print.odin @@ -1,370 +1,370 @@ package runtime -_INTEGER_DIGITS :: "0123456789abcdefghijklmnopqrstuvwxyz"; +_INTEGER_DIGITS :: "0123456789abcdefghijklmnopqrstuvwxyz" encode_rune :: proc "contextless" (c: rune) -> ([4]u8, int) { - r := c; + r := c - buf: [4]u8; - i := u32(r); - mask :: u8(0x3f); + buf: [4]u8 + i := u32(r) + mask :: u8(0x3f) if i <= 1<<7-1 { - buf[0] = u8(r); - return buf, 1; + buf[0] = u8(r) + return buf, 1 } if i <= 1<<11-1 { - buf[0] = 0xc0 | u8(r>>6); - buf[1] = 0x80 | u8(r) & mask; - return buf, 2; + buf[0] = 0xc0 | u8(r>>6) + buf[1] = 0x80 | u8(r) & mask + return buf, 2 } // Invalid or Surrogate range if i > 0x0010ffff || (0xd800 <= i && i <= 0xdfff) { - r = 0xfffd; + r = 0xfffd } if i <= 1<<16-1 { - buf[0] = 0xe0 | u8(r>>12); - buf[1] = 0x80 | u8(r>>6) & mask; - buf[2] = 0x80 | u8(r) & mask; - return buf, 3; + buf[0] = 0xe0 | u8(r>>12) + buf[1] = 0x80 | u8(r>>6) & mask + buf[2] = 0x80 | u8(r) & mask + return buf, 3 } - buf[0] = 0xf0 | u8(r>>18); - buf[1] = 0x80 | u8(r>>12) & mask; - buf[2] = 0x80 | u8(r>>6) & mask; - buf[3] = 0x80 | u8(r) & mask; - return buf, 4; + buf[0] = 0xf0 | u8(r>>18) + buf[1] = 0x80 | u8(r>>12) & mask + buf[2] = 0x80 | u8(r>>6) & mask + buf[3] = 0x80 | u8(r) & mask + return buf, 4 } print_string :: proc "contextless" (str: string) -> (int, _OS_Errno) { - return os_write(transmute([]byte)str); + return os_write(transmute([]byte)str) } print_strings :: proc "contextless" (args: ..string) -> (n: int, err: _OS_Errno) { for str in args { - m: int; - m, err = os_write(transmute([]byte)str); - n += m; + m: int + m, err = os_write(transmute([]byte)str) + n += m if err != 0 { - break; + break } } - return; + return } print_byte :: proc "contextless" (b: byte) -> (int, _OS_Errno) { - return os_write([]byte{b}); + return os_write([]byte{b}) } print_encoded_rune :: proc "contextless" (r: rune) { - print_byte('\''); + print_byte('\'') switch r { - case '\a': print_string("\\a"); - case '\b': print_string("\\b"); - case '\e': print_string("\\e"); - case '\f': print_string("\\f"); - case '\n': print_string("\\n"); - case '\r': print_string("\\r"); - case '\t': print_string("\\t"); - case '\v': print_string("\\v"); + case '\a': print_string("\\a") + case '\b': print_string("\\b") + case '\e': print_string("\\e") + case '\f': print_string("\\f") + case '\n': print_string("\\n") + case '\r': print_string("\\r") + case '\t': print_string("\\t") + case '\v': print_string("\\v") case: if r <= 0 { - print_string("\\x00"); + print_string("\\x00") } else if r < 32 { - digits := _INTEGER_DIGITS; - n0, n1 := u8(r) >> 4, u8(r) & 0xf; - print_string("\\x"); - print_byte(digits[n0]); - print_byte(digits[n1]); + digits := _INTEGER_DIGITS + n0, n1 := u8(r) >> 4, u8(r) & 0xf + print_string("\\x") + print_byte(digits[n0]) + print_byte(digits[n1]) } else { - print_rune(r); + print_rune(r) } } - print_byte('\''); + print_byte('\'') } print_rune :: proc "contextless" (r: rune) -> (int, _OS_Errno) #no_bounds_check { - RUNE_SELF :: 0x80; + RUNE_SELF :: 0x80 if r < RUNE_SELF { - return print_byte(byte(r)); + return print_byte(byte(r)) } - b, n := encode_rune(r); - return os_write(b[:n]); + b, n := encode_rune(r) + return os_write(b[:n]) } print_u64 :: proc "contextless" (x: u64) #no_bounds_check { - digits := _INTEGER_DIGITS; + digits := _INTEGER_DIGITS - a: [129]byte; - i := len(a); - b := u64(10); - u := x; + a: [129]byte + i := len(a) + b := u64(10) + u := x for u >= b { - i -= 1; a[i] = digits[u % b]; - u /= b; + i -= 1; a[i] = digits[u % b] + u /= b } - i -= 1; a[i] = digits[u % b]; + i -= 1; a[i] = digits[u % b] - os_write(a[i:]); + os_write(a[i:]) } print_i64 :: proc "contextless" (x: i64) #no_bounds_check { - digits := _INTEGER_DIGITS; - b :: i64(10); + digits := _INTEGER_DIGITS + b :: i64(10) - u := x; - neg := u < 0; - u = abs(u); + u := x + neg := u < 0 + u = abs(u) - a: [129]byte; - i := len(a); + a: [129]byte + i := len(a) for u >= b { - i -= 1; a[i] = digits[u % b]; - u /= b; + i -= 1; a[i] = digits[u % b] + u /= b } - i -= 1; a[i] = digits[u % b]; + i -= 1; a[i] = digits[u % b] if neg { - i -= 1; a[i] = '-'; + i -= 1; a[i] = '-' } - os_write(a[i:]); + os_write(a[i:]) } print_caller_location :: proc "contextless" (using loc: Source_Code_Location) { - print_string(file_path); - print_byte('('); - print_u64(u64(line)); - print_byte(':'); - print_u64(u64(column)); - print_byte(')'); + print_string(file_path) + print_byte('(') + print_u64(u64(line)) + print_byte(':') + print_u64(u64(column)) + print_byte(')') } print_typeid :: proc "contextless" (id: typeid) { if id == nil { - print_string("nil"); + print_string("nil") } else { - ti := type_info_of(id); - print_type(ti); + ti := type_info_of(id) + print_type(ti) } } print_type :: proc "contextless" (ti: ^Type_Info) { if ti == nil { - print_string("nil"); - return; + print_string("nil") + return } switch info in ti.variant { case Type_Info_Named: - print_string(info.name); + print_string(info.name) case Type_Info_Integer: switch ti.id { - case int: print_string("int"); - case uint: print_string("uint"); - case uintptr: print_string("uintptr"); + case int: print_string("int") + case uint: print_string("uint") + case uintptr: print_string("uintptr") case: - print_byte('i' if info.signed else 'u'); - print_u64(u64(8*ti.size)); + print_byte('i' if info.signed else 'u') + print_u64(u64(8*ti.size)) } case Type_Info_Rune: - print_string("rune"); + print_string("rune") case Type_Info_Float: - print_byte('f'); - print_u64(u64(8*ti.size)); + print_byte('f') + print_u64(u64(8*ti.size)) case Type_Info_Complex: - print_string("complex"); - print_u64(u64(8*ti.size)); + print_string("complex") + print_u64(u64(8*ti.size)) case Type_Info_Quaternion: - print_string("quaternion"); - print_u64(u64(8*ti.size)); + print_string("quaternion") + print_u64(u64(8*ti.size)) case Type_Info_String: - print_string("string"); + print_string("string") case Type_Info_Boolean: switch ti.id { - case bool: print_string("bool"); + case bool: print_string("bool") case: - print_byte('b'); - print_u64(u64(8*ti.size)); + print_byte('b') + print_u64(u64(8*ti.size)) } case Type_Info_Any: - print_string("any"); + print_string("any") case Type_Info_Type_Id: - print_string("typeid"); + print_string("typeid") case Type_Info_Pointer: if info.elem == nil { - print_string("rawptr"); + print_string("rawptr") } else { - print_string("^"); - print_type(info.elem); + print_string("^") + print_type(info.elem) } case Type_Info_Multi_Pointer: - print_string("[^]"); - print_type(info.elem); + print_string("[^]") + print_type(info.elem) case Type_Info_Procedure: - print_string("proc"); + print_string("proc") if info.params == nil { - print_string("()"); + print_string("()") } else { - t := info.params.variant.(Type_Info_Tuple); - print_byte('('); + t := info.params.variant.(Type_Info_Tuple) + print_byte('(') for t, i in t.types { if i > 0 { print_string(", "); } - print_type(t); + print_type(t) } - print_string(")"); + print_string(")") } if info.results != nil { - print_string(" -> "); - print_type(info.results); + print_string(" -> ") + print_type(info.results) } case Type_Info_Tuple: - count := len(info.names); + count := len(info.names) if count != 1 { print_byte('('); } for name, i in info.names { if i > 0 { print_string(", "); } - t := info.types[i]; + t := info.types[i] if len(name) > 0 { - print_string(name); - print_string(": "); + print_string(name) + print_string(": ") } - print_type(t); + print_type(t) } if count != 1 { print_string(")"); } case Type_Info_Array: - print_byte('['); - print_u64(u64(info.count)); - print_byte(']'); - print_type(info.elem); + print_byte('[') + print_u64(u64(info.count)) + print_byte(']') + print_type(info.elem) case Type_Info_Enumerated_Array: - print_byte('['); - print_type(info.index); - print_byte(']'); - print_type(info.elem); + print_byte('[') + print_type(info.index) + print_byte(']') + print_type(info.elem) case Type_Info_Dynamic_Array: - print_string("[dynamic]"); - print_type(info.elem); + print_string("[dynamic]") + print_type(info.elem) case Type_Info_Slice: - print_string("[]"); - print_type(info.elem); + print_string("[]") + print_type(info.elem) case Type_Info_Map: - print_string("map["); - print_type(info.key); - print_byte(']'); - print_type(info.value); + print_string("map[") + print_type(info.key) + print_byte(']') + print_type(info.value) case Type_Info_Struct: switch info.soa_kind { case .None: // Ignore case .Fixed: - print_string("#soa["); - print_u64(u64(info.soa_len)); - print_byte(']'); - print_type(info.soa_base_type); - return; + print_string("#soa[") + print_u64(u64(info.soa_len)) + print_byte(']') + print_type(info.soa_base_type) + return case .Slice: - print_string("#soa[]"); - print_type(info.soa_base_type); - return; + print_string("#soa[]") + print_type(info.soa_base_type) + return case .Dynamic: - print_string("#soa[dynamic]"); - print_type(info.soa_base_type); - return; + print_string("#soa[dynamic]") + print_type(info.soa_base_type) + return } - print_string("struct "); + print_string("struct ") if info.is_packed { print_string("#packed "); } if info.is_raw_union { print_string("#raw_union "); } if info.custom_align { - print_string("#align "); - print_u64(u64(ti.align)); - print_byte(' '); + print_string("#align ") + print_u64(u64(ti.align)) + print_byte(' ') } - print_byte('{'); + print_byte('{') for name, i in info.names { if i > 0 { print_string(", "); } - print_string(name); - print_string(": "); - print_type(info.types[i]); + print_string(name) + print_string(": ") + print_type(info.types[i]) } - print_byte('}'); + print_byte('}') case Type_Info_Union: - print_string("union "); + print_string("union ") if info.custom_align { - print_string("#align "); - print_u64(u64(ti.align)); + print_string("#align ") + print_u64(u64(ti.align)) } if info.no_nil { - print_string("#no_nil "); + print_string("#no_nil ") } - print_byte('{'); + print_byte('{') for variant, i in info.variants { if i > 0 { print_string(", "); } - print_type(variant); + print_type(variant) } - print_string("}"); + print_string("}") case Type_Info_Enum: - print_string("enum "); - print_type(info.base); - print_string(" {"); + print_string("enum ") + print_type(info.base) + print_string(" {") for name, i in info.names { if i > 0 { print_string(", "); } - print_string(name); + print_string(name) } - print_string("}"); + print_string("}") case Type_Info_Bit_Set: - print_string("bit_set["); + print_string("bit_set[") #partial switch elem in type_info_base(info.elem).variant { case Type_Info_Enum: - print_type(info.elem); + print_type(info.elem) case Type_Info_Rune: - print_encoded_rune(rune(info.lower)); - print_string(".."); - print_encoded_rune(rune(info.upper)); + print_encoded_rune(rune(info.lower)) + print_string("..") + print_encoded_rune(rune(info.upper)) case: - print_i64(info.lower); - print_string(".."); - print_i64(info.upper); + print_i64(info.lower) + print_string("..") + print_i64(info.upper) } if info.underlying != nil { - print_string("; "); - print_type(info.underlying); + print_string("; ") + print_type(info.underlying) } - print_byte(']'); + print_byte(']') case Type_Info_Simd_Vector: - print_string("#simd["); - print_u64(u64(info.count)); - print_byte(']'); - print_type(info.elem); + print_string("#simd[") + print_u64(u64(info.count)) + print_byte(']') + print_type(info.elem) case Type_Info_Relative_Pointer: - print_string("#relative("); - print_type(info.base_integer); - print_string(") "); - print_type(info.pointer); + print_string("#relative(") + print_type(info.base_integer) + print_string(") ") + print_type(info.pointer) case Type_Info_Relative_Slice: - print_string("#relative("); - print_type(info.base_integer); - print_string(") "); - print_type(info.slice); + print_string("#relative(") + print_type(info.base_integer) + print_string(") ") + print_type(info.slice) } } diff --git a/core/runtime/procs_windows_amd64.odin b/core/runtime/procs_windows_amd64.odin index 511b1866d..4accfc0dc 100644 --- a/core/runtime/procs_windows_amd64.odin +++ b/core/runtime/procs_windows_amd64.odin @@ -8,14 +8,14 @@ foreign kernel32 { } windows_trap_array_bounds :: proc "contextless" () -> ! { - EXCEPTION_ARRAY_BOUNDS_EXCEEDED :: 0xC000008C; + EXCEPTION_ARRAY_BOUNDS_EXCEEDED :: 0xC000008C - RaiseException(EXCEPTION_ARRAY_BOUNDS_EXCEEDED, 0, 0, nil); + RaiseException(EXCEPTION_ARRAY_BOUNDS_EXCEEDED, 0, 0, nil) } windows_trap_type_assertion :: proc "contextless" () -> ! { - windows_trap_array_bounds(); + windows_trap_array_bounds() } // @private @@ -32,10 +32,10 @@ memcpy :: proc "c" (dst, src: rawptr, len: int) -> rawptr { RtlCopyMemory :: proc "c" (dst, src: rawptr, len: int) --- } if dst == nil || src == nil || len == 0 { - return dst; + return dst } - RtlCopyMemory(dst, src, len); - return dst; + RtlCopyMemory(dst, src, len) + return dst } // @(link_name="memmove") @@ -44,27 +44,27 @@ memmove :: proc "c" (dst, src: rawptr, len: int) -> rawptr { RtlMoveMemory :: proc "c" (dst, src: rawptr, len: int) --- } if dst == nil || src == nil || len == 0 { - return dst; + return dst } - RtlMoveMemory(dst, src, len); - return dst; + RtlMoveMemory(dst, src, len) + return dst } // @(link_name="memset") memset :: proc "c" (ptr: rawptr, val: i32, len: int) -> rawptr { if ptr == nil || len == 0 { - return ptr; + return ptr } - b := byte(val); + b := byte(val) - p_start := uintptr(ptr); - p_end := p_start + uintptr(max(len, 0)); + p_start := uintptr(ptr) + p_end := p_start + uintptr(max(len, 0)) for p := p_start; p < p_end; p += 1 { - (^byte)(p)^ = b; + (^byte)(p)^ = b } - return ptr; + return ptr } // @(link_name="memcmp") diff --git a/core/runtime/udivmod128.odin b/core/runtime/udivmod128.odin index 8850e0b24..ac0c20661 100644 --- a/core/runtime/udivmod128.odin +++ b/core/runtime/udivmod128.odin @@ -3,154 +3,154 @@ package runtime import "core:intrinsics" udivmod128 :: proc "c" (a, b: u128, rem: ^u128) -> u128 { - _ctz :: intrinsics.count_trailing_zeros; - _clz :: intrinsics.count_leading_zeros; + _ctz :: intrinsics.count_trailing_zeros + _clz :: intrinsics.count_leading_zeros - n := transmute([2]u64)a; - d := transmute([2]u64)b; - q, r: [2]u64 = ---, ---; - sr: u32 = 0; + n := transmute([2]u64)a + d := transmute([2]u64)b + q, r: [2]u64 = ---, --- + sr: u32 = 0 - low :: 1 when ODIN_ENDIAN == "big" else 0; - high :: 1 - low; - U64_BITS :: 8*size_of(u64); - U128_BITS :: 8*size_of(u128); + low :: 1 when ODIN_ENDIAN == "big" else 0 + high :: 1 - low + U64_BITS :: 8*size_of(u64) + U128_BITS :: 8*size_of(u128) // Special Cases if n[high] == 0 { if d[high] == 0 { if rem != nil { - res := n[low] % d[low]; - rem^ = u128(res); + res := n[low] % d[low] + rem^ = u128(res) } - return u128(n[low] / d[low]); + return u128(n[low] / d[low]) } if rem != nil { - rem^ = u128(n[low]); + rem^ = u128(n[low]) } - return 0; + return 0 } if d[low] == 0 { if d[high] == 0 { if rem != nil { - rem^ = u128(n[high] % d[low]); + rem^ = u128(n[high] % d[low]) } - return u128(n[high] / d[low]); + return u128(n[high] / d[low]) } if n[low] == 0 { if rem != nil { - r[high] = n[high] % d[high]; - r[low] = 0; - rem^ = transmute(u128)r; + r[high] = n[high] % d[high] + r[low] = 0 + rem^ = transmute(u128)r } - return u128(n[high] / d[high]); + return u128(n[high] / d[high]) } if d[high] & (d[high]-1) == 0 { if rem != nil { - r[low] = n[low]; - r[high] = n[high] & (d[high] - 1); - rem^ = transmute(u128)r; + r[low] = n[low] + r[high] = n[high] & (d[high] - 1) + rem^ = transmute(u128)r } - return u128(n[high] >> _ctz(d[high])); + return u128(n[high] >> _ctz(d[high])) } - sr = transmute(u32)(i32(_clz(d[high])) - i32(_clz(n[high]))); + sr = transmute(u32)(i32(_clz(d[high])) - i32(_clz(n[high]))) if sr > U64_BITS - 2 { if rem != nil { - rem^ = a; + rem^ = a } - return 0; + return 0 } - sr += 1; + sr += 1 - q[low] = 0; - q[high] = n[low] << u64(U64_BITS - sr); - r[high] = n[high] >> sr; - r[low] = (n[high] << (U64_BITS - sr)) | (n[low] >> sr); + q[low] = 0 + q[high] = n[low] << u64(U64_BITS - sr) + r[high] = n[high] >> sr + r[low] = (n[high] << (U64_BITS - sr)) | (n[low] >> sr) } else { if d[high] == 0 { if d[low] & (d[low] - 1) == 0 { if rem != nil { - rem^ = u128(n[low] & (d[low] - 1)); + rem^ = u128(n[low] & (d[low] - 1)) } if d[low] == 1 { - return a; + return a } - sr = u32(_ctz(d[low])); - q[high] = n[high] >> sr; - q[low] = (n[high] << (U64_BITS-sr)) | (n[low] >> sr); - return transmute(u128)q; + sr = u32(_ctz(d[low])) + q[high] = n[high] >> sr + q[low] = (n[high] << (U64_BITS-sr)) | (n[low] >> sr) + return transmute(u128)q } - sr = 1 + U64_BITS + u32(_clz(d[low])) - u32(_clz(n[high])); + sr = 1 + U64_BITS + u32(_clz(d[low])) - u32(_clz(n[high])) switch { case sr == U64_BITS: - q[low] = 0; - q[high] = n[low]; - r[high] = 0; - r[low] = n[high]; + q[low] = 0 + q[high] = n[low] + r[high] = 0 + r[low] = n[high] case sr < U64_BITS: - q[low] = 0; - q[high] = n[low] << (U64_BITS - sr); - r[high] = n[high] >> sr; - r[low] = (n[high] << (U64_BITS - sr)) | (n[low] >> sr); + q[low] = 0 + q[high] = n[low] << (U64_BITS - sr) + r[high] = n[high] >> sr + r[low] = (n[high] << (U64_BITS - sr)) | (n[low] >> sr) case: - q[low] = n[low] << (U128_BITS - sr); - q[high] = (n[high] << (U128_BITS - sr)) | (n[low] >> (sr - U64_BITS)); - r[high] = 0; - r[low] = n[high] >> (sr - U64_BITS); + q[low] = n[low] << (U128_BITS - sr) + q[high] = (n[high] << (U128_BITS - sr)) | (n[low] >> (sr - U64_BITS)) + r[high] = 0 + r[low] = n[high] >> (sr - U64_BITS) } } else { - sr = transmute(u32)(i32(_clz(d[high])) - i32(_clz(n[high]))); + sr = transmute(u32)(i32(_clz(d[high])) - i32(_clz(n[high]))) if sr > U64_BITS - 1 { if rem != nil { - rem^ = a; + rem^ = a } - return 0; + return 0 } - sr += 1; + sr += 1 - q[low] = 0; + q[low] = 0 if sr == U64_BITS { - q[high] = n[low]; - r[high] = 0; - r[low] = n[high]; + q[high] = n[low] + r[high] = 0 + r[low] = n[high] } else { - r[high] = n[high] >> sr; - r[low] = (n[high] << (U64_BITS - sr)) | (n[low] >> sr); - q[high] = n[low] << (U64_BITS - sr); + r[high] = n[high] >> sr + r[low] = (n[high] << (U64_BITS - sr)) | (n[low] >> sr) + q[high] = n[low] << (U64_BITS - sr) } } } - carry: u32 = 0; - r_all: u128 = ---; + carry: u32 = 0 + r_all: u128 = --- for ; sr > 0; sr -= 1 { - r[high] = (r[high] << 1) | (r[low] >> (U64_BITS - 1)); - r[low] = (r[low] << 1) | (q[high] >> (U64_BITS - 1)); - q[high] = (q[high] << 1) | (q[low] >> (U64_BITS - 1)); - q[low] = (q[low] << 1) | u64(carry); - - r_all = transmute(u128)r; - s := i128(b - r_all - 1) >> (U128_BITS - 1); - carry = u32(s & 1); - r_all -= b & transmute(u128)s; - r = transmute([2]u64)r_all; + r[high] = (r[high] << 1) | (r[low] >> (U64_BITS - 1)) + r[low] = (r[low] << 1) | (q[high] >> (U64_BITS - 1)) + q[high] = (q[high] << 1) | (q[low] >> (U64_BITS - 1)) + q[low] = (q[low] << 1) | u64(carry) + + r_all = transmute(u128)r + s := i128(b - r_all - 1) >> (U128_BITS - 1) + carry = u32(s & 1) + r_all -= b & transmute(u128)s + r = transmute([2]u64)r_all } - q_all := ((transmute(u128)q) << 1) | u128(carry); + q_all := ((transmute(u128)q) << 1) | u128(carry) if rem != nil { - rem^ = r_all; + rem^ = r_all } - return q_all; + return q_all } diff --git a/core/slice/map.odin b/core/slice/map.odin index d44b4b5b0..1c5512ceb 100644 --- a/core/slice/map.odin +++ b/core/slice/map.odin @@ -4,27 +4,27 @@ import "core:intrinsics" import "core:runtime" import "core:mem" -_ :: intrinsics; -_ :: runtime; -_ :: mem; +_ :: intrinsics +_ :: runtime +_ :: mem map_keys :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (keys: []K) { - keys = make(type_of(keys), len(m), allocator); - i := 0; + keys = make(type_of(keys), len(m), allocator) + i := 0 for key in m { - keys[i] = key; - i += 1; + keys[i] = key + i += 1 } - return; + return } map_values :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (values: []V) { - values = make(type_of(values), len(m), allocator); - i := 0; + values = make(type_of(values), len(m), allocator) + i := 0 for _, value in m { - values[i] = value; - i += 1; + values[i] = value + i += 1 } - return; + return } Map_Entry :: struct($Key, $Value: typeid) { @@ -40,42 +40,42 @@ Map_Entry_Info :: struct($Key, $Value: typeid) { map_entries :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (entries: []Map_Entry(K, V)) { - entries = make(type_of(entries), len(m), allocator); - i := 0; + entries = make(type_of(entries), len(m), allocator) + i := 0 for key, value in m { - entries[i].key = key; - entries[i].value = value; - i += 1; + entries[i].key = key + entries[i].value = value + i += 1 } - return; + return } map_entry_infos :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (entries: []Map_Entry_Info(K, V)) #no_bounds_check { - m := m; - rm := (^mem.Raw_Map)(&m); + m := m + rm := (^mem.Raw_Map)(&m) - info := runtime.type_info_base(type_info_of(M)).variant.(runtime.Type_Info_Map); - gs := runtime.type_info_base(info.generated_struct).variant.(runtime.Type_Info_Struct); - ed := runtime.type_info_base(gs.types[1]).variant.(runtime.Type_Info_Dynamic_Array); - entry_type := ed.elem.variant.(runtime.Type_Info_Struct); - key_offset := entry_type.offsets[2]; - value_offset := entry_type.offsets[3]; - entry_size := uintptr(ed.elem_size); + info := runtime.type_info_base(type_info_of(M)).variant.(runtime.Type_Info_Map) + gs := runtime.type_info_base(info.generated_struct).variant.(runtime.Type_Info_Struct) + ed := runtime.type_info_base(gs.types[1]).variant.(runtime.Type_Info_Dynamic_Array) + entry_type := ed.elem.variant.(runtime.Type_Info_Struct) + key_offset := entry_type.offsets[2] + value_offset := entry_type.offsets[3] + entry_size := uintptr(ed.elem_size) - entries = make(type_of(entries), rm.entries.len); + entries = make(type_of(entries), rm.entries.len) - data := uintptr(rm.entries.data); + data := uintptr(rm.entries.data) for i in 0..<rm.entries.len { - header := (^runtime.Map_Entry_Header)(data); + header := (^runtime.Map_Entry_Header)(data) - hash := header.hash; - key := (^K)(data + key_offset)^; - value := (^V)(data + value_offset)^; + hash := header.hash + key := (^K)(data + key_offset)^ + value := (^V)(data + value_offset)^ - entries[i] = {hash, key, value}; + entries[i] = {hash, key, value} - data += entry_size; + data += entry_size } - return; + return } diff --git a/core/slice/ptr.odin b/core/slice/ptr.odin index a63272818..0a3dea957 100644 --- a/core/slice/ptr.odin +++ b/core/slice/ptr.odin @@ -3,69 +3,69 @@ package slice import "core:mem" ptr_add :: proc(p: $P/^$T, x: int) -> ^T { - return (^T)(uintptr(p) + size_of(T)*x); + return (^T)(uintptr(p) + size_of(T)*x) } ptr_sub :: proc(p: $P/^$T, x: int) -> ^T { - return #force_inline ptr_add(p, -x); + return #force_inline ptr_add(p, -x) } ptr_swap_non_overlapping :: proc(x, y: rawptr, len: int) { if len <= 0 { - return; + return } if x == y { // Ignore pointers that are the same - return; + return } - Block :: distinct [4]u64; - BLOCK_SIZE :: size_of(Block); + Block :: distinct [4]u64 + BLOCK_SIZE :: size_of(Block) - i := 0; - t := &Block{}; + i := 0 + t := &Block{} for ; i + BLOCK_SIZE <= len; i += BLOCK_SIZE { - a := rawptr(uintptr(x) + uintptr(i)); - b := rawptr(uintptr(y) + uintptr(i)); + a := rawptr(uintptr(x) + uintptr(i)) + b := rawptr(uintptr(y) + uintptr(i)) - mem.copy(t, a, BLOCK_SIZE); - mem.copy(a, b, BLOCK_SIZE); - mem.copy(b, t, BLOCK_SIZE); + mem.copy(t, a, BLOCK_SIZE) + mem.copy(a, b, BLOCK_SIZE) + mem.copy(b, t, BLOCK_SIZE) } if i < len { - rem := len - i; + rem := len - i - a := rawptr(uintptr(x) + uintptr(i)); - b := rawptr(uintptr(y) + uintptr(i)); + a := rawptr(uintptr(x) + uintptr(i)) + b := rawptr(uintptr(y) + uintptr(i)) - mem.copy(t, a, rem); - mem.copy(a, b, rem); - mem.copy(b, t, rem); + mem.copy(t, a, rem) + mem.copy(a, b, rem) + mem.copy(b, t, rem) } } ptr_rotate :: proc(left: int, mid: ^$T, right: int) { when size_of(T) != 0 { - left, mid, right := left, mid, right; + left, mid, right := left, mid, right // TODO(bill): Optimization with a buffer for smaller ranges if left >= right { for { - ptr_swap_non_overlapping(ptr_sub(mid, right), mid, right); - mid = ptr_sub(mid, right); + ptr_swap_non_overlapping(ptr_sub(mid, right), mid, right) + mid = ptr_sub(mid, right) - left -= right; + left -= right if left < right { - break; + break } } } else { - ptr_swap_non_overlapping(ptr_sub(mid, left), mid, left); - mid = ptr_add(mid, left); + ptr_swap_non_overlapping(ptr_sub(mid, left), mid, left) + mid = ptr_add(mid, left) - right -= left; + right -= left if right < left { - break; + break } } } diff --git a/core/slice/slice.odin b/core/slice/slice.odin index 493afb8a2..0c266aa47 100644 --- a/core/slice/slice.odin +++ b/core/slice/slice.odin @@ -5,325 +5,325 @@ import "core:builtin" import "core:math/bits" import "core:mem" -_ :: intrinsics; -_ :: builtin; -_ :: bits; -_ :: mem; +_ :: intrinsics +_ :: builtin +_ :: bits +_ :: mem swap :: proc(array: $T/[]$E, a, b: int, loc := #caller_location) { when size_of(E) > 8 { - ptr_swap_non_overlapping(&array[a], &array[b], size_of(E)); + ptr_swap_non_overlapping(&array[a], &array[b], size_of(E)) } else { - array[a], array[b] = array[b], array[a]; + array[a], array[b] = array[b], array[a] } } reverse :: proc(array: $T/[]$E) { - n := len(array)/2; + n := len(array)/2 for i in 0..<n { - a, b := i, len(array)-i-1; - array[a], array[b] = array[b], array[a]; + a, b := i, len(array)-i-1 + array[a], array[b] = array[b], array[a] } } contains :: proc(array: $T/[]$E, value: E) -> bool where intrinsics.type_is_comparable(E) { - _, found := linear_search(array, value); - return found; + _, found := linear_search(array, value) + return found } linear_search :: proc(array: $A/[]$T, key: T) -> (index: int, found: bool) where intrinsics.type_is_comparable(T) #no_bounds_check { for x, i in array { if x == key { - return i, true; + return i, true } } - return -1, false; + return -1, false } linear_search_proc :: proc(array: $A/[]$T, f: proc(T) -> bool) -> (index: int, found: bool) #no_bounds_check { for x, i in array { if f(x) { - return i, true; + return i, true } } - return -1, false; + return -1, false } binary_search :: proc(array: $A/[]$T, key: T) -> (index: int, found: bool) where intrinsics.type_is_ordered(T) #no_bounds_check { - n := len(array); + n := len(array) switch n { case 0: - return -1, false; + return -1, false case 1: if array[0] == key { - return 0, true; + return 0, true } - return -1, false; + return -1, false } - lo, hi := 0, n-1; + lo, hi := 0, n-1 for array[hi] != array[lo] && key >= array[lo] && key <= array[hi] { when intrinsics.type_is_ordered_numeric(T) { // NOTE(bill): This is technically interpolation search - m := lo + int((key - array[lo]) * T(hi - lo) / (array[hi] - array[lo])); + m := lo + int((key - array[lo]) * T(hi - lo) / (array[hi] - array[lo])) } else { - m := lo + (hi - lo)/2; + m := lo + (hi - lo)/2 } switch { case array[m] < key: - lo = m + 1; + lo = m + 1 case key < array[m]: - hi = m - 1; + hi = m - 1 case: - return m, true; + return m, true } } if key == array[lo] { - return lo, true; + return lo, true } - return -1, false; + return -1, false } equal :: proc(a, b: $T/[]$E) -> bool where intrinsics.type_is_comparable(E) { if len(a) != len(b) { - return false; + return false } when intrinsics.type_is_simple_compare(E) { - return mem.compare_ptrs(raw_data(a), raw_data(b), len(a)*size_of(E)) == 0; + return mem.compare_ptrs(raw_data(a), raw_data(b), len(a)*size_of(E)) == 0 } else { for i in 0..<len(a) { if a[i] != b[i] { - return false; + return false } } - return true; + return true } } simple_equal :: proc(a, b: $T/[]$E) -> bool where intrinsics.type_is_simple_compare(E) { if len(a) != len(b) { - return false; + return false } - return mem.compare_ptrs(raw_data(a), raw_data(b), len(a)*size_of(E)) == 0; + return mem.compare_ptrs(raw_data(a), raw_data(b), len(a)*size_of(E)) == 0 } has_prefix :: proc(array: $T/[]$E, needle: E) -> bool where intrinsics.type_is_comparable(E) { - n := len(needle); + n := len(needle) if len(array) >= n { - return equal(array[:n], needle); + return equal(array[:n], needle) } - return false; + return false } has_suffix :: proc(array: $T/[]$E, needle: E) -> bool where intrinsics.type_is_comparable(E) { - array := array; - m, n := len(array), len(needle); + array := array + m, n := len(array), len(needle) if m >= n { - return equal(array[m-n:], needle); + return equal(array[m-n:], needle) } - return false; + return false } fill :: proc(array: $T/[]$E, value: E) { for _, i in array { - array[i] = value; + array[i] = value } } rotate_left :: proc(array: $T/[]$E, mid: int) { - n := len(array); - m := mid %% n; - k := n - m; - p := raw_data(array); - ptr_rotate(mid, ptr_add(p, mid), k); + n := len(array) + m := mid %% n + k := n - m + p := raw_data(array) + ptr_rotate(mid, ptr_add(p, mid), k) } rotate_right :: proc(array: $T/[]$E, k: int) { - rotate_left(array, -k); + rotate_left(array, -k) } swap_with_slice :: proc(a, b: $T/[]$E, loc := #caller_location) { - assert(len(a) == len(b), "miss matching slice lengths", loc); + assert(len(a) == len(b), "miss matching slice lengths", loc) - ptr_swap_non_overlapping(raw_data(a), raw_data(b), len(a)*size_of(E)); + ptr_swap_non_overlapping(raw_data(a), raw_data(b), len(a)*size_of(E)) } concatenate :: proc(a: []$T/[]$E, allocator := context.allocator) -> (res: T) { if len(a) == 0 { - return; + return } - n := 0; + n := 0 for s in a { - n += len(s); + n += len(s) } - res = make(T, n, allocator); - i := 0; + res = make(T, n, allocator) + i := 0 for s in a { - i += copy(res[i:], s); + i += copy(res[i:], s) } - return; + return } // copies slice into a new dynamic array clone :: proc(a: $T/[]$E, allocator := context.allocator) -> []E { - d := make([]E, len(a), allocator); - copy(d[:], a); - return d; + d := make([]E, len(a), allocator) + copy(d[:], a) + return d } // copies slice into a new dynamic array to_dynamic :: proc(a: $T/[]$E, allocator := context.allocator) -> [dynamic]E { - d := make([dynamic]E, len(a), allocator); - copy(d[:], a); - return d; + d := make([dynamic]E, len(a), allocator) + copy(d[:], a) + return d } // Converts slice into a dynamic array without cloning or allocating memory into_dynamic :: proc(a: $T/[]$E) -> [dynamic]E { - s := transmute(mem.Raw_Slice)a; + s := transmute(mem.Raw_Slice)a d := mem.Raw_Dynamic_Array{ data = s.data, len = 0, cap = s.len, allocator = mem.nil_allocator(), - }; - return transmute([dynamic]E)d; + } + return transmute([dynamic]E)d } length :: proc(a: $T/[]$E) -> int { - return len(a); + return len(a) } is_empty :: proc(a: $T/[]$E) -> bool { - return len(a) == 0; + return len(a) == 0 } split_at :: proc(array: $T/[]$E, index: int) -> (a, b: T) { - return array[:index], array[index:]; + return array[:index], array[index:] } split_first :: proc(array: $T/[]$E) -> (first: E, rest: T) { - return array[0], array[1:]; + return array[0], array[1:] } split_last :: proc(array: $T/[]$E) -> (rest: T, last: E) { - n := len(array)-1; - return array[:n], array[n]; + n := len(array)-1 + return array[:n], array[n] } first :: proc(array: $T/[]$E) -> E { - return array[0]; + return array[0] } last :: proc(array: $T/[]$E) -> E { - return array[len(array)-1]; + return array[len(array)-1] } first_ptr :: proc(array: $T/[]$E) -> ^E { if len(array) != 0 { - return &array[0]; + return &array[0] } - return nil; + return nil } last_ptr :: proc(array: $T/[]$E) -> ^E { if len(array) != 0 { - return &array[len(array)-1]; + return &array[len(array)-1] } - return nil; + return nil } get :: proc(array: $T/[]$E, index: int) -> (value: E, ok: bool) { if 0 <= index && index < len(array) { - value = array[index]; - ok = true; + value = array[index] + ok = true } - return; + return } get_ptr :: proc(array: $T/[]$E, index: int) -> (value: ^E, ok: bool) { if 0 <= index && index < len(array) { - value = &array[index]; - ok = true; + value = &array[index] + ok = true } - return; + return } as_ptr :: proc(array: $T/[]$E) -> ^E { - return raw_data(array); + return raw_data(array) } mapper :: proc(s: $S/[]$U, f: proc(U) -> $V, allocator := context.allocator) -> []V { - r := make([]V, len(s), allocator); + r := make([]V, len(s), allocator) for v, i in s { - r[i] = f(v); + r[i] = f(v) } - return r; + return r } reduce :: proc(s: $S/[]$U, initializer: $V, f: proc(V, U) -> V) -> V { - r := initializer; + r := initializer for v in s { - r = f(r, v); + r = f(r, v) } - return r; + return r } filter :: proc(s: $S/[]$U, f: proc(U) -> bool, allocator := context.allocator) -> S { - r := make([dynamic]U, 0, 0, allocator); + r := make([dynamic]U, 0, 0, allocator) for v in s { if f(v) { - append(&r, v); + append(&r, v) } } - return r[:]; + return r[:] } min :: proc(s: $S/[]$T) -> (res: T, ok: bool) where intrinsics.type_is_ordered(T) #optional_ok { if len(s) != 0 { - res = s[0]; - ok = true; + res = s[0] + ok = true for v in s[1:] { - res = builtin.min(res, v); + res = builtin.min(res, v) } } - return; + return } max :: proc(s: $S/[]$T) -> (res: T, ok: bool) where intrinsics.type_is_ordered(T) #optional_ok { if len(s) != 0 { - res = s[0]; - ok = true; + res = s[0] + ok = true for v in s[1:] { - res = builtin.max(res, v); + res = builtin.max(res, v) } } - return; + return } dot_product :: proc(a, b: $S/[]$T) -> T where intrinsics.type_is_numeric(T) { if len(a) != len(b) { - panic("slice.dot_product: slices of unequal length"); + panic("slice.dot_product: slices of unequal length") } - r: T; + r: T #no_bounds_check for _, i in a { - r += a[i] * b[i]; + r += a[i] * b[i] } - return r; + return r } diff --git a/core/slice/sort.odin b/core/slice/sort.odin index 01ab91452..0114fe18f 100644 --- a/core/slice/sort.odin +++ b/core/slice/sort.odin @@ -1,9 +1,9 @@ package slice import "core:intrinsics" -_ :: intrinsics; +_ :: intrinsics -ORD :: intrinsics.type_is_ordered; +ORD :: intrinsics.type_is_ordered Ordering :: enum { Less = -1, @@ -14,23 +14,23 @@ Ordering :: enum { cmp :: proc(a, b: $E) -> Ordering where ORD(E) { switch { case a < b: - return .Less; + return .Less case a > b: - return .Greater; + return .Greater } - return .Equal; + return .Equal } cmp_proc :: proc($E: typeid) -> (proc(E, E) -> Ordering) where ORD(E) { return proc(a, b: E) -> Ordering { switch { case a < b: - return .Less; + return .Less case a > b: - return .Greater; + return .Greater } - return .Equal; - }; + return .Equal + } } // sort sorts a slice @@ -38,7 +38,7 @@ cmp_proc :: proc($E: typeid) -> (proc(E, E) -> Ordering) where ORD(E) { sort :: proc(data: $T/[]$E) where ORD(E) { when size_of(E) != 0 { if n := len(data); n > 1 { - _quick_sort(data, 0, n, _max_depth(n)); + _quick_sort(data, 0, n, _max_depth(n)) } } } @@ -48,7 +48,7 @@ sort :: proc(data: $T/[]$E) where ORD(E) { sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) { when size_of(E) != 0 { if n := len(data); n > 1 { - _quick_sort_less(data, 0, n, _max_depth(n), less); + _quick_sort_less(data, 0, n, _max_depth(n), less) } } } @@ -56,7 +56,7 @@ sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) { sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) { when size_of(E) != 0 { if n := len(data); n > 1 { - _quick_sort_cmp(data, 0, n, _max_depth(n), cmp); + _quick_sort_cmp(data, 0, n, _max_depth(n), cmp) } } } @@ -64,124 +64,124 @@ sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) { is_sorted :: proc(array: $T/[]$E) -> bool where ORD(E) { for i := len(array)-1; i > 0; i -= 1 { if array[i] < array[i-1] { - return false; + return false } } - return true; + return true } is_sorted_by :: proc(array: $T/[]$E, less: proc(i, j: E) -> bool) -> bool { for i := len(array)-1; i > 0; i -= 1 { if less(array[i], array[i-1]) { - return false; + return false } } - return true; + return true } is_sorted_cmp :: proc(array: $T/[]$E, cmp: proc(i, j: E) -> Ordering) -> bool { for i := len(array)-1; i > 0; i -= 1 { if cmp(array[i], array[i-1]) == .Equal { - return false; + return false } } - return true; + return true } reverse_sort :: proc(data: $T/[]$E) where ORD(E) { sort_by(data, proc(i, j: E) -> bool { - return j < i; - }); + return j < i + }) } reverse_sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) where ORD(E) { - context._internal = rawptr(less); + context._internal = rawptr(less) sort_by(data, proc(i, j: E) -> bool { - k := (proc(i, j: E) -> bool)(context._internal); - return k(j, i); - }); + k := (proc(i, j: E) -> bool)(context._internal) + return k(j, i) + }) } reverse_sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) where ORD(E) { - context._internal = rawptr(cmp); + context._internal = rawptr(cmp) sort_by_cmp(data, proc(i, j: E) -> Ordering { - k := (proc(i, j: E) -> Ordering)(context._internal); - return k(j, i); - }); + k := (proc(i, j: E) -> Ordering)(context._internal) + return k(j, i) + }) } // TODO(bill): Should `sort_by_key` exist or is `sort_by` more than enough? sort_by_key :: proc(data: $T/[]$E, key: proc(E) -> $K) where ORD(K) { - context._internal = rawptr(key); + context._internal = rawptr(key) sort_by(data, proc(i, j: E) -> bool { - k := (proc(E) -> K)(context._internal); - return k(i) < k(j); - }); + k := (proc(E) -> K)(context._internal) + return k(i) < k(j) + }) } reverse_sort_by_key :: proc(data: $T/[]$E, key: proc(E) -> $K) where ORD(K) { - context._internal = rawptr(key); + context._internal = rawptr(key) sort_by(data, proc(i, j: E) -> bool { - k := (proc(E) -> K)(context._internal); - return k(j) < k(i); - }); + k := (proc(E) -> K)(context._internal) + return k(j) < k(i) + }) } is_sorted_by_key :: proc(array: $T/[]$E, key: proc(E) -> $K) -> bool where ORD(K) { for i := len(array)-1; i > 0; i -= 1 { if key(array[i]) < key(array[i-1]) { - return false; + return false } } - return true; + return true } @(private) _max_depth :: proc(n: int) -> int { // 2*ceil(log2(n+1)) - depth: int; + depth: int for i := n; i > 0; i >>= 1 { - depth += 1; + depth += 1 } - return depth * 2; + return depth * 2 } @(private) _quick_sort :: proc(data: $T/[]$E, a, b, max_depth: int) where ORD(E) { median3 :: proc(data: T, m1, m0, m2: int) { if data[m1] < data[m0] { - swap(data, m1, m0); + swap(data, m1, m0) } if data[m2] < data[m1] { - swap(data, m2, m1); + swap(data, m2, m1) if data[m1] < data[m0] { - swap(data, m1, m0); + swap(data, m1, m0) } } } do_pivot :: proc(data: T, lo, hi: int) -> (midlo, midhi: int) { - m := int(uint(lo+hi)>>1); + m := int(uint(lo+hi)>>1) if hi-lo > 40 { - s := (hi-lo)/8; - median3(data, lo, lo+s, lo+s*2); - median3(data, m, m-s, m+s); - median3(data, hi-1, hi-1-s, hi-1-s*2); + s := (hi-lo)/8 + median3(data, lo, lo+s, lo+s*2) + median3(data, m, m-s, m+s) + median3(data, hi-1, hi-1-s, hi-1-s*2) } - median3(data, lo, m, hi-1); + median3(data, lo, m, hi-1) - pivot := lo; - a, c := lo+1, hi-1; + pivot := lo + a, c := lo+1, hi-1 for ; a < c && data[a] < data[pivot]; a += 1 { } - b := a; + b := a for { for ; b < c && !(data[pivot] < data[b]); b += 1 { // data[b] <= pivot @@ -189,33 +189,33 @@ _quick_sort :: proc(data: $T/[]$E, a, b, max_depth: int) where ORD(E) { for ; b < c && data[pivot] < data[c-1]; c -=1 { // data[c-1] > pivot } if b >= c { - break; + break } - swap(data, b, c-1); - b += 1; - c -= 1; + swap(data, b, c-1) + b += 1 + c -= 1 } - protect := hi-c < 5; + protect := hi-c < 5 if !protect && hi-c < (hi-lo)/4 { - dups := 0; + dups := 0 if !(data[pivot] < data[hi-1]) { - swap(data, c, hi-1); - c += 1; - dups += 1; + swap(data, c, hi-1) + c += 1 + dups += 1 } if !(data[b-1] < data[pivot]) { - b -= 1; - dups += 1; + b -= 1 + dups += 1 } if !(data[m] < data[pivot]) { - swap(data, m, b-1); - b -= 1; - dups += 1; + swap(data, m, b-1) + b -= 1 + dups += 1 } - protect = dups > 1; + protect = dups > 1 } if protect { for { @@ -224,43 +224,43 @@ _quick_sort :: proc(data: $T/[]$E, a, b, max_depth: int) where ORD(E) { for ; a < b && data[a] < data[pivot]; a += 1 { } if a >= b { - break; + break } - swap(data, a, b-1); - a += 1; - b -= 1; + swap(data, a, b-1) + a += 1 + b -= 1 } } - swap(data, pivot, b-1); - return b-1, c; + swap(data, pivot, b-1) + return b-1, c } - a, b, max_depth := a, b, max_depth; + a, b, max_depth := a, b, max_depth if b-a > 12 { // only use shell sort for lengths <= 12 if max_depth == 0 { - _heap_sort(data, a, b); - return; + _heap_sort(data, a, b) + return } - max_depth -= 1; - mlo, mhi := do_pivot(data, a, b); + max_depth -= 1 + mlo, mhi := do_pivot(data, a, b) if mlo-a < b-mhi { - _quick_sort(data, a, mlo, max_depth); - a = mhi; + _quick_sort(data, a, mlo, max_depth) + a = mhi } else { - _quick_sort(data, mhi, b, max_depth); - b = mlo; + _quick_sort(data, mhi, b, max_depth) + b = mlo } } if b-a > 1 { // Shell short with gap 6 for i in a+6..<b { if data[i] < data[i-6] { - swap(data, i, i-6); + swap(data, i, i-6) } } - _insertion_sort(data, a, b); + _insertion_sort(data, a, b) } } @@ -268,7 +268,7 @@ _quick_sort :: proc(data: $T/[]$E, a, b, max_depth: int) where ORD(E) { _insertion_sort :: proc(data: $T/[]$E, a, b: int) where ORD(E) { for i in a+1..<b { for j := i; j > a && data[j] < data[j-1]; j -= 1 { - swap(data, j, j-1); + swap(data, j, j-1) } } } @@ -276,33 +276,33 @@ _insertion_sort :: proc(data: $T/[]$E, a, b: int) where ORD(E) { @(private) _heap_sort :: proc(data: $T/[]$E, a, b: int) where ORD(E) { sift_down :: proc(data: T, lo, hi, first: int) { - root := lo; + root := lo for { - child := 2*root + 1; + child := 2*root + 1 if child >= hi { - break; + break } if child+1 < hi && data[first+child] < data[first+child+1] { - child += 1; + child += 1 } if !(data[first+root] < data[first+child]) { - return; + return } - swap(data, first+root, first+child); - root = child; + swap(data, first+root, first+child) + root = child } } - first, lo, hi := a, 0, b-a; + first, lo, hi := a, 0, b-a for i := (hi-1)/2; i >= 0; i -= 1 { - sift_down(data, i, hi, first); + sift_down(data, i, hi, first) } for i := hi-1; i >= 0; i -= 1 { - swap(data, first, first+i); - sift_down(data, lo, i, first); + swap(data, first, first+i) + sift_down(data, lo, i, first) } } @@ -315,32 +315,32 @@ _heap_sort :: proc(data: $T/[]$E, a, b: int) where ORD(E) { _quick_sort_less :: proc(data: $T/[]$E, a, b, max_depth: int, less: proc(i, j: E) -> bool) { median3 :: proc(data: T, m1, m0, m2: int, less: proc(i, j: E) -> bool) { if less(data[m1], data[m0]) { - swap(data, m1, m0); + swap(data, m1, m0) } if less(data[m2], data[m1]) { - swap(data, m2, m1); + swap(data, m2, m1) if less(data[m1], data[m0]) { - swap(data, m1, m0); + swap(data, m1, m0) } } } do_pivot :: proc(data: T, lo, hi: int, less: proc(i, j: E) -> bool) -> (midlo, midhi: int) { - m := int(uint(lo+hi)>>1); + m := int(uint(lo+hi)>>1) if hi-lo > 40 { - s := (hi-lo)/8; - median3(data, lo, lo+s, lo+s*2, less); - median3(data, m, m-s, m+s, less); - median3(data, hi-1, hi-1-s, hi-1-s*2, less); + s := (hi-lo)/8 + median3(data, lo, lo+s, lo+s*2, less) + median3(data, m, m-s, m+s, less) + median3(data, hi-1, hi-1-s, hi-1-s*2, less) } - median3(data, lo, m, hi-1, less); + median3(data, lo, m, hi-1, less) - pivot := lo; - a, c := lo+1, hi-1; + pivot := lo + a, c := lo+1, hi-1 for ; a < c && less(data[a], data[pivot]); a += 1 { } - b := a; + b := a for { for ; b < c && !less(data[pivot], data[b]); b += 1 { // data[b] <= pivot @@ -348,33 +348,33 @@ _quick_sort_less :: proc(data: $T/[]$E, a, b, max_depth: int, less: proc(i, j: E for ; b < c && less(data[pivot], data[c-1]); c -=1 { // data[c-1] > pivot } if b >= c { - break; + break } - swap(data, b, c-1); - b += 1; - c -= 1; + swap(data, b, c-1) + b += 1 + c -= 1 } - protect := hi-c < 5; + protect := hi-c < 5 if !protect && hi-c < (hi-lo)/4 { - dups := 0; + dups := 0 if !less(data[pivot], data[hi-1]) { - swap(data, c, hi-1); - c += 1; - dups += 1; + swap(data, c, hi-1) + c += 1 + dups += 1 } if !less(data[b-1], data[pivot]) { - b -= 1; - dups += 1; + b -= 1 + dups += 1 } if !less(data[m], data[pivot]) { - swap(data, m, b-1); - b -= 1; - dups += 1; + swap(data, m, b-1) + b -= 1 + dups += 1 } - protect = dups > 1; + protect = dups > 1 } if protect { for { @@ -383,43 +383,43 @@ _quick_sort_less :: proc(data: $T/[]$E, a, b, max_depth: int, less: proc(i, j: E for ; a < b && less(data[a], data[pivot]); a += 1 { } if a >= b { - break; + break } - swap(data, a, b-1); - a += 1; - b -= 1; + swap(data, a, b-1) + a += 1 + b -= 1 } } - swap(data, pivot, b-1); - return b-1, c; + swap(data, pivot, b-1) + return b-1, c } - a, b, max_depth := a, b, max_depth; + a, b, max_depth := a, b, max_depth if b-a > 12 { // only use shell sort for lengths <= 12 if max_depth == 0 { - _heap_sort_less(data, a, b, less); - return; + _heap_sort_less(data, a, b, less) + return } - max_depth -= 1; - mlo, mhi := do_pivot(data, a, b, less); + max_depth -= 1 + mlo, mhi := do_pivot(data, a, b, less) if mlo-a < b-mhi { - _quick_sort_less(data, a, mlo, max_depth, less); - a = mhi; + _quick_sort_less(data, a, mlo, max_depth, less) + a = mhi } else { - _quick_sort_less(data, mhi, b, max_depth, less); - b = mlo; + _quick_sort_less(data, mhi, b, max_depth, less) + b = mlo } } if b-a > 1 { // Shell short with gap 6 for i in a+6..<b { if less(data[i], data[i-6]) { - swap(data, i, i-6); + swap(data, i, i-6) } } - _insertion_sort_less(data, a, b, less); + _insertion_sort_less(data, a, b, less) } } @@ -427,7 +427,7 @@ _quick_sort_less :: proc(data: $T/[]$E, a, b, max_depth: int, less: proc(i, j: E _insertion_sort_less :: proc(data: $T/[]$E, a, b: int, less: proc(i, j: E) -> bool) { for i in a+1..<b { for j := i; j > a && less(data[j], data[j-1]); j -= 1 { - swap(data, j, j-1); + swap(data, j, j-1) } } } @@ -435,33 +435,33 @@ _insertion_sort_less :: proc(data: $T/[]$E, a, b: int, less: proc(i, j: E) -> bo @(private) _heap_sort_less :: proc(data: $T/[]$E, a, b: int, less: proc(i, j: E) -> bool) { sift_down :: proc(data: T, lo, hi, first: int, less: proc(i, j: E) -> bool) { - root := lo; + root := lo for { - child := 2*root + 1; + child := 2*root + 1 if child >= hi { - break; + break } if child+1 < hi && less(data[first+child], data[first+child+1]) { - child += 1; + child += 1 } if !less(data[first+root], data[first+child]) { - return; + return } - swap(data, first+root, first+child); - root = child; + swap(data, first+root, first+child) + root = child } } - first, lo, hi := a, 0, b-a; + first, lo, hi := a, 0, b-a for i := (hi-1)/2; i >= 0; i -= 1 { - sift_down(data, i, hi, first, less); + sift_down(data, i, hi, first, less) } for i := hi-1; i >= 0; i -= 1 { - swap(data, first, first+i); - sift_down(data, lo, i, first, less); + swap(data, first, first+i) + sift_down(data, lo, i, first, less) } } @@ -474,32 +474,32 @@ _heap_sort_less :: proc(data: $T/[]$E, a, b: int, less: proc(i, j: E) -> bool) { _quick_sort_cmp :: proc(data: $T/[]$E, a, b, max_depth: int, cmp: proc(i, j: E) -> Ordering) { median3 :: proc(data: T, m1, m0, m2: int, cmp: proc(i, j: E) -> Ordering) { if cmp(data[m1], data[m0]) == .Less { - swap(data, m1, m0); + swap(data, m1, m0) } if cmp(data[m2], data[m1]) == .Less { - swap(data, m2, m1); + swap(data, m2, m1) if cmp(data[m1], data[m0]) == .Less { - swap(data, m1, m0); + swap(data, m1, m0) } } } do_pivot :: proc(data: T, lo, hi: int, cmp: proc(i, j: E) -> Ordering) -> (midlo, midhi: int) { - m := int(uint(lo+hi)>>1); + m := int(uint(lo+hi)>>1) if hi-lo > 40 { - s := (hi-lo)/8; - median3(data, lo, lo+s, lo+s*2, cmp); - median3(data, m, m-s, m+s, cmp); - median3(data, hi-1, hi-1-s, hi-1-s*2, cmp); + s := (hi-lo)/8 + median3(data, lo, lo+s, lo+s*2, cmp) + median3(data, m, m-s, m+s, cmp) + median3(data, hi-1, hi-1-s, hi-1-s*2, cmp) } - median3(data, lo, m, hi-1, cmp); + median3(data, lo, m, hi-1, cmp) - pivot := lo; - a, c := lo+1, hi-1; + pivot := lo + a, c := lo+1, hi-1 for ; a < c && cmp(data[a], data[pivot]) == .Less; a += 1 { } - b := a; + b := a for { for ; b < c && cmp(data[pivot], data[b]) >= .Equal; b += 1 { // data[b] <= pivot @@ -507,33 +507,33 @@ _quick_sort_cmp :: proc(data: $T/[]$E, a, b, max_depth: int, cmp: proc(i, j: E) for ; b < c && cmp(data[pivot], data[c-1]) == .Less; c -=1 { // data[c-1] > pivot } if b >= c { - break; + break } - swap(data, b, c-1); - b += 1; - c -= 1; + swap(data, b, c-1) + b += 1 + c -= 1 } - protect := hi-c < 5; + protect := hi-c < 5 if !protect && hi-c < (hi-lo)/4 { - dups := 0; + dups := 0 if cmp(data[pivot], data[hi-1]) != .Less { - swap(data, c, hi-1); - c += 1; - dups += 1; + swap(data, c, hi-1) + c += 1 + dups += 1 } if cmp(data[b-1], data[pivot]) != .Less { - b -= 1; - dups += 1; + b -= 1 + dups += 1 } if cmp(data[m], data[pivot]) != .Less { - swap(data, m, b-1); - b -= 1; - dups += 1; + swap(data, m, b-1) + b -= 1 + dups += 1 } - protect = dups > 1; + protect = dups > 1 } if protect { for { @@ -542,43 +542,43 @@ _quick_sort_cmp :: proc(data: $T/[]$E, a, b, max_depth: int, cmp: proc(i, j: E) for ; a < b && cmp(data[a], data[pivot]) == .Less; a += 1 { } if a >= b { - break; + break } - swap(data, a, b-1); - a += 1; - b -= 1; + swap(data, a, b-1) + a += 1 + b -= 1 } } - swap(data, pivot, b-1); - return b-1, c; + swap(data, pivot, b-1) + return b-1, c } - a, b, max_depth := a, b, max_depth; + a, b, max_depth := a, b, max_depth if b-a > 12 { // only use shell sort for lengths <= 12 if max_depth == 0 { - _heap_sort_cmp(data, a, b, cmp); - return; + _heap_sort_cmp(data, a, b, cmp) + return } - max_depth -= 1; - mlo, mhi := do_pivot(data, a, b, cmp); + max_depth -= 1 + mlo, mhi := do_pivot(data, a, b, cmp) if mlo-a < b-mhi { - _quick_sort_cmp(data, a, mlo, max_depth, cmp); - a = mhi; + _quick_sort_cmp(data, a, mlo, max_depth, cmp) + a = mhi } else { - _quick_sort_cmp(data, mhi, b, max_depth, cmp); - b = mlo; + _quick_sort_cmp(data, mhi, b, max_depth, cmp) + b = mlo } } if b-a > 1 { // Shell short with gap 6 for i in a+6..<b { if cmp(data[i], data[i-6]) == .Less { - swap(data, i, i-6); + swap(data, i, i-6) } } - _insertion_sort_cmp(data, a, b, cmp); + _insertion_sort_cmp(data, a, b, cmp) } } @@ -586,7 +586,7 @@ _quick_sort_cmp :: proc(data: $T/[]$E, a, b, max_depth: int, cmp: proc(i, j: E) _insertion_sort_cmp :: proc(data: $T/[]$E, a, b: int, cmp: proc(i, j: E) -> Ordering) { for i in a+1..<b { for j := i; j > a && cmp(data[j], data[j-1]) == .Less; j -= 1 { - swap(data, j, j-1); + swap(data, j, j-1) } } } @@ -594,33 +594,33 @@ _insertion_sort_cmp :: proc(data: $T/[]$E, a, b: int, cmp: proc(i, j: E) -> Orde @(private) _heap_sort_cmp :: proc(data: $T/[]$E, a, b: int, cmp: proc(i, j: E) -> Ordering) { sift_down :: proc(data: T, lo, hi, first: int, cmp: proc(i, j: E) -> Ordering) { - root := lo; + root := lo for { - child := 2*root + 1; + child := 2*root + 1 if child >= hi { - break; + break } if child+1 < hi && cmp(data[first+child], data[first+child+1]) == .Less { - child += 1; + child += 1 } if cmp(data[first+root], data[first+child]) >= .Equal { - return; + return } - swap(data, first+root, first+child); - root = child; + swap(data, first+root, first+child) + root = child } } - first, lo, hi := a, 0, b-a; + first, lo, hi := a, 0, b-a for i := (hi-1)/2; i >= 0; i -= 1 { - sift_down(data, i, hi, first, cmp); + sift_down(data, i, hi, first, cmp) } for i := hi-1; i >= 0; i -= 1 { - swap(data, first, first+i); - sift_down(data, lo, i, first, cmp); + swap(data, first, first+i) + sift_down(data, lo, i, first, cmp) } } diff --git a/core/sort/sort.odin b/core/sort/sort.odin index 7eb4fb89a..3ece4cac4 100644 --- a/core/sort/sort.odin +++ b/core/sort/sort.odin @@ -4,8 +4,8 @@ import "core:mem" import _slice "core:slice" import "core:intrinsics" -_ :: intrinsics; -ORD :: intrinsics.type_is_ordered; +_ :: intrinsics +ORD :: intrinsics.type_is_ordered Interface :: struct { len: proc(it: Interface) -> int, @@ -18,21 +18,21 @@ Interface :: struct { // This sort is not guaranteed to be stable sort :: proc(it: Interface) { max_depth :: proc(n: int) -> int { // 2*ceil(log2(n+1)) - depth: int; + depth: int for i := n; i > 0; i >>= 1 { - depth += 1; + depth += 1 } - return depth * 2; + return depth * 2 } - n := it->len(); - _quick_sort(it, 0, n, max_depth(n)); + n := it->len() + _quick_sort(it, 0, n, max_depth(n)) } @(deprecated="use slice.sort") slice :: proc(array: $T/[]$E) where ORD(E) { - _slice.sort(array); + _slice.sort(array) // s := array; // sort(slice_interface(&s)); } @@ -41,18 +41,18 @@ slice_interface :: proc(s: ^$T/[]$E) -> Interface where ORD(E) { return Interface{ collection = rawptr(s), len = proc(it: Interface) -> int { - s := (^T)(it.collection); - return len(s^); + s := (^T)(it.collection) + return len(s^) }, less = proc(it: Interface, i, j: int) -> bool { - s := (^T)(it.collection); - return s[i] < s[j]; + s := (^T)(it.collection) + return s[i] < s[j] }, swap = proc(it: Interface, i, j: int) { - s := (^T)(it.collection); - s[i], s[j] = s[j], s[i]; + s := (^T)(it.collection) + s[i], s[j] = s[j], s[i] }, - }; + } } reverse_interface :: proc(it: ^Interface) -> Interface { @@ -60,28 +60,28 @@ reverse_interface :: proc(it: ^Interface) -> Interface { collection = it, len = proc(rit: Interface) -> int { - it := (^Interface)(rit.collection); - return it.len(it^); + it := (^Interface)(rit.collection) + return it.len(it^) }, less = proc(rit: Interface, i, j: int) -> bool { - it := (^Interface)(rit.collection); - return it.less(it^, j, i); // reverse parameters + it := (^Interface)(rit.collection) + return it.less(it^, j, i) // reverse parameters }, swap = proc(rit: Interface, i, j: int) { - it := (^Interface)(rit.collection); - it.swap(it^, i, j); + it := (^Interface)(rit.collection) + it.swap(it^, i, j) }, - }; + } } reverse_sort :: proc(it: Interface) { - it := it; - sort(reverse_interface(&it)); + it := it + sort(reverse_interface(&it)) } @(deprecated="use slice.reverse") reverse_slice :: proc(array: $T/[]$E) where ORD(E) { - _slice.reverse(array); + _slice.reverse(array) /* s := array; sort(Interface{ @@ -105,36 +105,36 @@ reverse_slice :: proc(array: $T/[]$E) where ORD(E) { is_sorted :: proc(it: Interface) -> bool { - n := it->len(); + n := it->len() for i := n-1; i > 0; i -= 1 { if it->less(i, i-1) { - return false; + return false } } - return true; + return true } swap_range :: proc(it: Interface, a, b, n: int) { for i in 0..<n { - it->swap(a+i, b+i); + it->swap(a+i, b+i) } } rotate :: proc(it: Interface, a, m, b: int) { - i := m - a; - j := b - m; + i := m - a + j := b - m for i != j { if i > j { - swap_range(it, m-i, m, j); - i -= j; + swap_range(it, m-i, m, j) + i -= j } else { - swap_range(it, m-i, m+j-1, i); - j -= 1; + swap_range(it, m-i, m+j-1, i) + j -= 1 } } - swap_range(it, m-i, m, i); + swap_range(it, m-i, m, i) } @@ -143,32 +143,32 @@ rotate :: proc(it: Interface, a, m, b: int) { _quick_sort :: proc(it: Interface, a, b, max_depth: int) { median3 :: proc(it: Interface, m1, m0, m2: int) { if it->less(m1, m0) { - it->swap(m1, m0); + it->swap(m1, m0) } if it->less(m2, m1) { - it->swap(m2, m1); + it->swap(m2, m1) if it->less(m1, m0) { - it->swap(m1, m0); + it->swap(m1, m0) } } } do_pivot :: proc(it: Interface, lo, hi: int) -> (midlo, midhi: int) { - m := int(uint(lo+hi)>>1); + m := int(uint(lo+hi)>>1) if hi-lo > 40 { - s := (hi-lo)/8; - median3(it, lo, lo+s, lo+s*2); - median3(it, m, m-s, m+s); - median3(it, hi-1, hi-1-s, hi-1-s*2); + s := (hi-lo)/8 + median3(it, lo, lo+s, lo+s*2) + median3(it, m, m-s, m+s) + median3(it, hi-1, hi-1-s, hi-1-s*2) } - median3(it, lo, m, hi-1); + median3(it, lo, m, hi-1) - pivot := lo; - a, c := lo+1, hi-1; + pivot := lo + a, c := lo+1, hi-1 for ; a < c && it->less(a, pivot); a += 1 { } - b := a; + b := a for { for ; b < c && !it->less(pivot, b); b += 1 { // data[b] <= pivot @@ -176,33 +176,33 @@ _quick_sort :: proc(it: Interface, a, b, max_depth: int) { for ; b < c && it->less(pivot, c-1); c -=1 { // data[c-1] > pivot } if b >= c { - break; + break } - it->swap(b, c-1); - b += 1; - c -= 1; + it->swap(b, c-1) + b += 1 + c -= 1 } - protect := hi-c < 5; + protect := hi-c < 5 if !protect && hi-c < (hi-lo)/4 { - dups := 0; + dups := 0 if !it->less(pivot, hi-1) { - it->swap(c, hi-1); - c += 1; - dups += 1; + it->swap(c, hi-1) + c += 1 + dups += 1 } if !it->less(b-1, pivot) { - b -= 1; - dups += 1; + b -= 1 + dups += 1 } if !it->less(m, pivot) { - it->swap(m, b-1); - b -= 1; - dups += 1; + it->swap(m, b-1) + b -= 1 + dups += 1 } - protect = dups > 1; + protect = dups > 1 } if protect { for { @@ -211,76 +211,76 @@ _quick_sort :: proc(it: Interface, a, b, max_depth: int) { for ; a < b && it->less(a, pivot); a += 1 { } if a >= b { - break; + break } - it->swap(a, b-1); - a += 1; - b -= 1; + it->swap(a, b-1) + a += 1 + b -= 1 } } - it->swap(pivot, b-1); - return b-1, c; + it->swap(pivot, b-1) + return b-1, c } heap_sort :: proc(it: Interface, a, b: int) { sift_down :: proc(it: Interface, lo, hi, first: int) { - root := lo; + root := lo for { - child := 2*root + 1; + child := 2*root + 1 if child >= hi { - break; + break } if child+1 < hi && it->less(first+child, first+child+1) { - child += 1; + child += 1 } if !it->less(first+root, first+child) { - return; + return } - it->swap(first+root, first+child); - root = child; + it->swap(first+root, first+child) + root = child } } - first, lo, hi := a, 0, b-a; + first, lo, hi := a, 0, b-a for i := (hi-1)/2; i >= 0; i -= 1 { - sift_down(it, i, hi, first); + sift_down(it, i, hi, first) } for i := hi-1; i >= 0; i -= 1 { - it->swap(first, first+i); - sift_down(it, lo, i, first); + it->swap(first, first+i) + sift_down(it, lo, i, first) } } - a, b, max_depth := a, b, max_depth; + a, b, max_depth := a, b, max_depth if b-a > 12 { // only use shell sort for lengths <= 12 if max_depth == 0 { - heap_sort(it, a, b); - return; + heap_sort(it, a, b) + return } - max_depth -= 1; - mlo, mhi := do_pivot(it, a, b); + max_depth -= 1 + mlo, mhi := do_pivot(it, a, b) if mlo-a < b-mhi { - _quick_sort(it, a, mlo, max_depth); - a = mhi; + _quick_sort(it, a, mlo, max_depth) + a = mhi } else { - _quick_sort(it, mhi, b, max_depth); - b = mlo; + _quick_sort(it, mhi, b, max_depth) + b = mlo } } if b-a > 1 { // Shell short with gap 6 for i in a+6..<b { if it->less(i, i-6) { - it->swap(i, i-6); + it->swap(i, i-6) } } - _insertion_sort(it, a, b); + _insertion_sort(it, a, b) } } @@ -288,7 +288,7 @@ _quick_sort :: proc(it: Interface, a, b, max_depth: int) { _insertion_sort :: proc(it: Interface, a, b: int) { for i in a+1..<b { for j := i; j > a && it->less(j, j-1); j -= 1 { - it->swap(j, j-1); + it->swap(j, j-1) } } } @@ -299,368 +299,368 @@ _insertion_sort :: proc(it: Interface, a, b: int) { // @(deprecated="use sort.sort or slice.sort_by") bubble_sort_proc :: proc(array: $A/[]$T, f: proc(T, T) -> int) { - assert(f != nil); - count := len(array); + assert(f != nil) + count := len(array) - init_j, last_j := 0, count-1; + init_j, last_j := 0, count-1 for { - init_swap, prev_swap := -1, -1; + init_swap, prev_swap := -1, -1 for j in init_j..<last_j { if f(array[j], array[j+1]) > 0 { - array[j], array[j+1] = array[j+1], array[j]; - prev_swap = j; + array[j], array[j+1] = array[j+1], array[j] + prev_swap = j if init_swap == -1 { - init_swap = j; + init_swap = j } } } if prev_swap == -1 { - return; + return } - init_j = max(init_swap-1, 0); - last_j = prev_swap; + init_j = max(init_swap-1, 0) + last_j = prev_swap } } // @(deprecated="use sort.sort_slice or slice.sort") bubble_sort :: proc(array: $A/[]$T) where intrinsics.type_is_ordered(T) { - count := len(array); + count := len(array) - init_j, last_j := 0, count-1; + init_j, last_j := 0, count-1 for { - init_swap, prev_swap := -1, -1; + init_swap, prev_swap := -1, -1 for j in init_j..<last_j { if array[j] > array[j+1] { - array[j], array[j+1] = array[j+1], array[j]; - prev_swap = j; + array[j], array[j+1] = array[j+1], array[j] + prev_swap = j if init_swap == -1 { - init_swap = j; + init_swap = j } } } if prev_swap == -1 { - return; + return } - init_j = max(init_swap-1, 0); - last_j = prev_swap; + init_j = max(init_swap-1, 0) + last_j = prev_swap } } // @(deprecated="use sort.sort or slice.sort_by") quick_sort_proc :: proc(array: $A/[]$T, f: proc(T, T) -> int) { - assert(f != nil); - a := array; - n := len(a); + assert(f != nil) + a := array + n := len(a) if n < 2 { - return; + return } - p := a[n/2]; - i, j := 0, n-1; + p := a[n/2] + i, j := 0, n-1 loop: for { for f(a[i], p) < 0 { i += 1; } for f(p, a[j]) < 0 { j -= 1; } if i >= j { - break loop; + break loop } - a[i], a[j] = a[j], a[i]; - i += 1; - j -= 1; + a[i], a[j] = a[j], a[i] + i += 1 + j -= 1 } - quick_sort_proc(a[0:i], f); - quick_sort_proc(a[i:n], f); + quick_sort_proc(a[0:i], f) + quick_sort_proc(a[i:n], f) } // @(deprecated="use sort.sort_slice or slice.sort") quick_sort :: proc(array: $A/[]$T) where intrinsics.type_is_ordered(T) { - a := array; - n := len(a); + a := array + n := len(a) if n < 2 { - return; + return } - p := a[n/2]; - i, j := 0, n-1; + p := a[n/2] + i, j := 0, n-1 loop: for { for a[i] < p { i += 1; } for p < a[j] { j -= 1; } if i >= j { - break loop; + break loop } - a[i], a[j] = a[j], a[i]; - i += 1; - j -= 1; + a[i], a[j] = a[j], a[i] + i += 1 + j -= 1 } - quick_sort(a[0:i]); - quick_sort(a[i:n]); + quick_sort(a[0:i]) + quick_sort(a[i:n]) } _log2 :: proc(x: int) -> int { - res := 0; + res := 0 for n := x; n != 0; n >>= 1 { - res += 1; + res += 1 } - return res; + return res } // @(deprecated="use sort.sort or slice.sort_by") merge_sort_proc :: proc(array: $A/[]$T, f: proc(T, T) -> int) { merge :: proc(a: A, start, mid, end: int, f: proc(T, T) -> int) { - s, m := start, mid; + s, m := start, mid - s2 := m + 1; + s2 := m + 1 if f(a[m], a[s2]) <= 0 { - return; + return } for s <= m && s2 <= end { if f(a[s], a[s2]) <= 0 { - s += 1; + s += 1 } else { - v := a[s2]; - i := s2; + v := a[s2] + i := s2 for i != s { - a[i] = a[i-1]; - i -= 1; + a[i] = a[i-1] + i -= 1 } - a[s] = v; + a[s] = v - s += 1; - m += 1; - s2 += 1; + s += 1 + m += 1 + s2 += 1 } } } internal_sort :: proc(a: A, l, r: int, f: proc(T, T) -> int) { if l < r { - m := l + (r - l) / 2; + m := l + (r - l) / 2 - internal_sort(a, l, m, f); - internal_sort(a, m+1, r, f); - merge(a, l, m, r, f); + internal_sort(a, l, m, f) + internal_sort(a, m+1, r, f) + merge(a, l, m, r, f) } } - internal_sort(array, 0, len(array)-1, f); + internal_sort(array, 0, len(array)-1, f) } // @(deprecated="use sort.sort_slice or slice.sort") merge_sort :: proc(array: $A/[]$T) where intrinsics.type_is_ordered(T) { merge :: proc(a: A, start, mid, end: int) { - s, m := start, mid; + s, m := start, mid - s2 := m + 1; + s2 := m + 1 if a[m] <= a[s2] { - return; + return } for s <= m && s2 <= end { if a[s] <= a[s2] { - s += 1; + s += 1 } else { - v := a[s2]; - i := s2; + v := a[s2] + i := s2 for i != s { - a[i] = a[i-1]; - i -= 1; + a[i] = a[i-1] + i -= 1 } - a[s] = v; + a[s] = v - s += 1; - m += 1; - s2 += 1; + s += 1 + m += 1 + s2 += 1 } } } internal_sort :: proc(a: A, l, r: int) { if l < r { - m := l + (r - l) / 2; + m := l + (r - l) / 2 - internal_sort(a, l, m); - internal_sort(a, m+1, r); - merge(a, l, m, r); + internal_sort(a, l, m) + internal_sort(a, m+1, r) + merge(a, l, m, r) } } - internal_sort(array, 0, len(array)-1); + internal_sort(array, 0, len(array)-1) } // @(deprecated="use sort.sort or slice.sort_by") heap_sort_proc :: proc(array: $A/[]$T, f: proc(T, T) -> int) { sift_proc :: proc(a: A, pi: int, n: int, f: proc(T, T) -> int) #no_bounds_check { - p := pi; - v := a[p]; - m := p*2 + 1; + p := pi + v := a[p] + m := p*2 + 1 for m <= n { if (m < n) && f(a[m+1], a[m]) > 0 { - m += 1; + m += 1 } if f(v, a[m]) >= 0 { - break; + break } - a[p] = a[m]; - p = m; - m += m+1; - a[p] = v; + a[p] = a[m] + p = m + m += m+1 + a[p] = v } } - n := len(array); + n := len(array) if n == 0 { - return; + return } for i := n/2; i >= 0; i -= 1 { - sift_proc(array, i, n-1, f); + sift_proc(array, i, n-1, f) } for i := n-1; i >= 1; i -= 1 { - array[0], array[i] = array[i], array[0]; - sift_proc(array, 0, i-1, f); + array[0], array[i] = array[i], array[0] + sift_proc(array, 0, i-1, f) } } // @(deprecated="use sort.sort_slice or slice.sort") heap_sort :: proc(array: $A/[]$T) where intrinsics.type_is_ordered(T) { sift :: proc(a: A, pi: int, n: int) #no_bounds_check { - p := pi; - v := a[p]; - m := p*2 + 1; + p := pi + v := a[p] + m := p*2 + 1 for m <= n { if (m < n) && (a[m+1] > a[m]) { - m += 1; + m += 1 } if v >= a[m] { - break; + break } - a[p] = a[m]; - p = m; - m += m+1; - a[p] = v; + a[p] = a[m] + p = m + m += m+1 + a[p] = v } } - n := len(array); + n := len(array) if n == 0 { - return; + return } for i := n/2; i >= 0; i -= 1 { - sift(array, i, n-1); + sift(array, i, n-1) } for i := n-1; i >= 1; i -= 1 { - array[0], array[i] = array[i], array[0]; - sift(array, 0, i-1); + array[0], array[i] = array[i], array[0] + sift(array, 0, i-1) } } compare_bools :: proc(a, b: bool) -> int { switch { - case !a && b: return -1; - case a && !b: return +1; + case !a && b: return -1 + case a && !b: return +1 } - return 0; + return 0 } compare_ints :: proc(a, b: int) -> int { switch delta := a - b; { - case delta < 0: return -1; - case delta > 0: return +1; + case delta < 0: return -1 + case delta > 0: return +1 } - return 0; + return 0 } compare_uints :: proc(a, b: uint) -> int { switch { - case a < b: return -1; - case a > b: return +1; + case a < b: return -1 + case a > b: return +1 } - return 0; + return 0 } compare_u8s :: proc(a, b: u8) -> int { switch { - case a < b: return -1; - case a > b: return +1; + case a < b: return -1 + case a > b: return +1 } - return 0; + return 0 } compare_u16s :: proc(a, b: u16) -> int { switch { - case a < b: return -1; - case a > b: return +1; + case a < b: return -1 + case a > b: return +1 } - return 0; + return 0 } compare_u32s :: proc(a, b: u32) -> int { switch { - case a < b: return -1; - case a > b: return +1; + case a < b: return -1 + case a > b: return +1 } - return 0; + return 0 } compare_u64s :: proc(a, b: u64) -> int { switch { - case a < b: return -1; - case a > b: return +1; + case a < b: return -1 + case a > b: return +1 } - return 0; + return 0 } compare_i8s :: proc(a, b: i8) -> int { switch { - case a < b: return -1; - case a > b: return +1; + case a < b: return -1 + case a > b: return +1 } - return 0; + return 0 } compare_i16s :: proc(a, b: i16) -> int { switch { - case a < b: return -1; - case a > b: return +1; + case a < b: return -1 + case a > b: return +1 } - return 0; + return 0 } compare_i32s :: proc(a, b: i32) -> int { switch { - case a < b: return -1; - case a > b: return +1; + case a < b: return -1 + case a > b: return +1 } - return 0; + return 0 } compare_i64s :: proc(a, b: i64) -> int { switch { - case a < b: return -1; - case a > b: return +1; + case a < b: return -1 + case a > b: return +1 } - return 0; + return 0 } @@ -668,20 +668,20 @@ compare_i64s :: proc(a, b: i64) -> int { compare_f32s :: proc(a, b: f32) -> int { switch delta := a - b; { - case delta < 0: return -1; - case delta > 0: return +1; + case delta < 0: return -1 + case delta > 0: return +1 } - return 0; + return 0 } compare_f64s :: proc(a, b: f64) -> int { switch delta := a - b; { - case delta < 0: return -1; - case delta > 0: return +1; + case delta < 0: return -1 + case delta > 0: return +1 } - return 0; + return 0 } compare_strings :: proc(a, b: string) -> int { - x := transmute(mem.Raw_String)a; - y := transmute(mem.Raw_String)b; - return mem.compare_byte_ptrs(x.data, y.data, min(x.len, y.len)); + x := transmute(mem.Raw_String)a + y := transmute(mem.Raw_String)b + return mem.compare_byte_ptrs(x.data, y.data, min(x.len, y.len)) } diff --git a/core/strconv/decimal/decimal.odin b/core/strconv/decimal/decimal.odin index 5215843e1..eddcef001 100644 --- a/core/strconv/decimal/decimal.odin +++ b/core/strconv/decimal/decimal.odin @@ -12,192 +12,192 @@ Decimal :: struct { decimal_to_string :: proc(buf: []byte, a: ^Decimal) -> string { digit_zero :: proc(buf: []byte) -> int { for _, i in buf { - buf[i] = '0'; + buf[i] = '0' } - return len(buf); + return len(buf) } - n := 10 + a.count + abs(a.decimal_point); + n := 10 + a.count + abs(a.decimal_point) // TODO(bill): make this work with a buffer that's not big enough - assert(len(buf) >= n); - b := buf[0:n]; + assert(len(buf) >= n) + b := buf[0:n] if a.count == 0 { - b[0] = '0'; - return string(b[0:1]); + b[0] = '0' + return string(b[0:1]) } - w := 0; + w := 0 if a.decimal_point <= 0 { - b[w] = '0'; w += 1; - b[w] = '.'; w += 1; - w += digit_zero(b[w : w-a.decimal_point]); - w += copy(b[w:], a.digits[0:a.count]); + b[w] = '0'; w += 1 + b[w] = '.'; w += 1 + w += digit_zero(b[w : w-a.decimal_point]) + w += copy(b[w:], a.digits[0:a.count]) } else if a.decimal_point < a.count { - w += copy(b[w:], a.digits[0:a.decimal_point]); - b[w] = '.'; w += 1; - w += copy(b[w:], a.digits[a.decimal_point : a.count]); + w += copy(b[w:], a.digits[0:a.decimal_point]) + b[w] = '.'; w += 1 + w += copy(b[w:], a.digits[a.decimal_point : a.count]) } else { - w += copy(b[w:], a.digits[0:a.count]); - w += digit_zero(b[w : w+a.decimal_point-a.count]); + w += copy(b[w:], a.digits[0:a.count]) + w += digit_zero(b[w : w+a.decimal_point-a.count]) } - return string(b[0:w]); + return string(b[0:w]) } // trim trailing zeros trim :: proc(a: ^Decimal) { for a.count > 0 && a.digits[a.count-1] == '0' { - a.count -= 1; + a.count -= 1 } if a.count == 0 { - a.decimal_point = 0; + a.decimal_point = 0 } } assign :: proc(a: ^Decimal, idx: u64) { - buf: [64]byte; - n := 0; + buf: [64]byte + n := 0 for i := idx; i > 0; { - j := i/10; - i -= 10*j; - buf[n] = byte('0'+i); - n += 1; - i = j; + j := i/10 + i -= 10*j + buf[n] = byte('0'+i) + n += 1 + i = j } - a.count = 0; + a.count = 0 for n -= 1; n >= 0; n -= 1 { - a.digits[a.count] = buf[n]; - a.count += 1; + a.digits[a.count] = buf[n] + a.count += 1 } - a.decimal_point = a.count; - trim(a); + a.decimal_point = a.count + trim(a) } shift_right :: proc(a: ^Decimal, k: uint) { - r := 0; // read index - w := 0; // write index + r := 0 // read index + w := 0 // write index - n: uint; + n: uint for ; n>>k == 0; r += 1 { if r >= a.count { if n == 0 { // Just in case - a.count = 0; - return; + a.count = 0 + return } for n>>k == 0 { - n = n * 10; - r += 1; + n = n * 10 + r += 1 } - break; + break } - c := uint(a.digits[r]); - n = n*10 + c - '0'; + c := uint(a.digits[r]) + n = n*10 + c - '0' } - a.decimal_point -= r-1; + a.decimal_point -= r-1 - mask: uint = (1<<k) - 1; + mask: uint = (1<<k) - 1 for ; r < a.count; r += 1 { - c := uint(a.digits[r]); - dig := n>>k; - n &= mask; - a.digits[w] = byte('0' + dig); - w += 1; - n = n*10 + c - '0'; + c := uint(a.digits[r]) + dig := n>>k + n &= mask + a.digits[w] = byte('0' + dig) + w += 1 + n = n*10 + c - '0' } for n > 0 { - dig := n>>k; - n &= mask; + dig := n>>k + n &= mask if w < len(a.digits) { - a.digits[w] = byte('0' + dig); - w += 1; + a.digits[w] = byte('0' + dig) + w += 1 } else if dig > 0 { - a.trunc = true; + a.trunc = true } - n *= 10; + n *= 10 } - a.count = w; - trim(a); + a.count = w + trim(a) } shift_left :: proc(a: ^Decimal, k: uint) { // NOTE(bill): used to determine buffer size required for the decimal from the binary shift // 'k' means `1<<k` == `2^k` which equates to roundup(k*log10(2)) digits required - log10_2 :: 0.301029995663981195213738894724493026768189881462108541310; - capacity := int(f64(k)*log10_2 + 1); + log10_2 :: 0.301029995663981195213738894724493026768189881462108541310 + capacity := int(f64(k)*log10_2 + 1) - r := a.count; // read index - w := a.count+capacity; // write index + r := a.count // read index + w := a.count+capacity // write index - d := len(a.digits); + d := len(a.digits) - n: uint; + n: uint for r -= 1; r >= 0; r -= 1 { - n += (uint(a.digits[r]) - '0') << k; - quo := n/10; - rem := n - 10*quo; - w -= 1; + n += (uint(a.digits[r]) - '0') << k + quo := n/10 + rem := n - 10*quo + w -= 1 if w < d { - a.digits[w] = byte('0' + rem); + a.digits[w] = byte('0' + rem) } else if rem != 0 { - a.trunc = true; + a.trunc = true } - n = quo; + n = quo } for n > 0 { - quo := n/10; - rem := n - 10*quo; - w -= 1; + quo := n/10 + rem := n - 10*quo + w -= 1 if w < d { - a.digits[w] = byte('0' + rem); + a.digits[w] = byte('0' + rem) } else if rem != 0 { - a.trunc = true; + a.trunc = true } - n = quo; + n = quo } // NOTE(bill): Remove unused buffer size - assert(w >= 0); - capacity -= w; + assert(w >= 0) + capacity -= w - a.count = min(a.count+capacity, d); - a.decimal_point += capacity; - trim(a); + a.count = min(a.count+capacity, d) + a.decimal_point += capacity + trim(a) } shift :: proc(a: ^Decimal, i: int) { - uint_size :: 8*size_of(uint); - max_shift :: uint_size-4; + uint_size :: 8*size_of(uint) + max_shift :: uint_size-4 switch k := i; { case a.count == 0: // no need to update case k > 0: for k > max_shift { - shift_left(a, max_shift); - k -= max_shift; + shift_left(a, max_shift) + k -= max_shift } - shift_left(a, uint(k)); + shift_left(a, uint(k)) case k < 0: for k < -max_shift { - shift_right(a, max_shift); - k += max_shift; + shift_right(a, max_shift) + k += max_shift } - shift_right(a, uint(-k)); + shift_right(a, uint(-k)) } } @@ -205,20 +205,20 @@ can_round_up :: proc(a: ^Decimal, nd: int) -> bool { if nd < 0 || nd >= a.count { return false ; } if a.digits[nd] == '5' && nd+1 == a.count { if a.trunc { - return true; + return true } - return nd > 0 && (a.digits[nd-1]-'0')%2 != 0; + return nd > 0 && (a.digits[nd-1]-'0')%2 != 0 } - return a.digits[nd] >= '5'; + return a.digits[nd] >= '5' } round :: proc(a: ^Decimal, nd: int) { if nd < 0 || nd >= a.count { return; } if can_round_up(a, nd) { - round_up(a, nd); + round_up(a, nd) } else { - round_down(a, nd); + round_down(a, nd) } } @@ -227,42 +227,42 @@ round_up :: proc(a: ^Decimal, nd: int) { for i := nd-1; i >= 0; i -= 1 { if c := a.digits[i]; c < '9' { - a.digits[i] += 1; - a.count = i+1; - return; + a.digits[i] += 1 + a.count = i+1 + return } } // Number is just 9s - a.digits[0] = '1'; - a.count = 1; - a.decimal_point += 1; + a.digits[0] = '1' + a.count = 1 + a.decimal_point += 1 } round_down :: proc(a: ^Decimal, nd: int) { if nd < 0 || nd >= a.count { return; } - a.count = nd; - trim(a); + a.count = nd + trim(a) } // Extract integer part, rounded appropriately. There are no guarantees about overflow. rounded_integer :: proc(a: ^Decimal) -> u64 { if a.decimal_point > 20 { - return 0xffff_ffff_ffff_ffff; + return 0xffff_ffff_ffff_ffff } - i: int = 0; - n: u64 = 0; - m := min(a.decimal_point, a.count); + i: int = 0 + n: u64 = 0 + m := min(a.decimal_point, a.count) for ; i < m; i += 1 { - n = n*10 + u64(a.digits[i]-'0'); + n = n*10 + u64(a.digits[i]-'0') } for ; i < a.decimal_point; i += 1 { - n *= 10; + n *= 10 } if can_round_up(a, a.decimal_point) { - n += 1; + n += 1 } - return n; + return n } diff --git a/core/strconv/generic_float.odin b/core/strconv/generic_float.odin index e98d1400a..13f44a57c 100644 --- a/core/strconv/generic_float.odin +++ b/core/strconv/generic_float.odin @@ -16,83 +16,83 @@ Float_Info :: struct { } -_f16_info := Float_Info{10, 5, -15}; -_f32_info := Float_Info{23, 8, -127}; -_f64_info := Float_Info{52, 11, -1023}; +_f16_info := Float_Info{10, 5, -15} +_f32_info := Float_Info{23, 8, -127} +_f64_info := Float_Info{52, 11, -1023} generic_ftoa :: proc(buf: []byte, val: f64, fmt: byte, precision, bit_size: int) -> []byte { - bits: u64; - flt: ^Float_Info; + bits: u64 + flt: ^Float_Info switch bit_size { case 16: - bits = u64(transmute(u16)f16(val)); - flt = &_f16_info; + bits = u64(transmute(u16)f16(val)) + flt = &_f16_info case 32: - bits = u64(transmute(u32)f32(val)); - flt = &_f32_info; + bits = u64(transmute(u32)f32(val)) + flt = &_f32_info case 64: - bits = transmute(u64)val; - flt = &_f64_info; + bits = transmute(u64)val + flt = &_f64_info case: - panic("strconv: invalid bit_size"); + panic("strconv: invalid bit_size") } - neg := bits>>(flt.expbits+flt.mantbits) != 0; - exp := int(bits>>flt.mantbits) & (1<<flt.expbits - 1); - mant := bits & (u64(1) << flt.mantbits - 1); + neg := bits>>(flt.expbits+flt.mantbits) != 0 + exp := int(bits>>flt.mantbits) & (1<<flt.expbits - 1) + mant := bits & (u64(1) << flt.mantbits - 1) switch exp { case 1<<flt.expbits - 1: - s: string; + s: string if mant != 0 { - s = "NaN"; + s = "NaN" } else if neg { - s = "-Inf"; + s = "-Inf" } else { - s = "+Inf"; + s = "+Inf" } - n := copy(buf, s); - return buf[:n]; + n := copy(buf, s) + return buf[:n] case 0: // denormalized - exp += 1; + exp += 1 case: - mant |= u64(1) << flt.mantbits; + mant |= u64(1) << flt.mantbits } - exp += flt.bias; + exp += flt.bias - d_: decimal.Decimal; - d := &d_; - decimal.assign(d, mant); - decimal.shift(d, exp - int(flt.mantbits)); - digs: Decimal_Slice; - prec := precision; - shortest := prec < 0; + d_: decimal.Decimal + d := &d_ + decimal.assign(d, mant) + decimal.shift(d, exp - int(flt.mantbits)) + digs: Decimal_Slice + prec := precision + shortest := prec < 0 if shortest { - round_shortest(d, mant, exp, flt); - digs = Decimal_Slice{digits = d.digits[:], count = d.count, decimal_point = d.decimal_point}; + round_shortest(d, mant, exp, flt) + digs = Decimal_Slice{digits = d.digits[:], count = d.count, decimal_point = d.decimal_point} switch fmt { - case 'e', 'E': prec = digs.count-1; - case 'f', 'F': prec = max(digs.count-digs.decimal_point, 0); - case 'g', 'G': prec = digs.count; + case 'e', 'E': prec = digs.count-1 + case 'f', 'F': prec = max(digs.count-digs.decimal_point, 0) + case 'g', 'G': prec = digs.count } } else { switch fmt { - case 'e', 'E': decimal.round(d, prec+1); - case 'f', 'F': decimal.round(d, d.decimal_point+prec); + case 'e', 'E': decimal.round(d, prec+1) + case 'f', 'F': decimal.round(d, d.decimal_point+prec) case 'g', 'G': if prec == 0 { - prec = 1; + prec = 1 } - decimal.round(d, prec); + decimal.round(d, prec) } - digs = Decimal_Slice{digits = d.digits[:], count = d.count, decimal_point = d.decimal_point}; + digs = Decimal_Slice{digits = d.digits[:], count = d.count, decimal_point = d.decimal_point} } - return format_digits(buf, shortest, neg, digs, prec, fmt); + return format_digits(buf, shortest, neg, digs, prec, fmt) } @@ -101,118 +101,118 @@ format_digits :: proc(buf: []byte, shortest: bool, neg: bool, digs: Decimal_Slic Buffer :: struct { b: []byte, n: int, - }; + } to_bytes :: proc(b: Buffer) -> []byte { - return b.b[:b.n]; + return b.b[:b.n] } add_bytes :: proc(buf: ^Buffer, bytes: ..byte) { - buf.n += copy(buf.b[buf.n:], bytes); + buf.n += copy(buf.b[buf.n:], bytes) } - b := Buffer{b = buf}; - prec := precision; + b := Buffer{b = buf} + prec := precision switch fmt { case 'f', 'F': - add_bytes(&b, '-' if neg else '+'); + add_bytes(&b, '-' if neg else '+') // integer, padded with zeros when needed if digs.decimal_point > 0 { - m := min(digs.count, digs.decimal_point); - add_bytes(&b, ..digs.digits[0:m]); + m := min(digs.count, digs.decimal_point) + add_bytes(&b, ..digs.digits[0:m]) for ; m < digs.decimal_point; m += 1 { - add_bytes(&b, '0'); + add_bytes(&b, '0') } } else { - add_bytes(&b, '0'); + add_bytes(&b, '0') } // fractional part if prec > 0 { - add_bytes(&b, '.'); + add_bytes(&b, '.') for i in 0..<prec { - c: byte = '0'; + c: byte = '0' if j := digs.decimal_point + i; 0 <= j && j < digs.count { - c = digs.digits[j]; + c = digs.digits[j] } - add_bytes(&b, c); + add_bytes(&b, c) } } - return to_bytes(b); + return to_bytes(b) case 'e', 'E': - add_bytes(&b, '-' if neg else '+'); + add_bytes(&b, '-' if neg else '+') - ch := byte('0'); + ch := byte('0') if digs.count != 0 { - ch = digs.digits[0]; + ch = digs.digits[0] } - add_bytes(&b, ch); + add_bytes(&b, ch) if prec > 0 { - add_bytes(&b, '.'); - i := 1; - m := min(digs.count, prec+1); + add_bytes(&b, '.') + i := 1 + m := min(digs.count, prec+1) if i < m { - add_bytes(&b, ..digs.digits[i:m]); - i = m; + add_bytes(&b, ..digs.digits[i:m]) + i = m } for ; i <= prec; i += 1 { - add_bytes(&b, '0'); + add_bytes(&b, '0') } } - add_bytes(&b, fmt); - exp := digs.decimal_point-1; + add_bytes(&b, fmt) + exp := digs.decimal_point-1 if digs.count == 0 { // Zero has exponent of 0 - exp = 0; + exp = 0 } - ch = '+'; + ch = '+' if exp < 0 { - ch = '-'; - exp = -exp; + ch = '-' + exp = -exp } - add_bytes(&b, ch); + add_bytes(&b, ch) switch { - case exp < 10: add_bytes(&b, '0', byte(exp)+'0'); // add prefix 0 - case exp < 100: add_bytes(&b, byte(exp/10)+'0', byte(exp%10)+'0'); - case: add_bytes(&b, byte(exp/100)+'0', byte(exp/10)%10+'0', byte(exp%10)+'0'); + case exp < 10: add_bytes(&b, '0', byte(exp)+'0') // add prefix 0 + case exp < 100: add_bytes(&b, byte(exp/10)+'0', byte(exp%10)+'0') + case: add_bytes(&b, byte(exp/100)+'0', byte(exp/10)%10+'0', byte(exp%10)+'0') } - return to_bytes(b); + return to_bytes(b) case 'g', 'G': - eprec := prec; + eprec := prec if eprec > digs.count && digs.count >= digs.decimal_point { - eprec = digs.count; + eprec = digs.count } if shortest { - eprec = 6; + eprec = 6 } - exp := digs.decimal_point - 1; + exp := digs.decimal_point - 1 if exp < -4 || exp >= eprec { if prec > digs.count { - prec = digs.count; + prec = digs.count } - return format_digits(buf, shortest, neg, digs, prec-1, fmt+'e'-'g'); // keep the same case + return format_digits(buf, shortest, neg, digs, prec-1, fmt+'e'-'g') // keep the same case } if prec > digs.decimal_point { - prec = digs.count; + prec = digs.count } - return format_digits(buf, shortest, neg, digs, max(prec-digs.decimal_point, 0), 'f'); + return format_digits(buf, shortest, neg, digs, max(prec-digs.decimal_point, 0), 'f') case: - add_bytes(&b, '%', fmt); - return to_bytes(b); + add_bytes(&b, '%', fmt) + return to_bytes(b) } @@ -220,8 +220,8 @@ format_digits :: proc(buf: []byte, shortest: bool, neg: bool, digs: Decimal_Slic round_shortest :: proc(d: ^decimal.Decimal, mant: u64, exp: int, flt: ^Float_Info) { if mant == 0 { // If mantissa is zero, the number is zero - d.count = 0; - return; + d.count = 0 + return } /* @@ -230,56 +230,56 @@ round_shortest :: proc(d: ^decimal.Decimal, mant: u64, exp: int, flt: ^Float_Inf log(2) >~ 0.332 332*(dp-nd) >= 100*(exp-mantbits) */ - minexp := flt.bias+1; + minexp := flt.bias+1 if exp > minexp && 332*(d.decimal_point-d.count) >= 100*(exp - int(flt.mantbits)) { // Number is already its shortest - return; + return } - upper_: decimal.Decimal; upper := &upper_; - decimal.assign(upper, 2*mant - 1); - decimal.shift(upper, exp - int(flt.mantbits) - 1); + upper_: decimal.Decimal; upper := &upper_ + decimal.assign(upper, 2*mant - 1) + decimal.shift(upper, exp - int(flt.mantbits) - 1) - mantlo: u64; - explo: int; + mantlo: u64 + explo: int if mant > 1<<flt.mantbits || exp == minexp { - mantlo = mant-1; - explo = exp; + mantlo = mant-1 + explo = exp } else { - mantlo = 2*mant - 1; - explo = exp-1; + mantlo = 2*mant - 1 + explo = exp-1 } - lower_: decimal.Decimal; lower := &lower_; - decimal.assign(lower, 2*mantlo + 1); - decimal.shift(lower, explo - int(flt.mantbits) - 1); + lower_: decimal.Decimal; lower := &lower_ + decimal.assign(lower, 2*mantlo + 1) + decimal.shift(lower, explo - int(flt.mantbits) - 1) - inclusive := mant%2 == 0; + inclusive := mant%2 == 0 for i in 0..<d.count { - l: byte = '0'; // lower digit + l: byte = '0' // lower digit if i < lower.count { - l = lower.digits[i]; + l = lower.digits[i] } - m := d.digits[i]; // middle digit - u: byte = '0'; // upper digit + m := d.digits[i] // middle digit + u: byte = '0' // upper digit if i < upper.count { - u = upper.digits[i]; + u = upper.digits[i] } - ok_round_down := l != m || inclusive && i+1 == lower.count; - ok_round_up := m != u && (inclusive || m+1 < u || i+1 < upper.count); + ok_round_down := l != m || inclusive && i+1 == lower.count + ok_round_up := m != u && (inclusive || m+1 < u || i+1 < upper.count) if ok_round_down && ok_round_up { - decimal.round(d, i+1); - return; + decimal.round(d, i+1) + return } if ok_round_down { - decimal.round_down(d, i+1); - return; + decimal.round_down(d, i+1) + return } if ok_round_up { - decimal.round_up(d, i+1); - return; + decimal.round_up(d, i+1) + return } } diff --git a/core/strconv/integers.odin b/core/strconv/integers.odin index f3bae4e07..2b6d0786e 100644 --- a/core/strconv/integers.odin +++ b/core/strconv/integers.odin @@ -5,163 +5,163 @@ Int_Flag :: enum { Plus, Space, } -Int_Flags :: bit_set[Int_Flag]; +Int_Flags :: bit_set[Int_Flag] -MAX_BASE :: 32; -digits := "0123456789abcdefghijklmnopqrstuvwxyz"; +MAX_BASE :: 32 +digits := "0123456789abcdefghijklmnopqrstuvwxyz" is_integer_negative :: proc(x: u64, is_signed: bool, bit_size: int) -> (u: u64, neg: bool) { - u = x; + u = x if is_signed { switch bit_size { case 8: - i := i8(u); - neg = i < 0; - u = u64(abs(i64(i))); + i := i8(u) + neg = i < 0 + u = u64(abs(i64(i))) case 16: - i := i16(u); - neg = i < 0; - u = u64(abs(i64(i))); + i := i16(u) + neg = i < 0 + u = u64(abs(i64(i))) case 32: - i := i32(u); - neg = i < 0; - u = u64(abs(i64(i))); + i := i32(u) + neg = i < 0 + u = u64(abs(i64(i))) case 64: - i := i64(u); - neg = i < 0; - u = u64(abs(i)); + i := i64(u) + neg = i < 0 + u = u64(abs(i)) case: - panic("is_integer_negative: Unknown integer size"); + panic("is_integer_negative: Unknown integer size") } } - return; + return } append_bits :: proc(buf: []byte, x: u64, base: int, is_signed: bool, bit_size: int, digits: string, flags: Int_Flags) -> string { if base < 2 || base > MAX_BASE { - panic("strconv: illegal base passed to append_bits"); + panic("strconv: illegal base passed to append_bits") } - a: [129]byte; - i := len(a); - u, neg := is_integer_negative(x, is_signed, bit_size); - b := u64(base); + a: [129]byte + i := len(a) + u, neg := is_integer_negative(x, is_signed, bit_size) + b := u64(base) for u >= b { - i-=1; a[i] = digits[u % b]; - u /= b; + i-=1; a[i] = digits[u % b] + u /= b } - i-=1; a[i] = digits[u % b]; + i-=1; a[i] = digits[u % b] if .Prefix in flags { - ok := true; + ok := true switch base { - case 2: i-=1; a[i] = 'b'; - case 8: i-=1; a[i] = 'o'; + case 2: i-=1; a[i] = 'b' + case 8: i-=1; a[i] = 'o' // case 10: i-=1; a[i] = 'd'; - case 12: i-=1; a[i] = 'z'; - case 16: i-=1; a[i] = 'x'; - case: ok = false; + case 12: i-=1; a[i] = 'z' + case 16: i-=1; a[i] = 'x' + case: ok = false } if ok { - i-=1; a[i] = '0'; + i-=1; a[i] = '0' } } switch { case neg: - i-=1; a[i] = '-'; + i-=1; a[i] = '-' case .Plus in flags: - i-=1; a[i] = '+'; + i-=1; a[i] = '+' case .Space in flags: - i-=1; a[i] = ' '; + i-=1; a[i] = ' ' } - out := a[i:]; - copy(buf, out); - return string(buf[0:len(out)]); + out := a[i:] + copy(buf, out) + return string(buf[0:len(out)]) } is_integer_negative_128 :: proc(x: u128, is_signed: bool, bit_size: int) -> (u: u128, neg: bool) { - u = x; + u = x if is_signed { switch bit_size { case 8: - i := i8(u); - neg = i < 0; - u = u128(abs(i128(i))); + i := i8(u) + neg = i < 0 + u = u128(abs(i128(i))) case 16: - i := i16(u); - neg = i < 0; - u = u128(abs(i128(i))); + i := i16(u) + neg = i < 0 + u = u128(abs(i128(i))) case 32: - i := i32(u); - neg = i < 0; - u = u128(abs(i128(i))); + i := i32(u) + neg = i < 0 + u = u128(abs(i128(i))) case 64: - i := i64(u); - neg = i < 0; - u = u128(abs(i128(i))); + i := i64(u) + neg = i < 0 + u = u128(abs(i128(i))) case 128: - i := i128(u); - neg = i < 0; - u = u128(abs(i)); + i := i128(u) + neg = i < 0 + u = u128(abs(i)) case: - panic("is_integer_negative: Unknown integer size"); + panic("is_integer_negative: Unknown integer size") } } - return; + return } // import "core:runtime" append_bits_128 :: proc(buf: []byte, x: u128, base: int, is_signed: bool, bit_size: int, digits: string, flags: Int_Flags) -> string { if base < 2 || base > MAX_BASE { - panic("strconv: illegal base passed to append_bits"); + panic("strconv: illegal base passed to append_bits") } - a: [140]byte; - i := len(a); - u, neg := is_integer_negative_128(x, is_signed, bit_size); - b := u128(base); + a: [140]byte + i := len(a) + u, neg := is_integer_negative_128(x, is_signed, bit_size) + b := u128(base) for u >= b && i >= 0 { - i-=1; + i-=1 // rem: u128; // u = runtime.udivmod128(u, b, &rem); // u /= b; - rem := u % b; - u /= b; + rem := u % b + u /= b - idx := u32(rem); - a[i] = digits[idx]; + idx := u32(rem) + a[i] = digits[idx] } - i-=1; a[i] = digits[u64(u % b)]; + i-=1; a[i] = digits[u64(u % b)] if .Prefix in flags { - ok := true; + ok := true switch base { - case 2: i-=1; a[i] = 'b'; - case 8: i-=1; a[i] = 'o'; - case 10: i-=1; a[i] = 'd'; - case 12: i-=1; a[i] = 'z'; - case 16: i-=1; a[i] = 'x'; - case: ok = false; + case 2: i-=1; a[i] = 'b' + case 8: i-=1; a[i] = 'o' + case 10: i-=1; a[i] = 'd' + case 12: i-=1; a[i] = 'z' + case 16: i-=1; a[i] = 'x' + case: ok = false } if ok { - i-=1; a[i] = '0'; + i-=1; a[i] = '0' } } switch { case neg: - i-=1; a[i] = '-'; + i-=1; a[i] = '-' case .Plus in flags: - i-=1; a[i] = '+'; + i-=1; a[i] = '+' case .Space in flags: - i-=1; a[i] = ' '; + i-=1; a[i] = ' ' } - out := a[i:]; - copy(buf, out); - return string(buf[0:len(out)]); + out := a[i:] + copy(buf, out) + return string(buf[0:len(out)]) } diff --git a/core/strconv/strconv.odin b/core/strconv/strconv.odin index ca8934aa9..782f9d9a3 100644 --- a/core/strconv/strconv.odin +++ b/core/strconv/strconv.odin @@ -5,22 +5,22 @@ import "core:unicode/utf8" parse_bool :: proc(s: string) -> (result: bool = false, ok: bool) { switch s { case "1", "t", "T", "true", "TRUE", "True": - return true, true; + return true, true case "0", "f", "F", "false", "FALSE", "False": - return false, true; + return false, true } - return; + return } _digit_value :: proc(r: rune) -> int { - ri := int(r); - v: int = 16; + ri := int(r) + v: int = 16 switch r { - case '0'..='9': v = ri-'0'; - case 'a'..='z': v = ri-'a'+10; - case 'A'..='Z': v = ri-'A'+10; + case '0'..='9': v = ri-'0' + case 'a'..='z': v = ri-'a'+10 + case 'A'..='Z': v = ri-'A'+10 } - return v; + return v } // Parses an integer value from a string, in the given base, without a prefix. @@ -33,46 +33,46 @@ _digit_value :: proc(r: rune) -> int { // assert(n == -1234 && ok); // ``` parse_i64_of_base :: proc(str: string, base: int) -> (value: i64, ok: bool) { - assert(base <= 16, "base must be 1-16"); + assert(base <= 16, "base must be 1-16") - s := str; + s := str if s == "" { - return; + return } - neg := false; + neg := false if len(s) > 1 { switch s[0] { case '-': - neg = true; - s = s[1:]; + neg = true + s = s[1:] case '+': - s = s[1:]; + s = s[1:] } } - i := 0; + i := 0 for r in s { if r == '_' { - i += 1; - continue; + i += 1 + continue } - v := i64(_digit_value(r)); + v := i64(_digit_value(r)) if v >= i64(base) { - break; + break } - value *= i64(base); - value += v; - i += 1; + value *= i64(base) + value += v + i += 1 } - s = s[i:]; + s = s[i:] if neg { - value = -value; + value = -value } - ok = len(s) == 0; - return; + ok = len(s) == 0 + return } // Parses a integer value from a string, in base 10, unless there's a prefix. @@ -88,59 +88,59 @@ parse_i64_of_base :: proc(str: string, base: int) -> (value: i64, ok: bool) { // assert(n == 0xeeee && ok); // ``` parse_i64_maybe_prefixed :: proc(str: string) -> (value: i64, ok: bool) { - s := str; + s := str if s == "" { - return; + return } - neg := false; + neg := false if len(s) > 1 { switch s[0] { case '-': - neg = true; - s = s[1:]; + neg = true + s = s[1:] case '+': - s = s[1:]; + s = s[1:] } } - base: i64 = 10; + base: i64 = 10 if len(s) > 2 && s[0] == '0' { switch s[1] { - case 'b': base = 2; s = s[2:]; - case 'o': base = 8; s = s[2:]; - case 'd': base = 10; s = s[2:]; - case 'z': base = 12; s = s[2:]; - case 'x': base = 16; s = s[2:]; + case 'b': base = 2; s = s[2:] + case 'o': base = 8; s = s[2:] + case 'd': base = 10; s = s[2:] + case 'z': base = 12; s = s[2:] + case 'x': base = 16; s = s[2:] } } - i := 0; + i := 0 for r in s { if r == '_' { - i += 1; - continue; + i += 1 + continue } - v := i64(_digit_value(r)); + v := i64(_digit_value(r)) if v >= base { - break; + break } - value *= base; - value += v; - i += 1; + value *= base + value += v + i += 1 } - s = s[i:]; + s = s[i:] if neg { - value = -value; + value = -value } - ok = len(s) == 0; - return; + ok = len(s) == 0 + return } -parse_i64 :: proc{parse_i64_maybe_prefixed, parse_i64_of_base}; +parse_i64 :: proc{parse_i64_maybe_prefixed, parse_i64_of_base} // Parses an unsigned integer value from a string, in the given base, and // without a prefix. @@ -156,34 +156,34 @@ parse_i64 :: proc{parse_i64_maybe_prefixed, parse_i64_of_base}; // assert(n == 0x5678eeee && ok); // ``` parse_u64_of_base :: proc(str: string, base: int) -> (value: u64, ok: bool) { - assert(base <= 16, "base must be 1-16"); - s := str; + assert(base <= 16, "base must be 1-16") + s := str if s == "" { - return; + return } if len(s) > 1 && s[0] == '+' { - s = s[1:]; + s = s[1:] } - i := 0; + i := 0 for r in s { if r == '_' { - i += 1; - continue; + i += 1 + continue } - v := u64(_digit_value(r)); + v := u64(_digit_value(r)) if v >= u64(base) { - break; + break } - value *= u64(base); - value += v; - i += 1; + value *= u64(base) + value += v + i += 1 } - s = s[i:]; + s = s[i:] - ok = len(s) == 0; - return; + ok = len(s) == 0 + return } // Parses an unsigned integer value from a string in base 10, unless there's a prefix. @@ -199,48 +199,48 @@ parse_u64_of_base :: proc(str: string, base: int) -> (value: u64, ok: bool) { // assert(n == 0xeeee && ok); // ``` parse_u64_maybe_prefixed :: proc(str: string) -> (value: u64, ok: bool) { - s := str; + s := str if s == "" { - return; + return } if len(s) > 1 && s[0] == '+' { - s = s[1:]; + s = s[1:] } - base := u64(10); + base := u64(10) if len(s) > 2 && s[0] == '0' { switch s[1] { - case 'b': base = 2; s = s[2:]; - case 'o': base = 8; s = s[2:]; - case 'd': base = 10; s = s[2:]; - case 'z': base = 12; s = s[2:]; - case 'x': base = 16; s = s[2:]; + case 'b': base = 2; s = s[2:] + case 'o': base = 8; s = s[2:] + case 'd': base = 10; s = s[2:] + case 'z': base = 12; s = s[2:] + case 'x': base = 16; s = s[2:] } } - i := 0; + i := 0 for r in s { if r == '_' { - i += 1; - continue; + i += 1 + continue } - v := u64(_digit_value(r)); + v := u64(_digit_value(r)) if v >= base { - break; + break } - value *= base; - value += v; - i += 1; + value *= base + value += v + i += 1 } - s = s[i:]; + s = s[i:] - ok = len(s) == 0; - return; + ok = len(s) == 0 + return } -parse_u64 :: proc{parse_u64_maybe_prefixed, parse_u64_of_base}; +parse_u64 :: proc{parse_u64_maybe_prefixed, parse_u64_of_base} // Parses an integer value from a string in the given base, or // - if the string has a prefix (e.g: '0x') then that will determine the base; @@ -260,13 +260,13 @@ parse_u64 :: proc{parse_u64_maybe_prefixed, parse_u64_of_base}; // assert(n == 0xffff && ok); // ``` parse_int :: proc(s: string, base := 0) -> (value: int, ok: bool) { - v: i64 = ---; + v: i64 = --- switch base { - case 0: v, ok = parse_i64_maybe_prefixed(s); - case: v, ok = parse_i64_of_base(s, base); + case 0: v, ok = parse_i64_maybe_prefixed(s) + case: v, ok = parse_i64_of_base(s, base) } - value = int(v); - return; + value = int(v) + return } @@ -290,13 +290,13 @@ parse_int :: proc(s: string, base := 0) -> (value: int, ok: bool) { // assert(n == 0xffff && ok); // ``` parse_uint :: proc(s: string, base := 0) -> (value: uint, ok: bool) { - v: u64 = ---; + v: u64 = --- switch base { - case 0: v, ok = parse_u64_maybe_prefixed(s); - case: v, ok = parse_u64_of_base(s, base); + case 0: v, ok = parse_u64_maybe_prefixed(s) + case: v, ok = parse_u64_of_base(s, base) } - value = uint(v); - return; + value = uint(v) + return } @@ -313,9 +313,9 @@ parse_uint :: proc(s: string, base := 0) -> (value: uint, ok: bool) { // assert(n == 12.34 && ok); // ``` parse_f32 :: proc(s: string) -> (value: f32, ok: bool) { - v: f64 = ---; - v, ok = parse_f64(s); - return f32(v), ok; + v: f64 = --- + v, ok = parse_f64(s) + return f32(v), ok } // Parses a 64-bit floating point number from a string. @@ -331,76 +331,76 @@ parse_f32 :: proc(s: string) -> (value: f32, ok: bool) { // assert(n == 12.34 && ok); // ``` parse_f64 :: proc(str: string) -> (value: f64, ok: bool) { - s := str; + s := str if s == "" { - return; + return } - i := 0; + i := 0 - sign: f64 = 1; + sign: f64 = 1 switch s[i] { - case '-': i += 1; sign = -1; - case '+': i += 1; + case '-': i += 1; sign = -1 + case '+': i += 1 } for ; i < len(s); i += 1 { - r := rune(s[i]); + r := rune(s[i]) if r == '_' { - continue; + continue } - v := _digit_value(r); + v := _digit_value(r) if v >= 10 { - break; + break } - value *= 10; - value += f64(v); + value *= 10 + value += f64(v) } if i < len(s) && s[i] == '.' { - pow10: f64 = 10; - i += 1; + pow10: f64 = 10 + i += 1 for ; i < len(s); i += 1 { - r := rune(s[i]); + r := rune(s[i]) if r == '_' { - continue; + continue } - v := _digit_value(r); + v := _digit_value(r) if v >= 10 { - break; + break } - value += f64(v)/pow10; - pow10 *= 10; + value += f64(v)/pow10 + pow10 *= 10 } } - frac := false; - scale: f64 = 1; + frac := false + scale: f64 = 1 if i < len(s) && (s[i] == 'e' || s[i] == 'E') { - i += 1; + i += 1 if i < len(s) { switch s[i] { - case '-': i += 1; frac = true; - case '+': i += 1; + case '-': i += 1; frac = true + case '+': i += 1 } - exp: u32 = 0; + exp: u32 = 0 for ; i < len(s); i += 1 { - r := rune(s[i]); + r := rune(s[i]) if r == '_' { - continue; + continue } - d := u32(_digit_value(r)); + d := u32(_digit_value(r)) if d >= 10 { - break; + break } - exp = exp * 10 + d; + exp = exp * 10 + d } if exp > 308 { exp = 308; } @@ -409,146 +409,146 @@ parse_f64 :: proc(str: string) -> (value: f64, ok: bool) { for exp > 0 { scale *= 10; exp -= 1; } } } - s = s[i:]; + s = s[i:] if frac { - value = sign * (value/scale); + value = sign * (value/scale) } else { - value = sign * (value*scale); + value = sign * (value*scale) } - ok = len(s) == 0; - return; + ok = len(s) == 0 + return } append_bool :: proc(buf: []byte, b: bool) -> string { - n := 0; + n := 0 if b { - n = copy(buf, "true"); + n = copy(buf, "true") } else { - n = copy(buf, "false"); + n = copy(buf, "false") } - return string(buf[:n]); + return string(buf[:n]) } append_uint :: proc(buf: []byte, u: u64, base: int) -> string { - return append_bits(buf, u, base, false, 8*size_of(uint), digits, nil); + return append_bits(buf, u, base, false, 8*size_of(uint), digits, nil) } append_int :: proc(buf: []byte, i: i64, base: int) -> string { - return append_bits(buf, u64(i), base, true, 8*size_of(int), digits, nil); + return append_bits(buf, u64(i), base, true, 8*size_of(int), digits, nil) } itoa :: proc(buf: []byte, i: int) -> string { - return append_int(buf, i64(i), 10); + return append_int(buf, i64(i), 10) } atoi :: proc(s: string) -> int { - v, _ := parse_int(s); - return v; + v, _ := parse_int(s) + return v } atof :: proc(s: string) -> f64 { - v, _ := parse_f64(s); - return v; + v, _ := parse_f64(s) + return v } -ftoa :: append_float; +ftoa :: append_float append_float :: proc(buf: []byte, f: f64, fmt: byte, prec, bit_size: int) -> string { - return string(generic_ftoa(buf, f, fmt, prec, bit_size)); + return string(generic_ftoa(buf, f, fmt, prec, bit_size)) } quote :: proc(buf: []byte, str: string) -> string { write_byte :: proc(buf: []byte, i: ^int, bytes: ..byte) { if i^ >= len(buf) { - return; + return } - n := copy(buf[i^:], bytes[:]); - i^ += n; + n := copy(buf[i^:], bytes[:]) + i^ += n } if buf == nil { - return ""; + return "" } - c :: '"'; - i := 0; - s := str; + c :: '"' + i := 0 + s := str - write_byte(buf, &i, c); + write_byte(buf, &i, c) for width := 0; len(s) > 0; s = s[width:] { - r := rune(s[0]); - width = 1; + r := rune(s[0]) + width = 1 if r >= utf8.RUNE_SELF { - r, width = utf8.decode_rune_in_string(s); + r, width = utf8.decode_rune_in_string(s) } if width == 1 && r == utf8.RUNE_ERROR { - write_byte(buf, &i, '\\', 'x'); - write_byte(buf, &i, digits[s[0]>>4]); - write_byte(buf, &i, digits[s[0]&0xf]); + write_byte(buf, &i, '\\', 'x') + write_byte(buf, &i, digits[s[0]>>4]) + write_byte(buf, &i, digits[s[0]&0xf]) } if i < len(buf) { - x := quote_rune(buf[i:], r); - i += len(x); + x := quote_rune(buf[i:], r) + i += len(x) } } - write_byte(buf, &i, c); - return string(buf[:i]); + write_byte(buf, &i, c) + return string(buf[:i]) } quote_rune :: proc(buf: []byte, r: rune) -> string { write_byte :: proc(buf: []byte, i: ^int, bytes: ..byte) { if i^ < len(buf) { - n := copy(buf[i^:], bytes[:]); - i^ += n; + n := copy(buf[i^:], bytes[:]) + i^ += n } } write_string :: proc(buf: []byte, i: ^int, s: string) { if i^ < len(buf) { - n := copy(buf[i^:], s); - i^ += n; + n := copy(buf[i^:], s) + i^ += n } } write_rune :: proc(buf: []byte, i: ^int, r: rune) { if i^ < len(buf) { - b, w := utf8.encode_rune(r); - n := copy(buf[i^:], b[:w]); - i^ += n; + b, w := utf8.encode_rune(r) + n := copy(buf[i^:], b[:w]) + i^ += n } } if buf == nil { - return ""; + return "" } - i := 0; - write_byte(buf, &i, '\''); + i := 0 + write_byte(buf, &i, '\'') switch r { - case '\a': write_string(buf, &i, "\\a"); - case '\b': write_string(buf, &i, "\\b"); - case '\e': write_string(buf, &i, "\\e"); - case '\f': write_string(buf, &i, "\\f"); - case '\n': write_string(buf, &i, "\\n"); - case '\r': write_string(buf, &i, "\\r"); - case '\t': write_string(buf, &i, "\\t"); - case '\v': write_string(buf, &i, "\\v"); + case '\a': write_string(buf, &i, "\\a") + case '\b': write_string(buf, &i, "\\b") + case '\e': write_string(buf, &i, "\\e") + case '\f': write_string(buf, &i, "\\f") + case '\n': write_string(buf, &i, "\\n") + case '\r': write_string(buf, &i, "\\r") + case '\t': write_string(buf, &i, "\\t") + case '\v': write_string(buf, &i, "\\v") case: if r < 32 { - write_string(buf, &i, "\\x"); - b: [2]byte; - s := append_bits(b[:], u64(r), 16, true, 64, digits, nil); + write_string(buf, &i, "\\x") + b: [2]byte + s := append_bits(b[:], u64(r), 16, true, 64, digits, nil) switch len(s) { - case 0: write_string(buf, &i, "00"); - case 1: write_rune(buf, &i, '0'); - case 2: write_string(buf, &i, s); + case 0: write_string(buf, &i, "00") + case 1: write_rune(buf, &i, '0') + case 2: write_string(buf, &i, s) } } else { - write_rune(buf, &i, r); + write_rune(buf, &i, r) } } - write_byte(buf, &i, '\''); + write_byte(buf, &i, '\'') - return string(buf[:i]); + return string(buf[:i]) } @@ -557,152 +557,152 @@ quote_rune :: proc(buf: []byte, r: rune) -> string { unquote_char :: proc(str: string, quote: byte) -> (r: rune, multiple_bytes: bool, tail_string: string, success: bool) { hex_to_int :: proc(c: byte) -> int { switch c { - case '0'..='9': return int(c-'0'); - case 'a'..='f': return int(c-'a')+10; - case 'A'..='F': return int(c-'A')+10; + case '0'..='9': return int(c-'0') + case 'a'..='f': return int(c-'a')+10 + case 'A'..='F': return int(c-'A')+10 } - return -1; + return -1 } - w: int; + w: int if str[0] == quote && quote == '"' { - return; + return } else if str[0] >= 0x80 { - r, w = utf8.decode_rune_in_string(str); - return r, true, str[w:], true; + r, w = utf8.decode_rune_in_string(str) + return r, true, str[w:], true } else if str[0] != '\\' { - return rune(str[0]), false, str[1:], true; + return rune(str[0]), false, str[1:], true } if len(str) <= 1 { - return; + return } - s := str; - c := s[1]; - s = s[2:]; + s := str + c := s[1] + s = s[2:] switch c { case: - return; + return - case 'a': r = '\a'; - case 'b': r = '\b'; - case 'f': r = '\f'; - case 'n': r = '\n'; - case 'r': r = '\r'; - case 't': r = '\t'; - case 'v': r = '\v'; - case '\\': r = '\\'; + case 'a': r = '\a' + case 'b': r = '\b' + case 'f': r = '\f' + case 'n': r = '\n' + case 'r': r = '\r' + case 't': r = '\t' + case 'v': r = '\v' + case '\\': r = '\\' - case '"': r = '"'; - case '\'': r = '\''; + case '"': r = '"' + case '\'': r = '\'' case '0'..='7': - v := int(c-'0'); + v := int(c-'0') if len(s) < 2 { - return; + return } for i in 0..<len(s) { - d := int(s[i]-'0'); + d := int(s[i]-'0') if d < 0 || d > 7 { - return; + return } - v = (v<<3) | d; + v = (v<<3) | d } - s = s[2:]; + s = s[2:] if v > 0xff { - return; + return } - r = rune(v); + r = rune(v) case 'x', 'u', 'U': - count: int; + count: int switch c { - case 'x': count = 2; - case 'u': count = 4; - case 'U': count = 8; + case 'x': count = 2 + case 'u': count = 4 + case 'U': count = 8 } if len(s) < count { - return; + return } for i in 0..<count { - d := hex_to_int(s[i]); + d := hex_to_int(s[i]) if d < 0 { - return; + return } - r = (r<<4) | rune(d); + r = (r<<4) | rune(d) } - s = s[count:]; + s = s[count:] if c == 'x' { - break; + break } if r > utf8.MAX_RUNE { - return; + return } - multiple_bytes = true; + multiple_bytes = true } - success = true; - tail_string = s; - return; + success = true + tail_string = s + return } unquote_string :: proc(lit: string, allocator := context.allocator) -> (res: string, allocated, success: bool) { contains_rune :: proc(s: string, r: rune) -> int { for c, offset in s { if c == r { - return offset; + return offset } } - return -1; + return -1 } - assert(len(lit) >= 2); + assert(len(lit) >= 2) if lit[0] == '`' { - return lit[1:len(lit)-1], false, true; + return lit[1:len(lit)-1], false, true } - s := lit; - quote := '"'; + s := lit + quote := '"' if s == `""` { - return "", false, true; + return "", false, true } if contains_rune(s, '\n') >= 0 { - return s, false, false; + return s, false, false } if contains_rune(s, '\\') < 0 && contains_rune(s, quote) < 0 { if quote == '"' { - return s, false, true; + return s, false, true } } - buf_len := 3*len(s) / 2; - buf := make([]byte, buf_len, allocator); - offset := 0; + buf_len := 3*len(s) / 2 + buf := make([]byte, buf_len, allocator) + offset := 0 for len(s) > 0 { - r, multiple_bytes, tail_string, ok := unquote_char(s, byte(quote)); + r, multiple_bytes, tail_string, ok := unquote_char(s, byte(quote)) if !ok { - delete(buf); - return s, false, false; + delete(buf) + return s, false, false } - s = tail_string; + s = tail_string if r < 0x80 || !multiple_bytes { - buf[offset] = byte(r); - offset += 1; + buf[offset] = byte(r) + offset += 1 } else { - b, w := utf8.encode_rune(r); - copy(buf[offset:], b[:w]); - offset += w; + b, w := utf8.encode_rune(r) + copy(buf[offset:], b[:w]) + offset += w } } - new_string := string(buf[:offset]); + new_string := string(buf[:offset]) - return new_string, true, true; + return new_string, true, true } diff --git a/core/strings/ascii_set.odin b/core/strings/ascii_set.odin index 06aea982f..582049eee 100644 --- a/core/strings/ascii_set.odin +++ b/core/strings/ascii_set.odin @@ -3,20 +3,20 @@ package strings import "core:unicode/utf8" -Ascii_Set :: distinct [8]u32; +Ascii_Set :: distinct [8]u32 ascii_set_make :: proc(chars: string) -> (as: Ascii_Set, ok: bool) #no_bounds_check { for i in 0..<len(chars) { - c := chars[i]; + c := chars[i] if c >= utf8.RUNE_SELF { - return; + return } - as[c>>5] |= 1 << uint(c&31); + as[c>>5] |= 1 << uint(c&31) } - ok = true; - return; + ok = true + return } ascii_set_contains :: proc(as: Ascii_Set, c: byte) -> bool #no_bounds_check { - return as[c>>5] & (1<<(c&31)) != 0; + return as[c>>5] & (1<<(c&31)) != 0 }
\ No newline at end of file diff --git a/core/strings/builder.odin b/core/strings/builder.odin index f2926b969..b378811bb 100644 --- a/core/strings/builder.odin +++ b/core/strings/builder.odin @@ -5,199 +5,199 @@ import "core:unicode/utf8" import "core:strconv" import "core:io" -Builder_Flush_Proc :: #type proc(b: ^Builder) -> (do_reset: bool); +Builder_Flush_Proc :: #type proc(b: ^Builder) -> (do_reset: bool) Builder :: struct { buf: [dynamic]byte, } make_builder_none :: proc(allocator := context.allocator) -> Builder { - return Builder{buf=make([dynamic]byte, allocator)}; + return Builder{buf=make([dynamic]byte, allocator)} } make_builder_len :: proc(len: int, allocator := context.allocator) -> Builder { - return Builder{buf=make([dynamic]byte, len, allocator)}; + return Builder{buf=make([dynamic]byte, len, allocator)} } make_builder_len_cap :: proc(len, cap: int, allocator := context.allocator) -> Builder { - return Builder{buf=make([dynamic]byte, len, cap, allocator)}; + return Builder{buf=make([dynamic]byte, len, cap, allocator)} } make_builder :: proc{ make_builder_none, make_builder_len, make_builder_len_cap, -}; +} init_builder_none :: proc(b: ^Builder, allocator := context.allocator) { - b.buf = make([dynamic]byte, allocator); + b.buf = make([dynamic]byte, allocator) } init_builder_len :: proc(b: ^Builder, len: int, allocator := context.allocator) { - b.buf = make([dynamic]byte, len, allocator); + b.buf = make([dynamic]byte, len, allocator) } init_builder_len_cap :: proc(b: ^Builder, len, cap: int, allocator := context.allocator) { - b.buf = make([dynamic]byte, len, cap, allocator); + b.buf = make([dynamic]byte, len, cap, allocator) } init_builder :: proc{ init_builder_none, init_builder_len, init_builder_len_cap, -}; +} @(private) _builder_stream_vtable := &io.Stream_VTable{ impl_write = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) { - b := (^Builder)(s.stream_data); - n = write_bytes(b, p); + b := (^Builder)(s.stream_data) + n = write_bytes(b, p) if len(b.buf) == cap(b.buf) { - err = .EOF; + err = .EOF } - return; + return }, impl_write_byte = proc(s: io.Stream, c: byte) -> io.Error { - b := (^Builder)(s.stream_data); - _ = write_byte(b, c); + b := (^Builder)(s.stream_data) + _ = write_byte(b, c) if len(b.buf) == cap(b.buf) { - return .EOF; + return .EOF } - return nil; + return nil }, impl_size = proc(s: io.Stream) -> i64 { - b := (^Builder)(s.stream_data); - return i64(len(b.buf)); + b := (^Builder)(s.stream_data) + return i64(len(b.buf)) }, impl_destroy = proc(s: io.Stream) -> io.Error { - b := (^Builder)(s.stream_data); - delete(b.buf); - return .None; + b := (^Builder)(s.stream_data) + delete(b.buf) + return .None }, -}; +} to_stream :: proc(b: ^Builder) -> io.Stream { - return io.Stream{stream_vtable=_builder_stream_vtable, stream_data=b}; + return io.Stream{stream_vtable=_builder_stream_vtable, stream_data=b} } to_writer :: proc(b: ^Builder) -> io.Writer { - w, _ := io.to_writer(to_stream(b)); - return w; + w, _ := io.to_writer(to_stream(b)) + return w } destroy_builder :: proc(b: ^Builder) { - delete(b.buf); - clear(&b.buf); + delete(b.buf) + clear(&b.buf) } grow_builder :: proc(b: ^Builder, cap: int) { - reserve(&b.buf, cap); + reserve(&b.buf, cap) } reset_builder :: proc(b: ^Builder) { - clear(&b.buf); + clear(&b.buf) } builder_from_slice :: proc(backing: []byte) -> Builder { - s := transmute(mem.Raw_Slice)backing; + s := transmute(mem.Raw_Slice)backing d := mem.Raw_Dynamic_Array{ data = s.data, len = 0, cap = s.len, allocator = mem.nil_allocator(), - }; + } return Builder{ buf = transmute([dynamic]byte)d, - }; + } } to_string :: proc(b: Builder) -> string { - return string(b.buf[:]); + return string(b.buf[:]) } builder_len :: proc(b: Builder) -> int { - return len(b.buf); + return len(b.buf) } builder_cap :: proc(b: Builder) -> int { - return cap(b.buf); + return cap(b.buf) } builder_space :: proc(b: Builder) -> int { - return max(cap(b.buf), len(b.buf), 0); + return max(cap(b.buf), len(b.buf), 0) } write_byte :: proc(b: ^Builder, x: byte) -> (n: int) { if builder_space(b^) > 0 { - append(&b.buf, x); - n += 1; + append(&b.buf, x) + n += 1 } - return; + return } write_bytes :: proc(b: ^Builder, x: []byte) -> (n: int) { - x := x; + x := x for len(x) != 0 { - space := builder_space(b^); + space := builder_space(b^) if space == 0 { - break; // No need to append + break // No need to append } - i := min(space, len(x)); - n += i; - append(&b.buf, ..x[:i]); + i := min(space, len(x)) + n += i + append(&b.buf, ..x[:i]) if len(x) <= i { - break; // No more data to append + break // No more data to append } - x = x[i:]; + x = x[i:] } - return; + return } write_rune_builder :: proc(b: ^Builder, r: rune) -> (int, io.Error) { - return io.write_rune(to_writer(b), r); + return io.write_rune(to_writer(b), r) } write_quoted_rune_builder :: proc(b: ^Builder, r: rune) -> (n: int) { - return write_quoted_rune(to_writer(b), r); + return write_quoted_rune(to_writer(b), r) } @(private) _write_byte :: proc(w: io.Writer, c: byte) -> int { - err := io.write_byte(w, c); - return 1 if err == nil else 0; + err := io.write_byte(w, c) + return 1 if err == nil else 0 } write_quoted_rune :: proc(w: io.Writer, r: rune) -> (n: int) { - quote := byte('\''); - n += _write_byte(w, quote); - buf, width := utf8.encode_rune(r); + quote := byte('\'') + n += _write_byte(w, quote) + buf, width := utf8.encode_rune(r) if width == 1 && r == utf8.RUNE_ERROR { - n += _write_byte(w, '\\'); - n += _write_byte(w, 'x'); - n += _write_byte(w, DIGITS_LOWER[buf[0]>>4]); - n += _write_byte(w, DIGITS_LOWER[buf[0]&0xf]); + n += _write_byte(w, '\\') + n += _write_byte(w, 'x') + n += _write_byte(w, DIGITS_LOWER[buf[0]>>4]) + n += _write_byte(w, DIGITS_LOWER[buf[0]&0xf]) } else { - n += write_escaped_rune(w, r, quote); + n += write_escaped_rune(w, r, quote) } - n += _write_byte(w, quote); - return; + n += _write_byte(w, quote) + return } write_string :: proc{ write_string_builder, write_string_writer, -}; +} write_string_builder :: proc(b: ^Builder, s: string) -> (n: int) { - return write_string_writer(to_writer(b), s); + return write_string_writer(to_writer(b), s) } write_string_writer :: proc(w: io.Writer, s: string) -> (n: int) { - n, _ = io.write(w, transmute([]byte)s); - return; + n, _ = io.write(w, transmute([]byte)s) + return } @@ -205,109 +205,109 @@ write_string_writer :: proc(w: io.Writer, s: string) -> (n: int) { pop_byte :: proc(b: ^Builder) -> (r: byte) { if len(b.buf) == 0 { - return 0; + return 0 } - r = b.buf[len(b.buf)-1]; - d := cast(^mem.Raw_Dynamic_Array)&b.buf; - d.len = max(d.len-1, 0); - return; + r = b.buf[len(b.buf)-1] + d := cast(^mem.Raw_Dynamic_Array)&b.buf + d.len = max(d.len-1, 0) + return } pop_rune :: proc(b: ^Builder) -> (r: rune, width: int) { - r, width = utf8.decode_last_rune(b.buf[:]); - d := cast(^mem.Raw_Dynamic_Array)&b.buf; - d.len = max(d.len-width, 0); - return; + r, width = utf8.decode_last_rune(b.buf[:]) + d := cast(^mem.Raw_Dynamic_Array)&b.buf + d.len = max(d.len-width, 0) + return } @(private) -DIGITS_LOWER := "0123456789abcdefx"; +DIGITS_LOWER := "0123456789abcdefx" write_quoted_string :: proc{ write_quoted_string_builder, write_quoted_string_writer, -}; +} write_quoted_string_builder :: proc(b: ^Builder, str: string, quote: byte = '"') -> (n: int) { - return write_quoted_string_writer(to_writer(b), str, quote); + return write_quoted_string_writer(to_writer(b), str, quote) } write_quoted_string_writer :: proc(w: io.Writer, str: string, quote: byte = '"') -> (n: int) { - n += _write_byte(w, quote); + n += _write_byte(w, quote) for width, s := 0, str; len(s) > 0; s = s[width:] { - r := rune(s[0]); - width = 1; + r := rune(s[0]) + width = 1 if r >= utf8.RUNE_SELF { - r, width = utf8.decode_rune_in_string(s); + r, width = utf8.decode_rune_in_string(s) } if width == 1 && r == utf8.RUNE_ERROR { - n += _write_byte(w, '\\'); - n += _write_byte(w, 'x'); - n += _write_byte(w, DIGITS_LOWER[s[0]>>4]); - n += _write_byte(w, DIGITS_LOWER[s[0]&0xf]); - continue; + n += _write_byte(w, '\\') + n += _write_byte(w, 'x') + n += _write_byte(w, DIGITS_LOWER[s[0]>>4]) + n += _write_byte(w, DIGITS_LOWER[s[0]&0xf]) + continue } - n += write_escaped_rune(w, r, quote); + n += write_escaped_rune(w, r, quote) } - n += _write_byte(w, quote); - return; + n += _write_byte(w, quote) + return } write_encoded_rune :: proc{ write_encoded_rune_builder, write_encoded_rune_writer, -}; +} write_encoded_rune_builder :: proc(b: ^Builder, r: rune, write_quote := true) -> (n: int) { - return write_encoded_rune_writer(to_writer(b), r, write_quote); + return write_encoded_rune_writer(to_writer(b), r, write_quote) } write_encoded_rune_writer :: proc(w: io.Writer, r: rune, write_quote := true) -> (n: int) { if write_quote { - n += _write_byte(w, '\''); + n += _write_byte(w, '\'') } switch r { - case '\a': n += write_string(w, `\a"`); - case '\b': n += write_string(w, `\b"`); - case '\e': n += write_string(w, `\e"`); - case '\f': n += write_string(w, `\f"`); - case '\n': n += write_string(w, `\n"`); - case '\r': n += write_string(w, `\r"`); - case '\t': n += write_string(w, `\t"`); - case '\v': n += write_string(w, `\v"`); + case '\a': n += write_string(w, `\a"`) + case '\b': n += write_string(w, `\b"`) + case '\e': n += write_string(w, `\e"`) + case '\f': n += write_string(w, `\f"`) + case '\n': n += write_string(w, `\n"`) + case '\r': n += write_string(w, `\r"`) + case '\t': n += write_string(w, `\t"`) + case '\v': n += write_string(w, `\v"`) case: if r < 32 { - n += write_string(w, `\x`); - buf: [2]byte; - s := strconv.append_bits(buf[:], u64(r), 16, true, 64, strconv.digits, nil); + n += write_string(w, `\x`) + buf: [2]byte + s := strconv.append_bits(buf[:], u64(r), 16, true, 64, strconv.digits, nil) switch len(s) { - case 0: n += write_string(w, "00"); - case 1: n += _write_byte(w, '0'); - case 2: n += write_string(w, s); + case 0: n += write_string(w, "00") + case 1: n += _write_byte(w, '0') + case 2: n += write_string(w, s) } } else { - rn, _ := io.write_rune(w, r); - n += rn; + rn, _ := io.write_rune(w, r) + n += rn } } if write_quote { - n += _write_byte(w, '\''); + n += _write_byte(w, '\'') } - return; + return } write_escaped_rune :: proc{ write_escaped_rune_builder, write_escaped_rune_writer, -}; +} write_escaped_rune_builder :: proc(b: ^Builder, r: rune, quote: byte, html_safe := false) -> (n: int) { - return write_escaped_rune_writer(to_writer(b), r, quote, html_safe); + return write_escaped_rune_writer(to_writer(b), r, quote, html_safe) } write_escaped_rune_writer :: proc(w: io.Writer, r: rune, quote: byte, html_safe := false) -> (n: int) { @@ -315,89 +315,89 @@ write_escaped_rune_writer :: proc(w: io.Writer, r: rune, quote: byte, html_safe if r <= 0xff { switch r { case 0x20..=0x7e: - return true; + return true case 0xa1..=0xff: // ¡ through ÿ except for the soft hyphen - return r != 0xad; // + return r != 0xad // } } // TODO(bill): A proper unicode library will be needed! - return false; + return false } if html_safe { switch r { case '<', '>', '&': - n += _write_byte(w, '\\'); - n += _write_byte(w, 'u'); + n += _write_byte(w, '\\') + n += _write_byte(w, 'u') for s := 12; s >= 0; s -= 4 { - n += _write_byte(w, DIGITS_LOWER[r>>uint(s) & 0xf]); + n += _write_byte(w, DIGITS_LOWER[r>>uint(s) & 0xf]) } - return; + return } } if r == rune(quote) || r == '\\' { - n += _write_byte(w, '\\'); - n += _write_byte(w, byte(r)); - return; + n += _write_byte(w, '\\') + n += _write_byte(w, byte(r)) + return } else if is_printable(r) { - n += write_encoded_rune(w, r, false); - return; + n += write_encoded_rune(w, r, false) + return } switch r { - case '\a': n += write_string(w, `\a`); - case '\b': n += write_string(w, `\b`); - case '\e': n += write_string(w, `\e`); - case '\f': n += write_string(w, `\f`); - case '\n': n += write_string(w, `\n`); - case '\r': n += write_string(w, `\r`); - case '\t': n += write_string(w, `\t`); - case '\v': n += write_string(w, `\v`); + case '\a': n += write_string(w, `\a`) + case '\b': n += write_string(w, `\b`) + case '\e': n += write_string(w, `\e`) + case '\f': n += write_string(w, `\f`) + case '\n': n += write_string(w, `\n`) + case '\r': n += write_string(w, `\r`) + case '\t': n += write_string(w, `\t`) + case '\v': n += write_string(w, `\v`) case: switch c := r; { case c < ' ': - n += _write_byte(w, '\\'); - n += _write_byte(w, 'x'); - n += _write_byte(w, DIGITS_LOWER[byte(c)>>4]); - n += _write_byte(w, DIGITS_LOWER[byte(c)&0xf]); + n += _write_byte(w, '\\') + n += _write_byte(w, 'x') + n += _write_byte(w, DIGITS_LOWER[byte(c)>>4]) + n += _write_byte(w, DIGITS_LOWER[byte(c)&0xf]) case c > utf8.MAX_RUNE: - c = 0xfffd; - fallthrough; + c = 0xfffd + fallthrough case c < 0x10000: - n += _write_byte(w, '\\'); - n += _write_byte(w, 'u'); + n += _write_byte(w, '\\') + n += _write_byte(w, 'u') for s := 12; s >= 0; s -= 4 { - n += _write_byte(w, DIGITS_LOWER[c>>uint(s) & 0xf]); + n += _write_byte(w, DIGITS_LOWER[c>>uint(s) & 0xf]) } case: - n += _write_byte(w, '\\'); - n += _write_byte(w, 'U'); + n += _write_byte(w, '\\') + n += _write_byte(w, 'U') for s := 28; s >= 0; s -= 4 { - n += _write_byte(w, DIGITS_LOWER[c>>uint(s) & 0xf]); + n += _write_byte(w, DIGITS_LOWER[c>>uint(s) & 0xf]) } } } - return; + return } write_u64 :: proc(b: ^Builder, i: u64, base: int = 10) -> (n: int) { - buf: [32]byte; - s := strconv.append_bits(buf[:], i, base, false, 64, strconv.digits, nil); - return write_string(b, s); + buf: [32]byte + s := strconv.append_bits(buf[:], i, base, false, 64, strconv.digits, nil) + return write_string(b, s) } write_i64 :: proc(b: ^Builder, i: i64, base: int = 10) -> (n: int) { - buf: [32]byte; - s := strconv.append_bits(buf[:], u64(i), base, true, 64, strconv.digits, nil); - return write_string(b, s); + buf: [32]byte + s := strconv.append_bits(buf[:], u64(i), base, true, 64, strconv.digits, nil) + return write_string(b, s) } write_uint :: proc(b: ^Builder, i: uint, base: int = 10) -> (n: int) { - return write_u64(b, u64(i), base); + return write_u64(b, u64(i), base) } write_int :: proc(b: ^Builder, i: int, base: int = 10) -> (n: int) { - return write_i64(b, i64(i), base); + return write_i64(b, i64(i), base) } diff --git a/core/strings/conversion.odin b/core/strings/conversion.odin index 26535f8c0..b0d42b2eb 100644 --- a/core/strings/conversion.odin +++ b/core/strings/conversion.odin @@ -6,91 +6,91 @@ import "core:unicode/utf8" to_valid_utf8 :: proc(s, replacement: string, allocator := context.allocator) -> string { if len(s) == 0 { - return ""; + return "" } - b: Builder; - init_builder(&b, 0, 0, allocator); + b: Builder + init_builder(&b, 0, 0, allocator) - s := s; + s := s for c, i in s { if c != utf8.RUNE_ERROR { - continue; + continue } - _, w := utf8.decode_rune_in_string(s[i:]); + _, w := utf8.decode_rune_in_string(s[i:]) if w == 1 { - grow_builder(&b, len(s) + len(replacement)); - write_string(&b, s[:i]); - s = s[i:]; - break; + grow_builder(&b, len(s) + len(replacement)) + write_string(&b, s[:i]) + s = s[i:] + break } } if builder_cap(b) == 0 { - return clone(s, allocator); + return clone(s, allocator) } - invalid := false; + invalid := false for i := 0; i < len(s); /**/ { - c := s[i]; + c := s[i] if c < utf8.RUNE_SELF { - i += 1; - invalid = false; - write_byte(&b, c); - continue; + i += 1 + invalid = false + write_byte(&b, c) + continue } - _, w := utf8.decode_rune_in_string(s[i:]); + _, w := utf8.decode_rune_in_string(s[i:]) if w == 1 { - i += 1; + i += 1 if !invalid { - invalid = true; - write_string(&b, replacement); + invalid = true + write_string(&b, replacement) } - continue; + continue } - invalid = false; - write_string(&b, s[i:][:w]); - i += w; + invalid = false + write_string(&b, s[i:][:w]) + i += w } - return to_string(b); + return to_string(b) } to_lower :: proc(s: string, allocator := context.allocator) -> string { - b: Builder; - init_builder(&b, 0, len(s), allocator); + b: Builder + init_builder(&b, 0, len(s), allocator) for r in s { - write_rune_builder(&b, unicode.to_lower(r)); + write_rune_builder(&b, unicode.to_lower(r)) } - return to_string(b); + return to_string(b) } to_upper :: proc(s: string, allocator := context.allocator) -> string { - b: Builder; - init_builder(&b, 0, len(s), allocator); + b: Builder + init_builder(&b, 0, len(s), allocator) for r in s { - write_rune_builder(&b, unicode.to_upper(r)); + write_rune_builder(&b, unicode.to_upper(r)) } - return to_string(b); + return to_string(b) } is_delimiter :: proc(c: rune) -> bool { - return c == '-' || c == '_' || is_space(c); + return c == '-' || c == '_' || is_space(c) } is_separator :: proc(r: rune) -> bool { if r <= 0x7f { switch r { - case '0'..='9': return false; - case 'a'..='z': return false; - case 'A'..='Z': return false; - case '_': return false; + case '0'..='9': return false + case 'a'..='z': return false + case 'A'..='Z': return false + case '_': return false } - return true; + return true } // TODO(bill): unicode categories @@ -98,172 +98,172 @@ is_separator :: proc(r: rune) -> bool { // return false; // } - return unicode.is_space(r); + return unicode.is_space(r) } string_case_iterator :: proc(w: io.Writer, s: string, callback: proc(w: io.Writer, prev, curr, next: rune)) { - prev, curr: rune; + prev, curr: rune for next in s { if curr == 0 { - prev = curr; - curr = next; - continue; + prev = curr + curr = next + continue } - callback(w, prev, curr, next); + callback(w, prev, curr, next) - prev = curr; - curr = next; + prev = curr + curr = next } if len(s) > 0 { - callback(w, prev, curr, 0); + callback(w, prev, curr, 0) } } -to_lower_camel_case :: to_camel_case; +to_lower_camel_case :: to_camel_case to_camel_case :: proc(s: string, allocator := context.allocator) -> string { - s := s; - s = trim_space(s); - b: Builder; - init_builder(&b, 0, len(s), allocator); - w := to_writer(&b); + s := s + s = trim_space(s) + b: Builder + init_builder(&b, 0, len(s), allocator) + w := to_writer(&b) string_case_iterator(w, s, proc(w: io.Writer, prev, curr, next: rune) { if !is_delimiter(curr) { if is_delimiter(prev) { - io.write_rune(w, unicode.to_upper(curr)); + io.write_rune(w, unicode.to_upper(curr)) } else if unicode.is_lower(prev) { - io.write_rune(w, curr); + io.write_rune(w, curr) } else { - io.write_rune(w, unicode.to_lower(curr)); + io.write_rune(w, unicode.to_lower(curr)) } } - }); + }) - return to_string(b); + return to_string(b) } -to_upper_camel_case :: to_pascal_case; +to_upper_camel_case :: to_pascal_case to_pascal_case :: proc(s: string, allocator := context.allocator) -> string { - s := s; - s = trim_space(s); - b: Builder; - init_builder(&b, 0, len(s), allocator); - w := to_writer(&b); + s := s + s = trim_space(s) + b: Builder + init_builder(&b, 0, len(s), allocator) + w := to_writer(&b) string_case_iterator(w, s, proc(w: io.Writer, prev, curr, next: rune) { if !is_delimiter(curr) { if is_delimiter(prev) || prev == 0 { - io.write_rune(w, unicode.to_upper(curr)); + io.write_rune(w, unicode.to_upper(curr)) } else if unicode.is_lower(prev) { - io.write_rune(w, curr); + io.write_rune(w, curr) } else { - io.write_rune(w, unicode.to_lower(curr)); + io.write_rune(w, unicode.to_lower(curr)) } } - }); + }) - return to_string(b); + return to_string(b) } to_delimiter_case :: proc(s: string, delimiter: rune, all_upper_case: bool, allocator := context.allocator) -> string { - s := s; - s = trim_space(s); - b: Builder; - init_builder(&b, 0, len(s), allocator); - w := to_writer(&b); + s := s + s = trim_space(s) + b: Builder + init_builder(&b, 0, len(s), allocator) + w := to_writer(&b) - adjust_case := unicode.to_upper if all_upper_case else unicode.to_lower; + adjust_case := unicode.to_upper if all_upper_case else unicode.to_lower - prev, curr: rune; + prev, curr: rune for next in s { if is_delimiter(curr) { if !is_delimiter(prev) { - io.write_rune(w, delimiter); + io.write_rune(w, delimiter) } } else if unicode.is_upper(curr) { if unicode.is_lower(prev) || (unicode.is_upper(prev) && unicode.is_lower(next)) { - io.write_rune(w, delimiter); + io.write_rune(w, delimiter) } - io.write_rune(w, adjust_case(curr)); + io.write_rune(w, adjust_case(curr)) } else if curr != 0 { - io.write_rune(w, adjust_case(curr)); + io.write_rune(w, adjust_case(curr)) } - prev = curr; - curr = next; + prev = curr + curr = next } if len(s) > 0 { if unicode.is_upper(curr) && unicode.is_lower(prev) && prev != 0 { - io.write_rune(w, delimiter); + io.write_rune(w, delimiter) } - io.write_rune(w, adjust_case(curr)); + io.write_rune(w, adjust_case(curr)) } - return to_string(b); + return to_string(b) } to_snake_case :: proc(s: string, allocator := context.allocator) -> string { - return to_delimiter_case(s, '_', false, allocator); + return to_delimiter_case(s, '_', false, allocator) } -to_screaming_snake_case :: to_upper_snake_case; +to_screaming_snake_case :: to_upper_snake_case to_upper_snake_case :: proc(s: string, allocator := context.allocator) -> string { - return to_delimiter_case(s, '_', true, allocator); + return to_delimiter_case(s, '_', true, allocator) } to_kebab_case :: proc(s: string, allocator := context.allocator) -> string { - return to_delimiter_case(s, '-', false, allocator); + return to_delimiter_case(s, '-', false, allocator) } to_upper_case :: proc(s: string, allocator := context.allocator) -> string { - return to_delimiter_case(s, '-', true, allocator); + return to_delimiter_case(s, '-', true, allocator) } to_ada_case :: proc(s: string, allocator := context.allocator) -> string { - delimiter :: '_'; + delimiter :: '_' - s := s; - s = trim_space(s); - b: Builder; - init_builder(&b, 0, len(s), allocator); - w := to_writer(&b); + s := s + s = trim_space(s) + b: Builder + init_builder(&b, 0, len(s), allocator) + w := to_writer(&b) - prev, curr: rune; + prev, curr: rune for next in s { if is_delimiter(curr) { if !is_delimiter(prev) { - io.write_rune(w, delimiter); + io.write_rune(w, delimiter) } } else if unicode.is_upper(curr) { if unicode.is_lower(prev) || (unicode.is_upper(prev) && unicode.is_lower(next)) { - io.write_rune(w, delimiter); + io.write_rune(w, delimiter) } - io.write_rune(w, unicode.to_upper(curr)); + io.write_rune(w, unicode.to_upper(curr)) } else if curr != 0 { - io.write_rune(w, unicode.to_lower(curr)); + io.write_rune(w, unicode.to_lower(curr)) } - prev = curr; - curr = next; + prev = curr + curr = next } if len(s) > 0 { if unicode.is_upper(curr) && unicode.is_lower(prev) && prev != 0 { - io.write_rune(w, delimiter); - io.write_rune(w, unicode.to_upper(curr)); + io.write_rune(w, delimiter) + io.write_rune(w, unicode.to_upper(curr)) } else { - io.write_rune(w, unicode.to_lower(curr)); + io.write_rune(w, unicode.to_lower(curr)) } } - return to_string(b); + return to_string(b) } diff --git a/core/strings/intern.odin b/core/strings/intern.odin index 0e4951f87..ff26d7dbb 100644 --- a/core/strings/intern.odin +++ b/core/strings/intern.odin @@ -13,42 +13,42 @@ Intern :: struct { } intern_init :: proc(m: ^Intern, allocator := context.allocator, map_allocator := context.allocator) { - m.allocator = allocator; - m.entries = make(map[string]^Intern_Entry, 16, map_allocator); + m.allocator = allocator + m.entries = make(map[string]^Intern_Entry, 16, map_allocator) } intern_destroy :: proc(m: ^Intern) { for _, value in m.entries { - free(value, m.allocator); + free(value, m.allocator) } - delete(m.entries); + delete(m.entries) } intern_get :: proc(m: ^Intern, text: string) -> string { - entry := _intern_get_entry(m, text); - #no_bounds_check return string(entry.str[:entry.len]); + entry := _intern_get_entry(m, text) + #no_bounds_check return string(entry.str[:entry.len]) } intern_get_cstring :: proc(m: ^Intern, text: string) -> cstring { - entry := _intern_get_entry(m, text); - return cstring(&entry.str[0]); + entry := _intern_get_entry(m, text) + return cstring(&entry.str[0]) } _intern_get_entry :: proc(m: ^Intern, text: string) -> ^Intern_Entry #no_bounds_check { if prev, ok := m.entries[text]; ok { - return prev; + return prev } if m.allocator.procedure == nil { - m.allocator = context.allocator; + m.allocator = context.allocator } - entry_size := int(offset_of(Intern_Entry, str)) + len(text) + 1; - new_entry := (^Intern_Entry)(mem.alloc(entry_size, align_of(Intern_Entry), m.allocator)); + entry_size := int(offset_of(Intern_Entry, str)) + len(text) + 1 + new_entry := (^Intern_Entry)(mem.alloc(entry_size, align_of(Intern_Entry), m.allocator)) - new_entry.len = len(text); - copy(new_entry.str[:new_entry.len], text); - new_entry.str[new_entry.len] = 0; + new_entry.len = len(text) + copy(new_entry.str[:new_entry.len], text) + new_entry.str[new_entry.len] = 0 - key := string(new_entry.str[:new_entry.len]); - m.entries[key] = new_entry; - return new_entry; + key := string(new_entry.str[:new_entry.len]) + m.entries[key] = new_entry + return new_entry } diff --git a/core/strings/reader.odin b/core/strings/reader.odin index 8e6952fdc..ba266c0b5 100644 --- a/core/strings/reader.odin +++ b/core/strings/reader.odin @@ -10,190 +10,190 @@ Reader :: struct { } reader_init :: proc(r: ^Reader, s: string) { - r.s = s; - r.i = 0; - r.prev_rune = -1; + r.s = s + r.i = 0 + r.prev_rune = -1 } reader_to_stream :: proc(r: ^Reader) -> (s: io.Stream) { - s.stream_data = r; - s.stream_vtable = _reader_vtable; - return; + s.stream_data = r + s.stream_vtable = _reader_vtable + return } to_reader :: proc(r: ^Reader, s: string) -> io.Reader { - reader_init(r, s); - rr, _ := io.to_reader(reader_to_stream(r)); - return rr; + reader_init(r, s) + rr, _ := io.to_reader(reader_to_stream(r)) + return rr } to_reader_at :: proc(r: ^Reader, s: string) -> io.Reader_At { - reader_init(r, s); - rr, _ := io.to_reader_at(reader_to_stream(r)); - return rr; + reader_init(r, s) + rr, _ := io.to_reader_at(reader_to_stream(r)) + return rr } to_byte_reader :: proc(r: ^Reader, s: string) -> io.Byte_Reader { - reader_init(r, s); - rr, _ := io.to_byte_reader(reader_to_stream(r)); - return rr; + reader_init(r, s) + rr, _ := io.to_byte_reader(reader_to_stream(r)) + return rr } to_rune_reader :: proc(r: ^Reader, s: string) -> io.Rune_Reader { - reader_init(r, s); - rr, _ := io.to_rune_reader(reader_to_stream(r)); - return rr; + reader_init(r, s) + rr, _ := io.to_rune_reader(reader_to_stream(r)) + return rr } reader_length :: proc(r: ^Reader) -> int { if r.i >= i64(len(r.s)) { - return 0; + return 0 } - return int(i64(len(r.s)) - r.i); + return int(i64(len(r.s)) - r.i) } reader_size :: proc(r: ^Reader) -> i64 { - return i64(len(r.s)); + return i64(len(r.s)) } reader_read :: proc(r: ^Reader, p: []byte) -> (n: int, err: io.Error) { if r.i >= i64(len(r.s)) { - return 0, .EOF; + return 0, .EOF } - r.prev_rune = -1; - n = copy(p, r.s[r.i:]); - r.i += i64(n); - return; + r.prev_rune = -1 + n = copy(p, r.s[r.i:]) + r.i += i64(n) + return } reader_read_at :: proc(r: ^Reader, p: []byte, off: i64) -> (n: int, err: io.Error) { if off < 0 { - return 0, .Invalid_Offset; + return 0, .Invalid_Offset } if off >= i64(len(r.s)) { - return 0, .EOF; + return 0, .EOF } - n = copy(p, r.s[off:]); + n = copy(p, r.s[off:]) if n < len(p) { - err = .EOF; + err = .EOF } - return; + return } reader_read_byte :: proc(r: ^Reader) -> (byte, io.Error) { - r.prev_rune = -1; + r.prev_rune = -1 if r.i >= i64(len(r.s)) { - return 0, .EOF; + return 0, .EOF } - b := r.s[r.i]; - r.i += 1; - return b, nil; + b := r.s[r.i] + r.i += 1 + return b, nil } reader_unread_byte :: proc(r: ^Reader) -> io.Error { if r.i <= 0 { - return .Invalid_Unread; + return .Invalid_Unread } - r.prev_rune = -1; - r.i -= 1; - return nil; + r.prev_rune = -1 + r.i -= 1 + return nil } reader_read_rune :: proc(r: ^Reader) -> (ch: rune, size: int, err: io.Error) { if r.i >= i64(len(r.s)) { - r.prev_rune = -1; - return 0, 0, .EOF; + r.prev_rune = -1 + return 0, 0, .EOF } - r.prev_rune = int(r.i); + r.prev_rune = int(r.i) if c := r.s[r.i]; c < utf8.RUNE_SELF { - r.i += 1; - return rune(c), 1, nil; + r.i += 1 + return rune(c), 1, nil } - ch, size = utf8.decode_rune_in_string(r.s[r.i:]); - r.i += i64(size); - return; + ch, size = utf8.decode_rune_in_string(r.s[r.i:]) + r.i += i64(size) + return } reader_unread_rune :: proc(r: ^Reader) -> io.Error { if r.i <= 0 { - return .Invalid_Unread; + return .Invalid_Unread } if r.prev_rune < 0 { - return .Invalid_Unread; + return .Invalid_Unread } - r.i = i64(r.prev_rune); - r.prev_rune = -1; - return nil; + r.i = i64(r.prev_rune) + r.prev_rune = -1 + return nil } reader_seek :: proc(r: ^Reader, offset: i64, whence: io.Seek_From) -> (i64, io.Error) { - r.prev_rune = -1; - abs: i64; + r.prev_rune = -1 + abs: i64 switch whence { case .Start: - abs = offset; + abs = offset case .Current: - abs = r.i + offset; + abs = r.i + offset case .End: - abs = i64(len(r.s)) + offset; + abs = i64(len(r.s)) + offset case: - return 0, .Invalid_Whence; + return 0, .Invalid_Whence } if abs < 0 { - return 0, .Invalid_Offset; + return 0, .Invalid_Offset } - r.i = abs; - return abs, nil; + r.i = abs + return abs, nil } reader_write_to :: proc(r: ^Reader, w: io.Writer) -> (n: i64, err: io.Error) { - r.prev_rune = -1; + r.prev_rune = -1 if r.i >= i64(len(r.s)) { - return 0, nil; + return 0, nil } - s := r.s[r.i:]; - m: int; - m, err = io.write_string(w, s); + s := r.s[r.i:] + m: int + m, err = io.write_string(w, s) if m > len(s) { - panic("bytes.Reader.write_to: invalid io.write_string count"); + panic("bytes.Reader.write_to: invalid io.write_string count") } - r.i += i64(m); - n = i64(m); + r.i += i64(m) + n = i64(m) if m != len(s) && err == nil { - err = .Short_Write; + err = .Short_Write } - return; + return } @(private) _reader_vtable := &io.Stream_VTable{ impl_size = proc(s: io.Stream) -> i64 { - r := (^Reader)(s.stream_data); - return reader_size(r); + r := (^Reader)(s.stream_data) + return reader_size(r) }, impl_read = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) { - r := (^Reader)(s.stream_data); - return reader_read(r, p); + r := (^Reader)(s.stream_data) + return reader_read(r, p) }, impl_read_at = proc(s: io.Stream, p: []byte, off: i64) -> (n: int, err: io.Error) { - r := (^Reader)(s.stream_data); - return reader_read_at(r, p, off); + r := (^Reader)(s.stream_data) + return reader_read_at(r, p, off) }, impl_read_byte = proc(s: io.Stream) -> (byte, io.Error) { - r := (^Reader)(s.stream_data); - return reader_read_byte(r); + r := (^Reader)(s.stream_data) + return reader_read_byte(r) }, impl_unread_byte = proc(s: io.Stream) -> io.Error { - r := (^Reader)(s.stream_data); - return reader_unread_byte(r); + r := (^Reader)(s.stream_data) + return reader_unread_byte(r) }, impl_read_rune = proc(s: io.Stream) -> (ch: rune, size: int, err: io.Error) { - r := (^Reader)(s.stream_data); - return reader_read_rune(r); + r := (^Reader)(s.stream_data) + return reader_read_rune(r) }, impl_unread_rune = proc(s: io.Stream) -> io.Error { - r := (^Reader)(s.stream_data); - return reader_unread_rune(r); + r := (^Reader)(s.stream_data) + return reader_unread_rune(r) }, impl_seek = proc(s: io.Stream, offset: i64, whence: io.Seek_From) -> (i64, io.Error) { - r := (^Reader)(s.stream_data); - return reader_seek(r, offset, whence); + r := (^Reader)(s.stream_data) + return reader_seek(r, offset, whence) }, impl_write_to = proc(s: io.Stream, w: io.Writer) -> (n: i64, err: io.Error) { - r := (^Reader)(s.stream_data); - return reader_write_to(r, w); + r := (^Reader)(s.stream_data) + return reader_write_to(r, w) }, -}; +} diff --git a/core/strings/strings.odin b/core/strings/strings.odin index 70ceca26a..2919a6e47 100644 --- a/core/strings/strings.odin +++ b/core/strings/strings.odin @@ -6,67 +6,67 @@ import "core:unicode" import "core:unicode/utf8" clone :: proc(s: string, allocator := context.allocator, loc := #caller_location) -> string { - c := make([]byte, len(s)+1, allocator, loc); - copy(c, s); - c[len(s)] = 0; - return string(c[:len(s)]); + c := make([]byte, len(s)+1, allocator, loc) + copy(c, s) + c[len(s)] = 0 + return string(c[:len(s)]) } clone_to_cstring :: proc(s: string, allocator := context.allocator, loc := #caller_location) -> cstring { - c := make([]byte, len(s)+1, allocator, loc); - copy(c, s); - c[len(s)] = 0; - return cstring(&c[0]); + c := make([]byte, len(s)+1, allocator, loc) + copy(c, s) + c[len(s)] = 0 + return cstring(&c[0]) } string_from_ptr :: proc(ptr: ^byte, len: int) -> string { - return transmute(string)mem.Raw_String{ptr, len}; + return transmute(string)mem.Raw_String{ptr, len} } string_from_nul_terminated_ptr :: proc(ptr: ^byte, len: int) -> string { - s := transmute(string)mem.Raw_String{ptr, len}; - s = truncate_to_byte(s, 0); - return s; + s := transmute(string)mem.Raw_String{ptr, len} + s = truncate_to_byte(s, 0) + return s } ptr_from_string :: proc(str: string) -> ^byte { - d := transmute(mem.Raw_String)str; - return d.data; + d := transmute(mem.Raw_String)str + return d.data } unsafe_string_to_cstring :: proc(str: string) -> cstring { - d := transmute(mem.Raw_String)str; - return cstring(d.data); + d := transmute(mem.Raw_String)str + return cstring(d.data) } truncate_to_byte :: proc(str: string, b: byte) -> string { - n := index_byte(str, b); + n := index_byte(str, b) if n < 0 { - n = len(str); + n = len(str) } - return str[:n]; + return str[:n] } truncate_to_rune :: proc(str: string, r: rune) -> string { - n := index_rune(str, r); + n := index_rune(str, r) if n < 0 { - n = len(str); + n = len(str) } - return str[:n]; + return str[:n] } clone_from_bytes :: proc(s: []byte, allocator := context.allocator, loc := #caller_location) -> string { - c := make([]byte, len(s)+1, allocator, loc); - copy(c, s); - c[len(s)] = 0; - return string(c[:len(s)]); + c := make([]byte, len(s)+1, allocator, loc) + copy(c, s) + c[len(s)] = 0 + return string(c[:len(s)]) } clone_from_cstring :: proc(s: cstring, allocator := context.allocator, loc := #caller_location) -> string { - return clone(string(s), allocator, loc); + return clone(string(s), allocator, loc) } clone_from_ptr :: proc(ptr: ^byte, len: int, allocator := context.allocator, loc := #caller_location) -> string { - s := string_from_ptr(ptr, len); - return clone(s, allocator, loc); + s := string_from_ptr(ptr, len) + return clone(s, allocator, loc) } clone_from :: proc{ @@ -74,129 +74,129 @@ clone_from :: proc{ clone_from_bytes, clone_from_cstring, clone_from_ptr, -}; +} clone_from_cstring_bounded :: proc(ptr: cstring, len: int, allocator := context.allocator, loc := #caller_location) -> string { - s := string_from_ptr((^u8)(ptr), len); - s = truncate_to_byte(s, 0); - return clone(s, allocator, loc); + s := string_from_ptr((^u8)(ptr), len) + s = truncate_to_byte(s, 0) + return clone(s, allocator, loc) } // Compares two strings, returning a value representing which one comes first lexiographically. // -1 for `a`; 1 for `b`, or 0 if they are equal. compare :: proc(lhs, rhs: string) -> int { - return mem.compare(transmute([]byte)lhs, transmute([]byte)rhs); + return mem.compare(transmute([]byte)lhs, transmute([]byte)rhs) } contains_rune :: proc(s: string, r: rune) -> int { for c, offset in s { if c == r { - return offset; + return offset } } - return -1; + return -1 } contains :: proc(s, substr: string) -> bool { - return index(s, substr) >= 0; + return index(s, substr) >= 0 } contains_any :: proc(s, chars: string) -> bool { - return index_any(s, chars) >= 0; + return index_any(s, chars) >= 0 } rune_count :: proc(s: string) -> int { - return utf8.rune_count_in_string(s); + return utf8.rune_count_in_string(s) } equal_fold :: proc(u, v: string) -> bool { - s, t := u, v; + s, t := u, v loop: for s != "" && t != "" { - sr, tr: rune; + sr, tr: rune if s[0] < utf8.RUNE_SELF { - sr, s = rune(s[0]), s[1:]; + sr, s = rune(s[0]), s[1:] } else { - r, size := utf8.decode_rune_in_string(s); - sr, s = r, s[size:]; + r, size := utf8.decode_rune_in_string(s) + sr, s = r, s[size:] } if t[0] < utf8.RUNE_SELF { - tr, t = rune(t[0]), t[1:]; + tr, t = rune(t[0]), t[1:] } else { - r, size := utf8.decode_rune_in_string(t); - tr, t = r, t[size:]; + r, size := utf8.decode_rune_in_string(t) + tr, t = r, t[size:] } if tr == sr { // easy case - continue loop; + continue loop } if tr < sr { - tr, sr = sr, tr; + tr, sr = sr, tr } if tr < utf8.RUNE_SELF { switch sr { case 'A'..='Z': if tr == (sr+'a')-'A' { - continue loop; + continue loop } } - return false; + return false } // TODO(bill): Unicode folding - return false; + return false } - return s == t; + return s == t } has_prefix :: proc(s, prefix: string) -> bool { - return len(s) >= len(prefix) && s[0:len(prefix)] == prefix; + return len(s) >= len(prefix) && s[0:len(prefix)] == prefix } has_suffix :: proc(s, suffix: string) -> bool { - return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix; + return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix } join :: proc(a: []string, sep: string, allocator := context.allocator) -> string { if len(a) == 0 { - return ""; + return "" } - n := len(sep) * (len(a) - 1); + n := len(sep) * (len(a) - 1) for s in a { - n += len(s); + n += len(s) } - b := make([]byte, n, allocator); - i := copy(b, a[0]); + b := make([]byte, n, allocator) + i := copy(b, a[0]) for s in a[1:] { - i += copy(b[i:], sep); - i += copy(b[i:], s); + i += copy(b[i:], sep) + i += copy(b[i:], s) } - return string(b); + return string(b) } concatenate :: proc(a: []string, allocator := context.allocator) -> string { if len(a) == 0 { - return ""; + return "" } - n := 0; + n := 0 for s in a { - n += len(s); + n += len(s) } - b := make([]byte, n, allocator); - i := 0; + b := make([]byte, n, allocator) + i := 0 for s in a { - i += copy(b[i:], s); + i += copy(b[i:], s) } - return string(b); + return string(b) } /* @@ -204,153 +204,153 @@ concatenate :: proc(a: []string, allocator := context.allocator) -> string { If `rune_length` <= 0, then it'll return the remainder of the string starting with `rune_offset`. */ cut :: proc(s: string, rune_offset := int(0), rune_length := int(0), allocator := context.allocator) -> (res: string) { - s := s; rune_length := rune_length; - l := utf8.rune_count_in_string(s); + s := s; rune_length := rune_length + l := utf8.rune_count_in_string(s) if rune_offset >= l { return ""; } if rune_offset == 0 && rune_length <= 0 { - return clone(s, allocator); + return clone(s, allocator) } if rune_length == 0 { rune_length = l; } - bytes_needed := min(rune_length * 4, len(s)); - buf := make([]u8, bytes_needed, allocator); + bytes_needed := min(rune_length * 4, len(s)) + buf := make([]u8, bytes_needed, allocator) - byte_offset := 0; + byte_offset := 0 for i := 0; i < l; i += 1 { - _, w := utf8.decode_rune_in_string(s); + _, w := utf8.decode_rune_in_string(s) if i >= rune_offset { for j := 0; j < w; j += 1 { - buf[byte_offset+j] = s[j]; + buf[byte_offset+j] = s[j] } - byte_offset += w; + byte_offset += w } if rune_length > 0 { if i == rune_offset + rune_length - 1 { break; } } - s = s[w:]; + s = s[w:] } - return string(buf[:byte_offset]); + return string(buf[:byte_offset]) } @private _split :: proc(s_, sep: string, sep_save, n_: int, allocator := context.allocator) -> []string { - s, n := s_, n_; + s, n := s_, n_ if n == 0 { - return nil; + return nil } if sep == "" { - l := utf8.rune_count_in_string(s); + l := utf8.rune_count_in_string(s) if n < 0 || n > l { - n = l; + n = l } - res := make([dynamic]string, n, allocator); + res := make([dynamic]string, n, allocator) for i := 0; i < n-1; i += 1 { - _, w := utf8.decode_rune_in_string(s); - res[i] = s[:w]; - s = s[w:]; + _, w := utf8.decode_rune_in_string(s) + res[i] = s[:w] + s = s[w:] } if n > 0 { - res[n-1] = s; + res[n-1] = s } - return res[:]; + return res[:] } if n < 0 { - n = count(s, sep) + 1; + n = count(s, sep) + 1 } - res := make([dynamic]string, n, allocator); + res := make([dynamic]string, n, allocator) - n -= 1; + n -= 1 - i := 0; + i := 0 for ; i < n; i += 1 { - m := index(s, sep); + m := index(s, sep) if m < 0 { - break; + break } - res[i] = s[:m+sep_save]; - s = s[m+len(sep):]; + res[i] = s[:m+sep_save] + s = s[m+len(sep):] } - res[i] = s; + res[i] = s - return res[:i+1]; + return res[:i+1] } split :: proc(s, sep: string, allocator := context.allocator) -> []string { - return _split(s, sep, 0, -1, allocator); + return _split(s, sep, 0, -1, allocator) } split_n :: proc(s, sep: string, n: int, allocator := context.allocator) -> []string { - return _split(s, sep, 0, n, allocator); + return _split(s, sep, 0, n, allocator) } split_after :: proc(s, sep: string, allocator := context.allocator) -> []string { - return _split(s, sep, len(sep), -1, allocator); + return _split(s, sep, len(sep), -1, allocator) } split_after_n :: proc(s, sep: string, n: int, allocator := context.allocator) -> []string { - return _split(s, sep, len(sep), n, allocator); + return _split(s, sep, len(sep), n, allocator) } @private _split_iterator :: proc(s: ^string, sep: string, sep_save, n: int) -> (res: string, ok: bool) { - s, n := s, n; + s, n := s, n if n == 0 { - return; + return } if sep == "" { - res = s[:]; - ok = true; - s^ = s[len(s):]; - return; + res = s[:] + ok = true + s^ = s[len(s):] + return } if n < 0 { - n = count(s^, sep) + 1; + n = count(s^, sep) + 1 } - n -= 1; + n -= 1 - i := 0; + i := 0 for ; i < n; i += 1 { - m := index(s^, sep); + m := index(s^, sep) if m < 0 { - break; + break } - res = s[:m+sep_save]; - ok = true; - s^ = s[m+len(sep):]; - return; + res = s[:m+sep_save] + ok = true + s^ = s[m+len(sep):] + return } - res = s[:]; - ok = res != ""; - s^ = s[len(s):]; - return; + res = s[:] + ok = res != "" + s^ = s[len(s):] + return } split_iterator :: proc(s: ^string, sep: string) -> (string, bool) { - return _split_iterator(s, sep, 0, -1); + return _split_iterator(s, sep, 0, -1) } split_n_iterator :: proc(s: ^string, sep: string, n: int) -> (string, bool) { - return _split_iterator(s, sep, 0, n); + return _split_iterator(s, sep, 0, n) } split_after_iterator :: proc(s: ^string, sep: string) -> (string, bool) { - return _split_iterator(s, sep, len(sep), -1); + return _split_iterator(s, sep, len(sep), -1) } split_after_n_iterator :: proc(s: ^string, sep: string, n: int) -> (string, bool) { - return _split_iterator(s, sep, len(sep), n); + return _split_iterator(s, sep, len(sep), n) } @@ -361,597 +361,597 @@ split_after_n_iterator :: proc(s: ^string, sep: string, n: int) -> (string, bool index_byte :: proc(s: string, c: byte) -> int { for i := 0; i < len(s); i += 1 { if s[i] == c { - return i; + return i } } - return -1; + return -1 } // Returns -1 if c is not present last_index_byte :: proc(s: string, c: byte) -> int { for i := len(s)-1; i >= 0; i -= 1 { if s[i] == c { - return i; + return i } } - return -1; + return -1 } -@private PRIME_RABIN_KARP :: 16777619; +@private PRIME_RABIN_KARP :: 16777619 index :: proc(s, substr: string) -> int { hash_str_rabin_karp :: proc(s: string) -> (hash: u32 = 0, pow: u32 = 1) { for i := 0; i < len(s); i += 1 { - hash = hash*PRIME_RABIN_KARP + u32(s[i]); + hash = hash*PRIME_RABIN_KARP + u32(s[i]) } - sq := u32(PRIME_RABIN_KARP); + sq := u32(PRIME_RABIN_KARP) for i := len(s); i > 0; i >>= 1 { if (i & 1) != 0 { - pow *= sq; + pow *= sq } - sq *= sq; + sq *= sq } - return; + return } - n := len(substr); + n := len(substr) switch { case n == 0: - return 0; + return 0 case n == 1: - return index_byte(s, substr[0]); + return index_byte(s, substr[0]) case n == len(s): if s == substr { - return 0; + return 0 } - return -1; + return -1 case n > len(s): - return -1; + return -1 } - hash, pow := hash_str_rabin_karp(substr); - h: u32; + hash, pow := hash_str_rabin_karp(substr) + h: u32 for i := 0; i < n; i += 1 { - h = h*PRIME_RABIN_KARP + u32(s[i]); + h = h*PRIME_RABIN_KARP + u32(s[i]) } if h == hash && s[:n] == substr { - return 0; + return 0 } for i := n; i < len(s); /**/ { - h *= PRIME_RABIN_KARP; - h += u32(s[i]); - h -= pow * u32(s[i-n]); - i += 1; + h *= PRIME_RABIN_KARP + h += u32(s[i]) + h -= pow * u32(s[i-n]) + i += 1 if h == hash && s[i-n:i] == substr { - return i - n; + return i - n } } - return -1; + return -1 } last_index :: proc(s, substr: string) -> int { hash_str_rabin_karp_reverse :: proc(s: string) -> (hash: u32 = 0, pow: u32 = 1) { for i := len(s) - 1; i >= 0; i -= 1 { - hash = hash*PRIME_RABIN_KARP + u32(s[i]); + hash = hash*PRIME_RABIN_KARP + u32(s[i]) } - sq := u32(PRIME_RABIN_KARP); + sq := u32(PRIME_RABIN_KARP) for i := len(s); i > 0; i >>= 1 { if (i & 1) != 0 { - pow *= sq; + pow *= sq } - sq *= sq; + sq *= sq } - return; + return } - n := len(substr); + n := len(substr) switch { case n == 0: - return len(s); + return len(s) case n == 1: - return last_index_byte(s, substr[0]); + return last_index_byte(s, substr[0]) case n == len(s): - return 0 if substr == s else -1; + return 0 if substr == s else -1 case n > len(s): - return -1; + return -1 } - hash, pow := hash_str_rabin_karp_reverse(substr); - last := len(s) - n; - h: u32; + hash, pow := hash_str_rabin_karp_reverse(substr) + last := len(s) - n + h: u32 for i := len(s)-1; i >= last; i -= 1 { - h = h*PRIME_RABIN_KARP + u32(s[i]); + h = h*PRIME_RABIN_KARP + u32(s[i]) } if h == hash && s[last:] == substr { - return last; + return last } for i := last-1; i >= 0; i -= 1 { - h *= PRIME_RABIN_KARP; - h += u32(s[i]); - h -= pow * u32(s[i+n]); + h *= PRIME_RABIN_KARP + h += u32(s[i]) + h -= pow * u32(s[i+n]) if h == hash && s[i:i+n] == substr { - return i; + return i } } - return -1; + return -1 } index_any :: proc(s, chars: string) -> int { if chars == "" { - return -1; + return -1 } if len(chars) == 1 { - r := rune(chars[0]); + r := rune(chars[0]) if r >= utf8.RUNE_SELF { - r = utf8.RUNE_ERROR; + r = utf8.RUNE_ERROR } - return index_rune(s, r); + return index_rune(s, r) } if len(s) > 8 { if as, ok := ascii_set_make(chars); ok { for i in 0..<len(s) { if ascii_set_contains(as, s[i]) { - return i; + return i } } - return -1; + return -1 } } for c, i in chars { if index_rune(chars, c) >= 0 { - return i; + return i } } - return -1; + return -1 } last_index_any :: proc(s, chars: string) -> int { if chars == "" { - return -1; + return -1 } if len(s) == 1 { - r := rune(s[0]); + r := rune(s[0]) if r >= utf8.RUNE_SELF { - r = utf8.RUNE_ERROR; + r = utf8.RUNE_ERROR } - return index_rune(chars, r); + return index_rune(chars, r) } if len(s) > 8 { if as, ok := ascii_set_make(chars); ok { for i := len(s)-1; i >= 0; i -= 1 { if ascii_set_contains(as, s[i]) { - return i; + return i } } - return -1; + return -1 } } if len(chars) == 1 { - r := rune(chars[0]); + r := rune(chars[0]) if r >= utf8.RUNE_SELF { - r = utf8.RUNE_ERROR; + r = utf8.RUNE_ERROR } for i := len(s); i > 0; /**/ { - c, w := utf8.decode_last_rune_in_string(s[:i]); - i -= w; + c, w := utf8.decode_last_rune_in_string(s[:i]) + i -= w if c == r { - return i; + return i } } - return -1; + return -1 } for i := len(s); i > 0; /**/ { - r, w := utf8.decode_last_rune_in_string(s[:i]); - i -= w; + r, w := utf8.decode_last_rune_in_string(s[:i]) + i -= w if index_rune(chars, r) >= 0 { - return i; + return i } } - return -1; + return -1 } count :: proc(s, substr: string) -> int { if len(substr) == 0 { // special case - return rune_count(s) + 1; + return rune_count(s) + 1 } if len(substr) == 1 { - c := substr[0]; + c := substr[0] switch len(s) { case 0: - return 0; + return 0 case 1: - return int(s[0] == c); + return int(s[0] == c) } - n := 0; + n := 0 for i := 0; i < len(s); i += 1 { if s[i] == c { - n += 1; + n += 1 } } - return n; + return n } // TODO(bill): Use a non-brute for approach - n := 0; - str := s; + n := 0 + str := s for { - i := index(str, substr); + i := index(str, substr) if i == -1 { - return n; + return n } - n += 1; - str = str[i+len(substr):]; + n += 1 + str = str[i+len(substr):] } - return n; + return n } repeat :: proc(s: string, count: int, allocator := context.allocator) -> string { if count < 0 { - panic("strings: negative repeat count"); + panic("strings: negative repeat count") } else if count > 0 && (len(s)*count)/count != len(s) { - panic("strings: repeat count will cause an overflow"); + panic("strings: repeat count will cause an overflow") } - b := make([]byte, len(s)*count, allocator); - i := copy(b, s); + b := make([]byte, len(s)*count, allocator) + i := copy(b, s) for i < len(b) { // 2^N trick to reduce the need to copy - copy(b[i:], b[:i]); - i *= 2; + copy(b[i:], b[:i]) + i *= 2 } - return string(b); + return string(b) } replace_all :: proc(s, old, new: string, allocator := context.allocator) -> (output: string, was_allocation: bool) { - return replace(s, old, new, -1, allocator); + return replace(s, old, new, -1, allocator) } // if n < 0, no limit on the number of replacements replace :: proc(s, old, new: string, n: int, allocator := context.allocator) -> (output: string, was_allocation: bool) { if old == new || n == 0 { - was_allocation = false; - output = s; - return; + was_allocation = false + output = s + return } - byte_count := n; + byte_count := n if m := count(s, old); m == 0 { - was_allocation = false; - output = s; - return; + was_allocation = false + output = s + return } else if n < 0 || m < n { - byte_count = m; + byte_count = m } - t := make([]byte, len(s) + byte_count*(len(new) - len(old)), allocator); - was_allocation = true; + t := make([]byte, len(s) + byte_count*(len(new) - len(old)), allocator) + was_allocation = true - w := 0; - start := 0; + w := 0 + start := 0 for i := 0; i < byte_count; i += 1 { - j := start; + j := start if len(old) == 0 { if i > 0 { - _, width := utf8.decode_rune_in_string(s[start:]); - j += width; + _, width := utf8.decode_rune_in_string(s[start:]) + j += width } } else { - j += index(s[start:], old); + j += index(s[start:], old) } - w += copy(t[w:], s[start:j]); - w += copy(t[w:], new); - start = j + len(old); + w += copy(t[w:], s[start:j]) + w += copy(t[w:], new) + start = j + len(old) } - w += copy(t[w:], s[start:]); - output = string(t[0:w]); - return; + w += copy(t[w:], s[start:]) + output = string(t[0:w]) + return } remove :: proc(s, key: string, n: int, allocator := context.allocator) -> (output: string, was_allocation: bool) { - return replace(s, key, "", n, allocator); + return replace(s, key, "", n, allocator) } remove_all :: proc(s, key: string, allocator := context.allocator) -> (output: string, was_allocation: bool) { - return remove(s, key, -1, allocator); + return remove(s, key, -1, allocator) } -@(private) _ascii_space := [256]u8{'\t' = 1, '\n' = 1, '\v' = 1, '\f' = 1, '\r' = 1, ' ' = 1}; +@(private) _ascii_space := [256]u8{'\t' = 1, '\n' = 1, '\v' = 1, '\f' = 1, '\r' = 1, ' ' = 1} is_ascii_space :: proc(r: rune) -> bool { if r < utf8.RUNE_SELF { - return _ascii_space[u8(r)] != 0; + return _ascii_space[u8(r)] != 0 } - return false; + return false } is_space :: proc(r: rune) -> bool { if r < 0x2000 { switch r { case '\t', '\n', '\v', '\f', '\r', ' ', 0x85, 0xa0, 0x1680: - return true; + return true } } else { if r <= 0x200a { - return true; + return true } switch r { case 0x2028, 0x2029, 0x202f, 0x205f, 0x3000: - return true; + return true } } - return false; + return false } is_null :: proc(r: rune) -> bool { - return r == 0x0000; + return r == 0x0000 } index_proc :: proc(s: string, p: proc(rune) -> bool, truth := true) -> int { for r, i in s { if p(r) == truth { - return i; + return i } } - return -1; + return -1 } index_proc_with_state :: proc(s: string, p: proc(rawptr, rune) -> bool, state: rawptr, truth := true) -> int { for r, i in s { if p(state, r) == truth { - return i; + return i } } - return -1; + return -1 } last_index_proc :: proc(s: string, p: proc(rune) -> bool, truth := true) -> int { // TODO(bill): Probably use Rabin-Karp Search for i := len(s); i > 0; { - r, size := utf8.decode_last_rune_in_string(s[:i]); - i -= size; + r, size := utf8.decode_last_rune_in_string(s[:i]) + i -= size if p(r) == truth { - return i; + return i } } - return -1; + return -1 } last_index_proc_with_state :: proc(s: string, p: proc(rawptr, rune) -> bool, state: rawptr, truth := true) -> int { // TODO(bill): Probably use Rabin-Karp Search for i := len(s); i > 0; { - r, size := utf8.decode_last_rune_in_string(s[:i]); - i -= size; + r, size := utf8.decode_last_rune_in_string(s[:i]) + i -= size if p(state, r) == truth { - return i; + return i } } - return -1; + return -1 } trim_left_proc :: proc(s: string, p: proc(rune) -> bool) -> string { - i := index_proc(s, p, false); + i := index_proc(s, p, false) if i == -1 { - return ""; + return "" } - return s[i:]; + return s[i:] } index_rune :: proc(s: string, r: rune) -> int { switch { case 0 <= r && r < utf8.RUNE_SELF: - return index_byte(s, byte(r)); + return index_byte(s, byte(r)) case r == utf8.RUNE_ERROR: for c, i in s { if c == utf8.RUNE_ERROR { - return i; + return i } } - return -1; + return -1 case !utf8.valid_rune(r): - return -1; + return -1 } - b, w := utf8.encode_rune(r); - return index(s, string(b[:w])); + b, w := utf8.encode_rune(r) + return index(s, string(b[:w])) } trim_left_proc_with_state :: proc(s: string, p: proc(rawptr, rune) -> bool, state: rawptr) -> string { - i := index_proc_with_state(s, p, state, false); + i := index_proc_with_state(s, p, state, false) if i == -1 { - return ""; + return "" } - return s[i:]; + return s[i:] } trim_right_proc :: proc(s: string, p: proc(rune) -> bool) -> string { - i := last_index_proc(s, p, false); + i := last_index_proc(s, p, false) if i >= 0 && s[i] >= utf8.RUNE_SELF { - _, w := utf8.decode_rune_in_string(s[i:]); - i += w; + _, w := utf8.decode_rune_in_string(s[i:]) + i += w } else { - i += 1; + i += 1 } - return s[0:i]; + return s[0:i] } trim_right_proc_with_state :: proc(s: string, p: proc(rawptr, rune) -> bool, state: rawptr) -> string { - i := last_index_proc_with_state(s, p, state, false); + i := last_index_proc_with_state(s, p, state, false) if i >= 0 && s[i] >= utf8.RUNE_SELF { - _, w := utf8.decode_rune_in_string(s[i:]); - i += w; + _, w := utf8.decode_rune_in_string(s[i:]) + i += w } else { - i += 1; + i += 1 } - return s[0:i]; + return s[0:i] } is_in_cutset :: proc(state: rawptr, r: rune) -> bool { if state == nil { - return false; + return false } - cutset := (^string)(state)^; + cutset := (^string)(state)^ for c in cutset { if r == c { - return true; + return true } } - return false; + return false } trim_left :: proc(s: string, cutset: string) -> string { if s == "" || cutset == "" { - return s; + return s } - state := cutset; - return trim_left_proc_with_state(s, is_in_cutset, &state); + state := cutset + return trim_left_proc_with_state(s, is_in_cutset, &state) } trim_right :: proc(s: string, cutset: string) -> string { if s == "" || cutset == "" { - return s; + return s } - state := cutset; - return trim_right_proc_with_state(s, is_in_cutset, &state); + state := cutset + return trim_right_proc_with_state(s, is_in_cutset, &state) } trim :: proc(s: string, cutset: string) -> string { - return trim_right(trim_left(s, cutset), cutset); + return trim_right(trim_left(s, cutset), cutset) } trim_left_space :: proc(s: string) -> string { - return trim_left_proc(s, is_space); + return trim_left_proc(s, is_space) } trim_right_space :: proc(s: string) -> string { - return trim_right_proc(s, is_space); + return trim_right_proc(s, is_space) } trim_space :: proc(s: string) -> string { - return trim_right_space(trim_left_space(s)); + return trim_right_space(trim_left_space(s)) } trim_left_null :: proc(s: string) -> string { - return trim_left_proc(s, is_null); + return trim_left_proc(s, is_null) } trim_right_null :: proc(s: string) -> string { - return trim_right_proc(s, is_null); + return trim_right_proc(s, is_null) } trim_null :: proc(s: string) -> string { - return trim_right_null(trim_left_null(s)); + return trim_right_null(trim_left_null(s)) } trim_prefix :: proc(s, prefix: string) -> string { if has_prefix(s, prefix) { - return s[len(prefix):]; + return s[len(prefix):] } - return s; + return s } trim_suffix :: proc(s, suffix: string) -> string { if has_suffix(s, suffix) { - return s[:len(s)-len(suffix)]; + return s[:len(s)-len(suffix)] } - return s; + return s } split_multi :: proc(s: string, substrs: []string, skip_empty := false, allocator := context.allocator) -> []string #no_bounds_check { if s == "" || len(substrs) <= 0 { - return nil; + return nil } - sublen := len(substrs[0]); + sublen := len(substrs[0]) for substr in substrs[1:] { - sublen = min(sublen, len(substr)); + sublen = min(sublen, len(substr)) } - shared := len(s) - sublen; + shared := len(s) - sublen if shared <= 0 { - return nil; + return nil } // number, index, last - n, i, l := 0, 0, 0; + n, i, l := 0, 0, 0 // count results first_pass: for i <= shared { for substr in substrs { if s[i:i+sublen] == substr { if !skip_empty || i - l > 0 { - n += 1; + n += 1 } - i += sublen; - l = i; + i += sublen + l = i - continue first_pass; + continue first_pass } } - _, skip := utf8.decode_rune_in_string(s[i:]); - i += skip; + _, skip := utf8.decode_rune_in_string(s[i:]) + i += skip } if !skip_empty || len(s) - l > 0 { - n += 1; + n += 1 } if n < 1 { // no results - return nil; + return nil } - buf := make([]string, n, allocator); + buf := make([]string, n, allocator) - n, i, l = 0, 0, 0; + n, i, l = 0, 0, 0 // slice results second_pass: for i <= shared { for substr in substrs { if s[i:i+sublen] == substr { if !skip_empty || i - l > 0 { - buf[n] = s[l:i]; - n += 1; + buf[n] = s[l:i] + n += 1 } - i += sublen; - l = i; + i += sublen + l = i - continue second_pass; + continue second_pass } } - _, skip := utf8.decode_rune_in_string(s[i:]); - i += skip; + _, skip := utf8.decode_rune_in_string(s[i:]) + i += skip } if !skip_empty || len(s) - l > 0 { - buf[n] = s[l:]; + buf[n] = s[l:] } - return buf; + return buf } @@ -959,51 +959,51 @@ split_multi :: proc(s: string, substrs: []string, skip_empty := false, allocator split_multi_iterator :: proc(s: ^string, substrs: []string, skip_empty := false) -> (string, bool) #no_bounds_check { if s == nil || s^ == "" || len(substrs) <= 0 { - return "", false; + return "", false } - sublen := len(substrs[0]); + sublen := len(substrs[0]) for substr in substrs[1:] { - sublen = min(sublen, len(substr)); + sublen = min(sublen, len(substr)) } - shared := len(s) - sublen; + shared := len(s) - sublen if shared <= 0 { - return "", false; + return "", false } // index, last - i, l := 0, 0; + i, l := 0, 0 loop: for i <= shared { for substr in substrs { if s[i:i+sublen] == substr { if !skip_empty || i - l > 0 { - res := s[l:i]; - s^ = s[i:]; - return res, true; + res := s[l:i] + s^ = s[i:] + return res, true } - i += sublen; - l = i; + i += sublen + l = i - continue loop; + continue loop } } - _, skip := utf8.decode_rune_in_string(s[i:]); - i += skip; + _, skip := utf8.decode_rune_in_string(s[i:]) + i += skip } if !skip_empty || len(s) - l > 0 { - res := s[l:]; - s^ = s[len(s):]; - return res, true; + res := s[l:] + s^ = s[len(s):] + return res, true } - return "", false; + return "", false } @@ -1014,177 +1014,177 @@ split_multi_iterator :: proc(s: ^string, substrs: []string, skip_empty := false) // scrub scruvs invalid utf-8 characters and replaces them with the replacement string // Adjacent invalid bytes are only replaced once scrub :: proc(s: string, replacement: string, allocator := context.allocator) -> string { - str := s; - b: Builder; - init_builder(&b, 0, len(s), allocator); + str := s + b: Builder + init_builder(&b, 0, len(s), allocator) - has_error := false; - cursor := 0; - origin := str; + has_error := false + cursor := 0 + origin := str for len(str) > 0 { - r, w := utf8.decode_rune_in_string(str); + r, w := utf8.decode_rune_in_string(str) if r == utf8.RUNE_ERROR { if !has_error { - has_error = true; - write_string(&b, origin[:cursor]); + has_error = true + write_string(&b, origin[:cursor]) } } else if has_error { - has_error = false; - write_string(&b, replacement); + has_error = false + write_string(&b, replacement) - origin = origin[cursor:]; - cursor = 0; + origin = origin[cursor:] + cursor = 0 } - cursor += w; - str = str[w:]; + cursor += w + str = str[w:] } - return to_string(b); + return to_string(b) } reverse :: proc(s: string, allocator := context.allocator) -> string { - str := s; - n := len(str); - buf := make([]byte, n); - i := n; + str := s + n := len(str) + buf := make([]byte, n) + i := n for len(str) > 0 { - _, w := utf8.decode_rune_in_string(str); - i -= w; - copy(buf[i:], str[:w]); - str = str[w:]; + _, w := utf8.decode_rune_in_string(str) + i -= w + copy(buf[i:], str[:w]) + str = str[w:] } - return string(buf); + return string(buf) } expand_tabs :: proc(s: string, tab_size: int, allocator := context.allocator) -> string { if tab_size <= 0 { - panic("tab size must be positive"); + panic("tab size must be positive") } if s == "" { - return ""; + return "" } - b: Builder; - init_builder(&b, allocator); - writer := to_writer(&b); - str := s; - column: int; + b: Builder + init_builder(&b, allocator) + writer := to_writer(&b) + str := s + column: int for len(str) > 0 { - r, w := utf8.decode_rune_in_string(str); + r, w := utf8.decode_rune_in_string(str) if r == '\t' { - expand := tab_size - column%tab_size; + expand := tab_size - column%tab_size for i := 0; i < expand; i += 1 { - io.write_byte(writer, ' '); + io.write_byte(writer, ' ') } - column += expand; + column += expand } else { if r == '\n' { - column = 0; + column = 0 } else { - column += w; + column += w } - io.write_rune(writer, r); + io.write_rune(writer, r) } - str = str[w:]; + str = str[w:] } - return to_string(b); + return to_string(b) } partition :: proc(str, sep: string) -> (head, match, tail: string) { - i := index(str, sep); + i := index(str, sep) if i == -1 { - head = str; - return; + head = str + return } - head = str[:i]; - match = str[i:i+len(sep)]; - tail = str[i+len(sep):]; - return; + head = str[:i] + match = str[i:i+len(sep)] + tail = str[i+len(sep):] + return } -center_justify :: centre_justify; // NOTE(bill): Because Americans exist +center_justify :: centre_justify // NOTE(bill): Because Americans exist // centre_justify returns a string with a pad string at boths sides if the str's rune length is smaller than length centre_justify :: proc(str: string, length: int, pad: string, allocator := context.allocator) -> string { - n := rune_count(str); + n := rune_count(str) if n >= length || pad == "" { - return clone(str, allocator); + return clone(str, allocator) } - remains := length-1; - pad_len := rune_count(pad); + remains := length-1 + pad_len := rune_count(pad) - b: Builder; - init_builder(&b, allocator); - grow_builder(&b, len(str) + (remains/pad_len + 1)*len(pad)); + b: Builder + init_builder(&b, allocator) + grow_builder(&b, len(str) + (remains/pad_len + 1)*len(pad)) - w := to_writer(&b); + w := to_writer(&b) - write_pad_string(w, pad, pad_len, remains/2); - io.write_string(w, str); - write_pad_string(w, pad, pad_len, (remains+1)/2); + write_pad_string(w, pad, pad_len, remains/2) + io.write_string(w, str) + write_pad_string(w, pad, pad_len, (remains+1)/2) - return to_string(b); + return to_string(b) } // left_justify returns a string with a pad string at left side if the str's rune length is smaller than length left_justify :: proc(str: string, length: int, pad: string, allocator := context.allocator) -> string { - n := rune_count(str); + n := rune_count(str) if n >= length || pad == "" { - return clone(str, allocator); + return clone(str, allocator) } - remains := length-1; - pad_len := rune_count(pad); + remains := length-1 + pad_len := rune_count(pad) - b: Builder; - init_builder(&b, allocator); - grow_builder(&b, len(str) + (remains/pad_len + 1)*len(pad)); + b: Builder + init_builder(&b, allocator) + grow_builder(&b, len(str) + (remains/pad_len + 1)*len(pad)) - w := to_writer(&b); + w := to_writer(&b) - io.write_string(w, str); - write_pad_string(w, pad, pad_len, remains); + io.write_string(w, str) + write_pad_string(w, pad, pad_len, remains) - return to_string(b); + return to_string(b) } // right_justify returns a string with a pad string at right side if the str's rune length is smaller than length right_justify :: proc(str: string, length: int, pad: string, allocator := context.allocator) -> string { - n := rune_count(str); + n := rune_count(str) if n >= length || pad == "" { - return clone(str, allocator); + return clone(str, allocator) } - remains := length-1; - pad_len := rune_count(pad); + remains := length-1 + pad_len := rune_count(pad) - b: Builder; - init_builder(&b, allocator); - grow_builder(&b, len(str) + (remains/pad_len + 1)*len(pad)); + b: Builder + init_builder(&b, allocator) + grow_builder(&b, len(str) + (remains/pad_len + 1)*len(pad)) - w := to_writer(&b); + w := to_writer(&b) - write_pad_string(w, pad, pad_len, remains); - io.write_string(w, str); + write_pad_string(w, pad, pad_len, remains) + io.write_string(w, str) - return to_string(b); + return to_string(b) } @@ -1192,19 +1192,19 @@ right_justify :: proc(str: string, length: int, pad: string, allocator := contex @private write_pad_string :: proc(w: io.Writer, pad: string, pad_len, remains: int) { - repeats := remains / pad_len; + repeats := remains / pad_len for i := 0; i < repeats; i += 1 { - io.write_string(w, pad); + io.write_string(w, pad) } - n := remains % pad_len; - p := pad; + n := remains % pad_len + p := pad for i := 0; i < n; i += 1 { - r, width := utf8.decode_rune_in_string(p); - io.write_rune(w, r); - p = p[width:]; + r, width := utf8.decode_rune_in_string(p) + io.write_rune(w, r) + p = p[width:] } } @@ -1212,52 +1212,52 @@ write_pad_string :: proc(w: io.Writer, pad: string, pad_len, remains: int) { // fields splits the string s around each instance of one or more consecutive white space character, defined by unicode.is_space // returning a slice of substrings of s or an empty slice if s only contains white space fields :: proc(s: string, allocator := context.allocator) -> []string #no_bounds_check { - n := 0; - was_space := 1; - set_bits := u8(0); + n := 0 + was_space := 1 + set_bits := u8(0) // check to see for i in 0..<len(s) { - r := s[i]; - set_bits |= r; - is_space := int(_ascii_space[r]); - n += was_space & ~is_space; - was_space = is_space; + r := s[i] + set_bits |= r + is_space := int(_ascii_space[r]) + n += was_space & ~is_space + was_space = is_space } if set_bits >= utf8.RUNE_SELF { - return fields_proc(s, unicode.is_space, allocator); + return fields_proc(s, unicode.is_space, allocator) } if n == 0 { - return nil; + return nil } - a := make([]string, n, allocator); - na := 0; - field_start := 0; - i := 0; + a := make([]string, n, allocator) + na := 0 + field_start := 0 + i := 0 for i < len(s) && _ascii_space[s[i]] != 0 { - i += 1; + i += 1 } - field_start = i; + field_start = i for i < len(s) { if _ascii_space[s[i]] == 0 { - i += 1; - continue; + i += 1 + continue } - a[na] = s[field_start : i]; - na += 1; - i += 1; + a[na] = s[field_start : i] + na += 1 + i += 1 for i < len(s) && _ascii_space[s[i]] != 0 { - i += 1; + i += 1 } - field_start = i; + field_start = i } if field_start < len(s) { - a[na] = s[field_start:]; + a[na] = s[field_start:] } - return a; + return a } @@ -1268,28 +1268,28 @@ fields :: proc(s: string, allocator := context.allocator) -> []string #no_bounds // fields_proc makes no guarantee about the order in which it calls f(ch) // it assumes that `f` always returns the same value for a given ch fields_proc :: proc(s: string, f: proc(rune) -> bool, allocator := context.allocator) -> []string #no_bounds_check { - substrings := make([dynamic]string, 0, 32, allocator); + substrings := make([dynamic]string, 0, 32, allocator) - start, end := -1, -1; + start, end := -1, -1 for r, offset in s { - end = offset; + end = offset if f(r) { if start >= 0 { - append(&substrings, s[start : end]); + append(&substrings, s[start : end]) // -1 could be used, but just speed it up through bitwise not // gotta love 2's complement - start = ~start; + start = ~start } } else { if start < 0 { - start = end; + start = end } } } if start >= 0 { - append(&substrings, s[start : end]); + append(&substrings, s[start : end]) } - return substrings[:]; + return substrings[:] } diff --git a/core/sync/atomic.odin b/core/sync/atomic.odin index 9a2274f69..dbcb5283f 100644 --- a/core/sync/atomic.odin +++ b/core/sync/atomic.odin @@ -16,10 +16,10 @@ strongest_failure_ordering_table := [Ordering]Ordering{ .Acquire = .Acquire, .Acquire_Release = .Acquire, .Sequentially_Consistent = .Sequentially_Consistent, -}; +} strongest_failure_ordering :: #force_inline proc(order: Ordering) -> Ordering { - return strongest_failure_ordering_table[order]; + return strongest_failure_ordering_table[order] } fence :: #force_inline proc($order: Ordering) { @@ -80,7 +80,7 @@ atomic_compare_exchange :: #force_inline proc(dst: ^$T, old, new: T, $success, $ when success == .Acquire { return instrinsics.atomic_cxchg_failacq(dst, old, new); } else { #panic("an unknown ordering combination"); } } else { - return T{}, false; + return T{}, false } } @@ -106,7 +106,7 @@ atomic_compare_exchange_weak :: #force_inline proc(dst: ^$T, old, new: T, $succe when success == .Acquire { return intrinsics.atomic_cxchgweak_failacq(dst, old, new); } else { #panic("an unknown ordering combination"); } } else { - return T{}, false; + return T{}, false } } diff --git a/core/sync/barrier.odin b/core/sync/barrier.odin index 51abec536..997fde82d 100644 --- a/core/sync/barrier.odin +++ b/core/sync/barrier.odin @@ -48,34 +48,34 @@ Barrier :: struct { } barrier_init :: proc(b: ^Barrier, thread_count: int) { - blocking_mutex_init(&b.mutex); - condition_init(&b.cond, &b.mutex); - b.index = 0; - b.generation_id = 0; - b.thread_count = thread_count; + blocking_mutex_init(&b.mutex) + condition_init(&b.cond, &b.mutex) + b.index = 0 + b.generation_id = 0 + b.thread_count = thread_count } barrier_destroy :: proc(b: ^Barrier) { - blocking_mutex_destroy(&b.mutex); - condition_destroy(&b.cond); + blocking_mutex_destroy(&b.mutex) + condition_destroy(&b.cond) } // Block the current thread until all threads have rendezvoused // Barrier can be reused after all threads rendezvoused once, and can be used continuously barrier_wait :: proc(b: ^Barrier) -> (is_leader: bool) { - blocking_mutex_lock(&b.mutex); - defer blocking_mutex_unlock(&b.mutex); - local_gen := b.generation_id; - b.index += 1; + blocking_mutex_lock(&b.mutex) + defer blocking_mutex_unlock(&b.mutex) + local_gen := b.generation_id + b.index += 1 if b.index < b.thread_count { for local_gen == b.generation_id && b.index < b.thread_count { - condition_wait_for(&b.cond); + condition_wait_for(&b.cond) } - return false; + return false } - b.index = 0; - b.generation_id += 1; - condition_broadcast(&b.cond); - return true; + b.index = 0 + b.generation_id += 1 + condition_broadcast(&b.cond) + return true } diff --git a/core/sync/channel.odin b/core/sync/channel.odin index 46eb53af7..82b9504f4 100644 --- a/core/sync/channel.odin +++ b/core/sync/channel.odin @@ -5,7 +5,7 @@ import "core:time" import "core:intrinsics" import "core:math/rand" -_, _ :: time, rand; +_, _ :: time, rand Channel_Direction :: enum i8 { Both = 0, @@ -18,152 +18,152 @@ Channel :: struct($T: typeid, $Direction := Channel_Direction.Both) { } channel_init :: proc(ch: ^$C/Channel($T, $D), cap := 0, allocator := context.allocator) { - context.allocator = allocator; - ch._internal = raw_channel_create(size_of(T), align_of(T), cap); - return; + context.allocator = allocator + ch._internal = raw_channel_create(size_of(T), align_of(T), cap) + return } channel_make :: proc($T: typeid, cap := 0, allocator := context.allocator) -> (ch: Channel(T, .Both)) { - context.allocator = allocator; - ch._internal = raw_channel_create(size_of(T), align_of(T), cap); - return; + context.allocator = allocator + ch._internal = raw_channel_create(size_of(T), align_of(T), cap) + return } channel_make_send :: proc($T: typeid, cap := 0, allocator := context.allocator) -> (ch: Channel(T, .Send)) { - context.allocator = allocator; - ch._internal = raw_channel_create(size_of(T), align_of(T), cap); - return; + context.allocator = allocator + ch._internal = raw_channel_create(size_of(T), align_of(T), cap) + return } channel_make_recv :: proc($T: typeid, cap := 0, allocator := context.allocator) -> (ch: Channel(T, .Recv)) { - context.allocator = allocator; - ch._internal = raw_channel_create(size_of(T), align_of(T), cap); - return; + context.allocator = allocator + ch._internal = raw_channel_create(size_of(T), align_of(T), cap) + return } channel_destroy :: proc(ch: $C/Channel($T, $D)) { - raw_channel_destroy(ch._internal); + raw_channel_destroy(ch._internal) } channel_as_send :: proc(ch: $C/Channel($T, .Both)) -> (res: Channel(T, .Send)) { - res._internal = ch._internal; - return; + res._internal = ch._internal + return } channel_as_recv :: proc(ch: $C/Channel($T, .Both)) -> (res: Channel(T, .Recv)) { - res._internal = ch._internal; - return; + res._internal = ch._internal + return } channel_len :: proc(ch: $C/Channel($T, $D)) -> int { - return ch._internal.len if ch._internal != nil else 0; + return ch._internal.len if ch._internal != nil else 0 } channel_cap :: proc(ch: $C/Channel($T, $D)) -> int { - return ch._internal.cap if ch._internal != nil else 0; + return ch._internal.cap if ch._internal != nil else 0 } channel_send :: proc(ch: $C/Channel($T, $D), msg: T, loc := #caller_location) where D >= .Both { - msg := msg; - _ = raw_channel_send_impl(ch._internal, &msg, /*block*/true, loc); + msg := msg + _ = raw_channel_send_impl(ch._internal, &msg, /*block*/true, loc) } channel_try_send :: proc(ch: $C/Channel($T, $D), msg: T, loc := #caller_location) -> bool where D >= .Both { - msg := msg; - return raw_channel_send_impl(ch._internal, &msg, /*block*/false, loc); + msg := msg + return raw_channel_send_impl(ch._internal, &msg, /*block*/false, loc) } channel_recv :: proc(ch: $C/Channel($T, $D), loc := #caller_location) -> (msg: T) where D <= .Both { - c := ch._internal; + c := ch._internal if c == nil { - panic(message="cannot recv message; channel is nil", loc=loc); + panic(message="cannot recv message; channel is nil", loc=loc) } - mutex_lock(&c.mutex); - raw_channel_recv_impl(c, &msg, loc); - mutex_unlock(&c.mutex); - return; + mutex_lock(&c.mutex) + raw_channel_recv_impl(c, &msg, loc) + mutex_unlock(&c.mutex) + return } channel_try_recv :: proc(ch: $C/Channel($T, $D), loc := #caller_location) -> (msg: T, ok: bool) where D <= .Both { - c := ch._internal; + c := ch._internal if c != nil && mutex_try_lock(&c.mutex) { if c.len > 0 { - raw_channel_recv_impl(c, &msg, loc); - ok = true; + raw_channel_recv_impl(c, &msg, loc) + ok = true } - mutex_unlock(&c.mutex); + mutex_unlock(&c.mutex) } - return; + return } channel_try_recv_ptr :: proc(ch: $C/Channel($T, $D), msg: ^T, loc := #caller_location) -> (ok: bool) where D <= .Both { - res: T; - res, ok = channel_try_recv(ch, loc); + res: T + res, ok = channel_try_recv(ch, loc) if ok && msg != nil { - msg^ = res; + msg^ = res } - return; + return } channel_is_nil :: proc(ch: $C/Channel($T, $D)) -> bool { - return ch._internal == nil; + return ch._internal == nil } channel_is_open :: proc(ch: $C/Channel($T, $D)) -> bool { - c := ch._internal; - return c != nil && !c.closed; + c := ch._internal + return c != nil && !c.closed } channel_eq :: proc(a, b: $C/Channel($T, $D)) -> bool { - return a._internal == b._internal; + return a._internal == b._internal } channel_ne :: proc(a, b: $C/Channel($T, $D)) -> bool { - return a._internal != b._internal; + return a._internal != b._internal } channel_can_send :: proc(ch: $C/Channel($T, $D)) -> (ok: bool) where D >= .Both { - return raw_channel_can_send(ch._internal); + return raw_channel_can_send(ch._internal) } channel_can_recv :: proc(ch: $C/Channel($T, $D)) -> (ok: bool) where D <= .Both { - return raw_channel_can_recv(ch._internal); + return raw_channel_can_recv(ch._internal) } channel_peek :: proc(ch: $C/Channel($T, $D)) -> int { - c := ch._internal; + c := ch._internal if c == nil { - return -1; + return -1 } if intrinsics.atomic_load(&c.closed) { - return -1; + return -1 } - return intrinsics.atomic_load(&c.len); + return intrinsics.atomic_load(&c.len) } channel_close :: proc(ch: $C/Channel($T, $D), loc := #caller_location) { - raw_channel_close(ch._internal, loc); + raw_channel_close(ch._internal, loc) } channel_iterator :: proc(ch: $C/Channel($T, $D)) -> (msg: T, ok: bool) where D <= .Both { - c := ch._internal; + c := ch._internal if c == nil { - return; + return } if !c.closed || c.len > 0 { - msg, ok = channel_recv(ch), true; + msg, ok = channel_recv(ch), true } - return; + return } channel_drain :: proc(ch: $C/Channel($T, $D)) where D >= .Both { - raw_channel_drain(ch._internal); + raw_channel_drain(ch._internal) } channel_move :: proc(dst: $C1/Channel($T, $D1) src: $C2/Channel(T, $D2)) where D1 <= .Both, D2 >= .Both { for msg in channel_iterator(src) { - channel_send(dst, msg); + channel_send(dst, msg) } } @@ -190,195 +190,195 @@ Raw_Channel :: struct { } raw_channel_wait_queue_insert :: proc(head: ^^Raw_Channel_Wait_Queue, val: ^Raw_Channel_Wait_Queue) { - val.next = head^; - head^ = val; + val.next = head^ + head^ = val } raw_channel_wait_queue_remove :: proc(head: ^^Raw_Channel_Wait_Queue, val: ^Raw_Channel_Wait_Queue) { - p := head; + p := head for p^ != nil && p^ != val { - p = &p^.next; + p = &p^.next } if p != nil { - p^ = p^.next; + p^ = p^.next } } raw_channel_create :: proc(elem_size, elem_align: int, cap := 0) -> ^Raw_Channel { - assert(int(u32(elem_size)) == elem_size); + assert(int(u32(elem_size)) == elem_size) - s := size_of(Raw_Channel); - s = mem.align_forward_int(s, elem_align); - data_offset := uintptr(s); - s += elem_size * max(cap, 1); + s := size_of(Raw_Channel) + s = mem.align_forward_int(s, elem_align) + data_offset := uintptr(s) + s += elem_size * max(cap, 1) - a := max(elem_align, align_of(Raw_Channel)); + a := max(elem_align, align_of(Raw_Channel)) - c := (^Raw_Channel)(mem.alloc(s, a)); + c := (^Raw_Channel)(mem.alloc(s, a)) if c == nil { - return nil; + return nil } - c.data_offset = u16(data_offset); - c.elem_size = u32(elem_size); - c.len, c.cap = 0, max(cap, 0); - c.read, c.write = 0, 0; - mutex_init(&c.mutex); - condition_init(&c.cond, &c.mutex); - c.allocator = context.allocator; - c.closed = false; + c.data_offset = u16(data_offset) + c.elem_size = u32(elem_size) + c.len, c.cap = 0, max(cap, 0) + c.read, c.write = 0, 0 + mutex_init(&c.mutex) + condition_init(&c.cond, &c.mutex) + c.allocator = context.allocator + c.closed = false - return c; + return c } raw_channel_destroy :: proc(c: ^Raw_Channel) { if c == nil { - return; + return } - context.allocator = c.allocator; - intrinsics.atomic_store(&c.closed, true); + context.allocator = c.allocator + intrinsics.atomic_store(&c.closed, true) - condition_destroy(&c.cond); - mutex_destroy(&c.mutex); - free(c); + condition_destroy(&c.cond) + mutex_destroy(&c.mutex) + free(c) } raw_channel_close :: proc(c: ^Raw_Channel, loc := #caller_location) { if c == nil { - panic(message="cannot close nil channel", loc=loc); + panic(message="cannot close nil channel", loc=loc) } - mutex_lock(&c.mutex); - defer mutex_unlock(&c.mutex); - intrinsics.atomic_store(&c.closed, true); + mutex_lock(&c.mutex) + defer mutex_unlock(&c.mutex) + intrinsics.atomic_store(&c.closed, true) // Release readers and writers - raw_channel_wait_queue_broadcast(c.recvq); - raw_channel_wait_queue_broadcast(c.sendq); - condition_broadcast(&c.cond); + raw_channel_wait_queue_broadcast(c.recvq) + raw_channel_wait_queue_broadcast(c.sendq) + condition_broadcast(&c.cond) } raw_channel_send_impl :: proc(c: ^Raw_Channel, msg: rawptr, block: bool, loc := #caller_location) -> bool { send :: proc(c: ^Raw_Channel, src: rawptr) { - data := uintptr(c) + uintptr(c.data_offset); - dst := data + uintptr(c.write * int(c.elem_size)); - mem.copy(rawptr(dst), src, int(c.elem_size)); - c.len += 1; - c.write = (c.write + 1) % max(c.cap, 1); + data := uintptr(c) + uintptr(c.data_offset) + dst := data + uintptr(c.write * int(c.elem_size)) + mem.copy(rawptr(dst), src, int(c.elem_size)) + c.len += 1 + c.write = (c.write + 1) % max(c.cap, 1) } switch { case c == nil: - panic(message="cannot send message; channel is nil", loc=loc); + panic(message="cannot send message; channel is nil", loc=loc) case c.closed: - panic(message="cannot send message; channel is closed", loc=loc); + panic(message="cannot send message; channel is closed", loc=loc) } - mutex_lock(&c.mutex); - defer mutex_unlock(&c.mutex); + mutex_lock(&c.mutex) + defer mutex_unlock(&c.mutex) if c.cap > 0 { if !block && c.len >= c.cap { - return false; + return false } for c.len >= c.cap { - condition_wait_for(&c.cond); + condition_wait_for(&c.cond) } } else if c.len > 0 { // TODO(bill): determine correct behaviour if !block { - return false; + return false } - condition_wait_for(&c.cond); + condition_wait_for(&c.cond) } else if c.len == 0 && !block { - return false; + return false } - send(c, msg); - condition_signal(&c.cond); - raw_channel_wait_queue_signal(c.recvq); + send(c, msg) + condition_signal(&c.cond) + raw_channel_wait_queue_signal(c.recvq) - return true; + return true } raw_channel_recv_impl :: proc(c: ^Raw_Channel, res: rawptr, loc := #caller_location) { recv :: proc(c: ^Raw_Channel, dst: rawptr, loc := #caller_location) { if c.len < 1 { - panic(message="cannot recv message; channel is empty", loc=loc); + panic(message="cannot recv message; channel is empty", loc=loc) } - c.len -= 1; + c.len -= 1 - data := uintptr(c) + uintptr(c.data_offset); - src := data + uintptr(c.read * int(c.elem_size)); - mem.copy(dst, rawptr(src), int(c.elem_size)); - c.read = (c.read + 1) % max(c.cap, 1); + data := uintptr(c) + uintptr(c.data_offset) + src := data + uintptr(c.read * int(c.elem_size)) + mem.copy(dst, rawptr(src), int(c.elem_size)) + c.read = (c.read + 1) % max(c.cap, 1) } if c == nil { - panic(message="cannot recv message; channel is nil", loc=loc); + panic(message="cannot recv message; channel is nil", loc=loc) } - intrinsics.atomic_store(&c.ready, true); + intrinsics.atomic_store(&c.ready, true) for c.len < 1 { - raw_channel_wait_queue_signal(c.sendq); - condition_wait_for(&c.cond); + raw_channel_wait_queue_signal(c.sendq) + condition_wait_for(&c.cond) } - intrinsics.atomic_store(&c.ready, false); - recv(c, res, loc); + intrinsics.atomic_store(&c.ready, false) + recv(c, res, loc) if c.cap > 0 { if c.len == c.cap - 1 { // NOTE(bill): Only signal on the last one - condition_signal(&c.cond); + condition_signal(&c.cond) } } else { - condition_signal(&c.cond); + condition_signal(&c.cond) } } raw_channel_can_send :: proc(c: ^Raw_Channel) -> (ok: bool) { if c == nil { - return false; + return false } - mutex_lock(&c.mutex); + mutex_lock(&c.mutex) switch { case c.closed: - ok = false; + ok = false case c.cap > 0: - ok = c.ready && c.len < c.cap; + ok = c.ready && c.len < c.cap case: - ok = c.ready && c.len == 0; + ok = c.ready && c.len == 0 } - mutex_unlock(&c.mutex); - return; + mutex_unlock(&c.mutex) + return } raw_channel_can_recv :: proc(c: ^Raw_Channel) -> (ok: bool) { if c == nil { - return false; + return false } - mutex_lock(&c.mutex); - ok = c.len > 0; - mutex_unlock(&c.mutex); - return; + mutex_lock(&c.mutex) + ok = c.len > 0 + mutex_unlock(&c.mutex) + return } raw_channel_drain :: proc(c: ^Raw_Channel) { if c == nil { - return; + return } - mutex_lock(&c.mutex); - c.len = 0; - c.read = 0; - c.write = 0; - mutex_unlock(&c.mutex); + mutex_lock(&c.mutex) + c.len = 0 + c.read = 0 + c.write = 0 + mutex_unlock(&c.mutex) } -MAX_SELECT_CHANNELS :: 64; -SELECT_MAX_TIMEOUT :: max(time.Duration); +MAX_SELECT_CHANNELS :: 64 +SELECT_MAX_TIMEOUT :: max(time.Duration) Select_Command :: enum { Recv, @@ -393,67 +393,67 @@ Select_Channel :: struct { select :: proc(channels: ..Select_Channel) -> (index: int) { - return select_timeout(SELECT_MAX_TIMEOUT, ..channels); + return select_timeout(SELECT_MAX_TIMEOUT, ..channels) } select_timeout :: proc(timeout: time.Duration, channels: ..Select_Channel) -> (index: int) { switch len(channels) { case 0: - panic("sync: select with no channels"); + panic("sync: select with no channels") } - assert(len(channels) <= MAX_SELECT_CHANNELS); + assert(len(channels) <= MAX_SELECT_CHANNELS) - backing: [MAX_SELECT_CHANNELS]int; - queues: [MAX_SELECT_CHANNELS]Raw_Channel_Wait_Queue; - candidates := backing[:]; - cap := len(channels); - candidates = candidates[:cap]; + backing: [MAX_SELECT_CHANNELS]int + queues: [MAX_SELECT_CHANNELS]Raw_Channel_Wait_Queue + candidates := backing[:] + cap := len(channels) + candidates = candidates[:cap] - count := u32(0); + count := u32(0) for c, i in channels { if c.channel == nil { - continue; + continue } switch c.command { case .Recv: if raw_channel_can_recv(c.channel) { - candidates[count] = i; - count += 1; + candidates[count] = i + count += 1 } case .Send: if raw_channel_can_send(c.channel) { - candidates[count] = i; - count += 1; + candidates[count] = i + count += 1 } } } if count == 0 { - wait_state: uintptr = 0; + wait_state: uintptr = 0 for _, i in channels { - q := &queues[i]; - q.state = &wait_state; + q := &queues[i] + q.state = &wait_state } for c, i in channels { if c.channel == nil { - continue; + continue } - q := &queues[i]; + q := &queues[i] switch c.command { - case .Recv: raw_channel_wait_queue_insert(&c.channel.recvq, q); - case .Send: raw_channel_wait_queue_insert(&c.channel.sendq, q); + case .Recv: raw_channel_wait_queue_insert(&c.channel.recvq, q) + case .Send: raw_channel_wait_queue_insert(&c.channel.sendq, q) } } - raw_channel_wait_queue_wait_on(&wait_state, timeout); + raw_channel_wait_queue_wait_on(&wait_state, timeout) for c, i in channels { if c.channel == nil { - continue; + continue } - q := &queues[i]; + q := &queues[i] switch c.command { - case .Recv: raw_channel_wait_queue_remove(&c.channel.recvq, q); - case .Send: raw_channel_wait_queue_remove(&c.channel.sendq, q); + case .Recv: raw_channel_wait_queue_remove(&c.channel.recvq, q) + case .Send: raw_channel_wait_queue_remove(&c.channel.sendq, q) } } @@ -461,429 +461,429 @@ select_timeout :: proc(timeout: time.Duration, channels: ..Select_Channel) -> (i switch c.command { case .Recv: if raw_channel_can_recv(c.channel) { - candidates[count] = i; - count += 1; + candidates[count] = i + count += 1 } case .Send: if raw_channel_can_send(c.channel) { - candidates[count] = i; - count += 1; + candidates[count] = i + count += 1 } } } if count == 0 && timeout == SELECT_MAX_TIMEOUT { - index = -1; - return; + index = -1 + return } - assert(count != 0); + assert(count != 0) } - t := time.now(); - r := rand.create(transmute(u64)t); - i := rand.uint32(&r); + t := time.now() + r := rand.create(transmute(u64)t) + i := rand.uint32(&r) - index = candidates[i % count]; - return; + index = candidates[i % count] + return } select_recv :: proc(channels: ..^Raw_Channel) -> (index: int) { switch len(channels) { case 0: - panic("sync: select with no channels"); + panic("sync: select with no channels") } - assert(len(channels) <= MAX_SELECT_CHANNELS); + assert(len(channels) <= MAX_SELECT_CHANNELS) - backing: [MAX_SELECT_CHANNELS]int; - queues: [MAX_SELECT_CHANNELS]Raw_Channel_Wait_Queue; - candidates := backing[:]; - cap := len(channels); - candidates = candidates[:cap]; + backing: [MAX_SELECT_CHANNELS]int + queues: [MAX_SELECT_CHANNELS]Raw_Channel_Wait_Queue + candidates := backing[:] + cap := len(channels) + candidates = candidates[:cap] - count := u32(0); + count := u32(0) for c, i in channels { if raw_channel_can_recv(c) { - candidates[count] = i; - count += 1; + candidates[count] = i + count += 1 } } if count == 0 { - state: uintptr; + state: uintptr for c, i in channels { - q := &queues[i]; - q.state = &state; - raw_channel_wait_queue_insert(&c.recvq, q); + q := &queues[i] + q.state = &state + raw_channel_wait_queue_insert(&c.recvq, q) } - raw_channel_wait_queue_wait_on(&state, SELECT_MAX_TIMEOUT); + raw_channel_wait_queue_wait_on(&state, SELECT_MAX_TIMEOUT) for c, i in channels { - q := &queues[i]; - raw_channel_wait_queue_remove(&c.recvq, q); + q := &queues[i] + raw_channel_wait_queue_remove(&c.recvq, q) } for c, i in channels { if raw_channel_can_recv(c) { - candidates[count] = i; - count += 1; + candidates[count] = i + count += 1 } } - assert(count != 0); + assert(count != 0) } - t := time.now(); - r := rand.create(transmute(u64)t); - i := rand.uint32(&r); + t := time.now() + r := rand.create(transmute(u64)t) + i := rand.uint32(&r) - index = candidates[i % count]; - return; + index = candidates[i % count] + return } select_recv_msg :: proc(channels: ..$C/Channel($T, $D)) -> (msg: T, index: int) { switch len(channels) { case 0: - panic("sync: select with no channels"); + panic("sync: select with no channels") } - assert(len(channels) <= MAX_SELECT_CHANNELS); + assert(len(channels) <= MAX_SELECT_CHANNELS) - queues: [MAX_SELECT_CHANNELS]Raw_Channel_Wait_Queue; - candidates: [MAX_SELECT_CHANNELS]int; + queues: [MAX_SELECT_CHANNELS]Raw_Channel_Wait_Queue + candidates: [MAX_SELECT_CHANNELS]int - count := u32(0); + count := u32(0) for c, i in channels { if raw_channel_can_recv(c) { - candidates[count] = i; - count += 1; + candidates[count] = i + count += 1 } } if count == 0 { - state: uintptr; + state: uintptr for c, i in channels { - q := &queues[i]; - q.state = &state; - raw_channel_wait_queue_insert(&c.recvq, q); + q := &queues[i] + q.state = &state + raw_channel_wait_queue_insert(&c.recvq, q) } - raw_channel_wait_queue_wait_on(&state, SELECT_MAX_TIMEOUT); + raw_channel_wait_queue_wait_on(&state, SELECT_MAX_TIMEOUT) for c, i in channels { - q := &queues[i]; - raw_channel_wait_queue_remove(&c.recvq, q); + q := &queues[i] + raw_channel_wait_queue_remove(&c.recvq, q) } for c, i in channels { if raw_channel_can_recv(c) { - candidates[count] = i; - count += 1; + candidates[count] = i + count += 1 } } - assert(count != 0); + assert(count != 0) } - t := time.now(); - r := rand.create(transmute(u64)t); - i := rand.uint32(&r); + t := time.now() + r := rand.create(transmute(u64)t) + i := rand.uint32(&r) - index = candidates[i % count]; - msg = channel_recv(channels[index]); + index = candidates[i % count] + msg = channel_recv(channels[index]) - return; + return } select_send_msg :: proc(msg: $T, channels: ..$C/Channel(T, $D)) -> (index: int) { switch len(channels) { case 0: - panic("sync: select with no channels"); + panic("sync: select with no channels") } - assert(len(channels) <= MAX_SELECT_CHANNELS); + assert(len(channels) <= MAX_SELECT_CHANNELS) - backing: [MAX_SELECT_CHANNELS]int; - queues: [MAX_SELECT_CHANNELS]Raw_Channel_Wait_Queue; - candidates := backing[:]; - cap := len(channels); - candidates = candidates[:cap]; + backing: [MAX_SELECT_CHANNELS]int + queues: [MAX_SELECT_CHANNELS]Raw_Channel_Wait_Queue + candidates := backing[:] + cap := len(channels) + candidates = candidates[:cap] - count := u32(0); + count := u32(0) for c, i in channels { if raw_channel_can_recv(c) { - candidates[count] = i; - count += 1; + candidates[count] = i + count += 1 } } if count == 0 { - state: uintptr; + state: uintptr for c, i in channels { - q := &queues[i]; - q.state = &state; - raw_channel_wait_queue_insert(&c.recvq, q); + q := &queues[i] + q.state = &state + raw_channel_wait_queue_insert(&c.recvq, q) } - raw_channel_wait_queue_wait_on(&state, SELECT_MAX_TIMEOUT); + raw_channel_wait_queue_wait_on(&state, SELECT_MAX_TIMEOUT) for c, i in channels { - q := &queues[i]; - raw_channel_wait_queue_remove(&c.recvq, q); + q := &queues[i] + raw_channel_wait_queue_remove(&c.recvq, q) } for c, i in channels { if raw_channel_can_recv(c) { - candidates[count] = i; - count += 1; + candidates[count] = i + count += 1 } } - assert(count != 0); + assert(count != 0) } - t := time.now(); - r := rand.create(transmute(u64)t); - i := rand.uint32(&r); + t := time.now() + r := rand.create(transmute(u64)t) + i := rand.uint32(&r) - index = candidates[i % count]; + index = candidates[i % count] if msg != nil { - channel_send(channels[index], msg); + channel_send(channels[index], msg) } - return; + return } select_send :: proc(channels: ..^Raw_Channel) -> (index: int) { switch len(channels) { case 0: - panic("sync: select with no channels"); + panic("sync: select with no channels") } - assert(len(channels) <= MAX_SELECT_CHANNELS); - candidates: [MAX_SELECT_CHANNELS]int; - queues: [MAX_SELECT_CHANNELS]Raw_Channel_Wait_Queue; + assert(len(channels) <= MAX_SELECT_CHANNELS) + candidates: [MAX_SELECT_CHANNELS]int + queues: [MAX_SELECT_CHANNELS]Raw_Channel_Wait_Queue - count := u32(0); + count := u32(0) for c, i in channels { if raw_channel_can_send(c) { - candidates[count] = i; - count += 1; + candidates[count] = i + count += 1 } } if count == 0 { - state: uintptr; + state: uintptr for c, i in channels { - q := &queues[i]; - q.state = &state; - raw_channel_wait_queue_insert(&c.sendq, q); + q := &queues[i] + q.state = &state + raw_channel_wait_queue_insert(&c.sendq, q) } - raw_channel_wait_queue_wait_on(&state, SELECT_MAX_TIMEOUT); + raw_channel_wait_queue_wait_on(&state, SELECT_MAX_TIMEOUT) for c, i in channels { - q := &queues[i]; - raw_channel_wait_queue_remove(&c.sendq, q); + q := &queues[i] + raw_channel_wait_queue_remove(&c.sendq, q) } for c, i in channels { if raw_channel_can_send(c) { - candidates[count] = i; - count += 1; + candidates[count] = i + count += 1 } } - assert(count != 0); + assert(count != 0) } - t := time.now(); - r := rand.create(transmute(u64)t); - i := rand.uint32(&r); + t := time.now() + r := rand.create(transmute(u64)t) + i := rand.uint32(&r) - index = candidates[i % count]; - return; + index = candidates[i % count] + return } select_try :: proc(channels: ..Select_Channel) -> (index: int) { switch len(channels) { case 0: - panic("sync: select with no channels"); + panic("sync: select with no channels") } - assert(len(channels) <= MAX_SELECT_CHANNELS); + assert(len(channels) <= MAX_SELECT_CHANNELS) - backing: [MAX_SELECT_CHANNELS]int; - candidates := backing[:]; - cap := len(channels); - candidates = candidates[:cap]; + backing: [MAX_SELECT_CHANNELS]int + candidates := backing[:] + cap := len(channels) + candidates = candidates[:cap] - count := u32(0); + count := u32(0) for c, i in channels { switch c.command { case .Recv: if raw_channel_can_recv(c.channel) { - candidates[count] = i; - count += 1; + candidates[count] = i + count += 1 } case .Send: if raw_channel_can_send(c.channel) { - candidates[count] = i; - count += 1; + candidates[count] = i + count += 1 } } } if count == 0 { - index = -1; - return; + index = -1 + return } - t := time.now(); - r := rand.create(transmute(u64)t); - i := rand.uint32(&r); + t := time.now() + r := rand.create(transmute(u64)t) + i := rand.uint32(&r) - index = candidates[i % count]; - return; + index = candidates[i % count] + return } select_try_recv :: proc(channels: ..^Raw_Channel) -> (index: int) { switch len(channels) { case 0: - index = -1; - return; + index = -1 + return case 1: - index = -1; + index = -1 if raw_channel_can_recv(channels[0]) { - index = 0; + index = 0 } - return; + return } - assert(len(channels) <= MAX_SELECT_CHANNELS); - candidates: [MAX_SELECT_CHANNELS]int; + assert(len(channels) <= MAX_SELECT_CHANNELS) + candidates: [MAX_SELECT_CHANNELS]int - count := u32(0); + count := u32(0) for c, i in channels { if raw_channel_can_recv(c) { - candidates[count] = i; - count += 1; + candidates[count] = i + count += 1 } } if count == 0 { - index = -1; - return; + index = -1 + return } - t := time.now(); - r := rand.create(transmute(u64)t); - i := rand.uint32(&r); + t := time.now() + r := rand.create(transmute(u64)t) + i := rand.uint32(&r) - index = candidates[i % count]; - return; + index = candidates[i % count] + return } select_try_send :: proc(channels: ..^Raw_Channel) -> (index: int) #no_bounds_check { switch len(channels) { case 0: - return -1; + return -1 case 1: if raw_channel_can_send(channels[0]) { - return 0; + return 0 } - return -1; + return -1 } - assert(len(channels) <= MAX_SELECT_CHANNELS); - candidates: [MAX_SELECT_CHANNELS]int; + assert(len(channels) <= MAX_SELECT_CHANNELS) + candidates: [MAX_SELECT_CHANNELS]int - count := u32(0); + count := u32(0) for c, i in channels { if raw_channel_can_send(c) { - candidates[count] = i; - count += 1; + candidates[count] = i + count += 1 } } if count == 0 { - index = -1; - return; + index = -1 + return } - t := time.now(); - r := rand.create(transmute(u64)t); - i := rand.uint32(&r); + t := time.now() + r := rand.create(transmute(u64)t) + i := rand.uint32(&r) - index = candidates[i % count]; - return; + index = candidates[i % count] + return } select_try_recv_msg :: proc(channels: ..$C/Channel($T, $D)) -> (msg: T, index: int) { switch len(channels) { case 0: - index = -1; - return; + index = -1 + return case 1: - ok: bool; + ok: bool if msg, ok = channel_try_recv(channels[0]); ok { - index = 0; + index = 0 } - return; + return } - assert(len(channels) <= MAX_SELECT_CHANNELS); - candidates: [MAX_SELECT_CHANNELS]int; + assert(len(channels) <= MAX_SELECT_CHANNELS) + candidates: [MAX_SELECT_CHANNELS]int - count := u32(0); + count := u32(0) for c, i in channels { if channel_can_recv(c) { - candidates[count] = i; - count += 1; + candidates[count] = i + count += 1 } } if count == 0 { - index = -1; - return; + index = -1 + return } - t := time.now(); - r := rand.create(transmute(u64)t); - i := rand.uint32(&r); + t := time.now() + r := rand.create(transmute(u64)t) + i := rand.uint32(&r) - index = candidates[i % count]; - msg = channel_recv(channels[index]); - return; + index = candidates[i % count] + msg = channel_recv(channels[index]) + return } select_try_send_msg :: proc(msg: $T, channels: ..$C/Channel(T, $D)) -> (index: int) { - index = -1; + index = -1 switch len(channels) { case 0: - return; + return case 1: if channel_try_send(channels[0], msg) { - index = 0; + index = 0 } - return; + return } - assert(len(channels) <= MAX_SELECT_CHANNELS); - candidates: [MAX_SELECT_CHANNELS]int; + assert(len(channels) <= MAX_SELECT_CHANNELS) + candidates: [MAX_SELECT_CHANNELS]int - count := u32(0); + count := u32(0) for c, i in channels { if raw_channel_can_send(c) { - candidates[count] = i; - count += 1; + candidates[count] = i + count += 1 } } if count == 0 { - index = -1; - return; + index = -1 + return } - t := time.now(); - r := rand.create(transmute(u64)t); - i := rand.uint32(&r); + t := time.now() + r := rand.create(transmute(u64)t) + i := rand.uint32(&r) - index = candidates[i % count]; - channel_send(channels[index], msg); - return; + index = candidates[i % count] + channel_send(channels[index], msg) + return } diff --git a/core/sync/channel_windows.odin b/core/sync/channel_windows.odin index a28c41437..5d469ffff 100644 --- a/core/sync/channel_windows.odin +++ b/core/sync/channel_windows.odin @@ -5,29 +5,29 @@ import win32 "core:sys/windows" import "core:time" raw_channel_wait_queue_wait_on :: proc(state: ^uintptr, timeout: time.Duration) { - ms: win32.DWORD = win32.INFINITE; + ms: win32.DWORD = win32.INFINITE if max(time.Duration) != SELECT_MAX_TIMEOUT { - ms = win32.DWORD((max(time.duration_nanoseconds(timeout), 0) + 999999)/1000000); + ms = win32.DWORD((max(time.duration_nanoseconds(timeout), 0) + 999999)/1000000) } - v := intrinsics.atomic_load(state); + v := intrinsics.atomic_load(state) for v == 0 { - win32.WaitOnAddress(state, &v, size_of(state^), ms); - v = intrinsics.atomic_load(state); + win32.WaitOnAddress(state, &v, size_of(state^), ms) + v = intrinsics.atomic_load(state) } - intrinsics.atomic_store(state, 0); + intrinsics.atomic_store(state, 0) } raw_channel_wait_queue_signal :: proc(q: ^Raw_Channel_Wait_Queue) { for x := q; x != nil; x = x.next { - intrinsics.atomic_add(x.state, 1); - win32.WakeByAddressSingle(x.state); + intrinsics.atomic_add(x.state, 1) + win32.WakeByAddressSingle(x.state) } } raw_channel_wait_queue_broadcast :: proc(q: ^Raw_Channel_Wait_Queue) { for x := q; x != nil; x = x.next { - intrinsics.atomic_add(x.state, 1); - win32.WakeByAddressAll(x.state); + intrinsics.atomic_add(x.state, 1) + win32.WakeByAddressAll(x.state) } } diff --git a/core/sync/sync.odin b/core/sync/sync.odin index 5c2c09a7a..05c86a868 100644 --- a/core/sync/sync.odin +++ b/core/sync/sync.odin @@ -3,10 +3,10 @@ package sync import "core:intrinsics" cpu_relax :: #force_inline proc "contextless" () { - intrinsics.cpu_relax(); + intrinsics.cpu_relax() } -Condition_Mutex_Ptr :: union{^Mutex, ^Blocking_Mutex}; +Condition_Mutex_Ptr :: union{^Mutex, ^Blocking_Mutex} Ticket_Mutex :: struct { @@ -15,19 +15,19 @@ Ticket_Mutex :: struct { } ticket_mutex_init :: proc(m: ^Ticket_Mutex) { - atomic_store(&m.ticket, 0, .Relaxed); - atomic_store(&m.serving, 0, .Relaxed); + atomic_store(&m.ticket, 0, .Relaxed) + atomic_store(&m.serving, 0, .Relaxed) } ticket_mutex_lock :: #force_inline proc(m: ^Ticket_Mutex) { - ticket := atomic_add(&m.ticket, 1, .Relaxed); + ticket := atomic_add(&m.ticket, 1, .Relaxed) for ticket != atomic_load(&m.serving, .Acquire) { - intrinsics.cpu_relax(); + intrinsics.cpu_relax() } } ticket_mutex_unlock :: #force_inline proc(m: ^Ticket_Mutex) { - atomic_add(&m.serving, 1, .Relaxed); + atomic_add(&m.serving, 1, .Relaxed) } @@ -37,28 +37,28 @@ Benaphore :: struct { } benaphore_init :: proc(b: ^Benaphore) { - intrinsics.atomic_store(&b.counter, 0); - semaphore_init(&b.sema); + intrinsics.atomic_store(&b.counter, 0) + semaphore_init(&b.sema) } benaphore_destroy :: proc(b: ^Benaphore) { - semaphore_destroy(&b.sema); + semaphore_destroy(&b.sema) } benaphore_lock :: proc(b: ^Benaphore) { if intrinsics.atomic_add_acq(&b.counter, 1) > 1 { - semaphore_wait_for(&b.sema); + semaphore_wait_for(&b.sema) } } benaphore_try_lock :: proc(b: ^Benaphore) -> bool { - v, _ := intrinsics.atomic_cxchg_acq(&b.counter, 1, 0); - return v == 0; + v, _ := intrinsics.atomic_cxchg_acq(&b.counter, 1, 0) + return v == 0 } benaphore_unlock :: proc(b: ^Benaphore) { if intrinsics.atomic_sub_rel(&b.counter, 1) > 0 { - semaphore_post(&b.sema); + semaphore_post(&b.sema) } } @@ -70,53 +70,53 @@ Recursive_Benaphore :: struct { } recursive_benaphore_init :: proc(b: ^Recursive_Benaphore) { - intrinsics.atomic_store(&b.counter, 0); - semaphore_init(&b.sema); + intrinsics.atomic_store(&b.counter, 0) + semaphore_init(&b.sema) } recursive_benaphore_destroy :: proc(b: ^Recursive_Benaphore) { - semaphore_destroy(&b.sema); + semaphore_destroy(&b.sema) } recursive_benaphore_lock :: proc(b: ^Recursive_Benaphore) { - tid := current_thread_id(); + tid := current_thread_id() if intrinsics.atomic_add_acq(&b.counter, 1) > 1 { if tid != b.owner { - semaphore_wait_for(&b.sema); + semaphore_wait_for(&b.sema) } } // inside the lock - b.owner = tid; - b.recursion += 1; + b.owner = tid + b.recursion += 1 } recursive_benaphore_try_lock :: proc(b: ^Recursive_Benaphore) -> bool { - tid := current_thread_id(); + tid := current_thread_id() if b.owner == tid { - intrinsics.atomic_add_acq(&b.counter, 1); + intrinsics.atomic_add_acq(&b.counter, 1) } else { - v, _ := intrinsics.atomic_cxchg_acq(&b.counter, 1, 0); + v, _ := intrinsics.atomic_cxchg_acq(&b.counter, 1, 0) if v != 0 { - return false; + return false } // inside the lock - b.owner = tid; + b.owner = tid } - b.recursion += 1; - return true; + b.recursion += 1 + return true } recursive_benaphore_unlock :: proc(b: ^Recursive_Benaphore) { - tid := current_thread_id(); - assert(tid == b.owner); - b.recursion -= 1; - recursion := b.recursion; + tid := current_thread_id() + assert(tid == b.owner) + b.recursion -= 1 + recursion := b.recursion if recursion == 0 { - b.owner = 0; + b.owner = 0 } if intrinsics.atomic_sub_rel(&b.counter, 1) > 0 { if recursion == 0 { - semaphore_post(&b.sema); + semaphore_post(&b.sema) } } // outside the lock diff --git a/core/sync/sync2/atomic.odin b/core/sync/sync2/atomic.odin index 89d7bfe71..fe19f17c8 100644 --- a/core/sync/sync2/atomic.odin +++ b/core/sync/sync2/atomic.odin @@ -2,78 +2,78 @@ package sync2 import "core:intrinsics" -cpu_relax :: intrinsics.cpu_relax; +cpu_relax :: intrinsics.cpu_relax -atomic_fence :: intrinsics.atomic_fence; -atomic_fence_acquire :: intrinsics.atomic_fence_acq; -atomic_fence_release :: intrinsics.atomic_fence_rel; -atomic_fence_acqrel :: intrinsics.atomic_fence_acqrel; +atomic_fence :: intrinsics.atomic_fence +atomic_fence_acquire :: intrinsics.atomic_fence_acq +atomic_fence_release :: intrinsics.atomic_fence_rel +atomic_fence_acqrel :: intrinsics.atomic_fence_acqrel -atomic_store :: intrinsics.atomic_store; -atomic_store_release :: intrinsics.atomic_store_rel; -atomic_store_relaxed :: intrinsics.atomic_store_relaxed; -atomic_store_unordered :: intrinsics.atomic_store_unordered; +atomic_store :: intrinsics.atomic_store +atomic_store_release :: intrinsics.atomic_store_rel +atomic_store_relaxed :: intrinsics.atomic_store_relaxed +atomic_store_unordered :: intrinsics.atomic_store_unordered -atomic_load :: intrinsics.atomic_load; -atomic_load_acquire :: intrinsics.atomic_load_acq; -atomic_load_relaxed :: intrinsics.atomic_load_relaxed; -atomic_load_unordered :: intrinsics.atomic_load_unordered; +atomic_load :: intrinsics.atomic_load +atomic_load_acquire :: intrinsics.atomic_load_acq +atomic_load_relaxed :: intrinsics.atomic_load_relaxed +atomic_load_unordered :: intrinsics.atomic_load_unordered -atomic_add :: intrinsics.atomic_add; -atomic_add_acquire :: intrinsics.atomic_add_acq; -atomic_add_release :: intrinsics.atomic_add_rel; -atomic_add_acqrel :: intrinsics.atomic_add_acqrel; -atomic_add_relaxed :: intrinsics.atomic_add_relaxed; -atomic_sub :: intrinsics.atomic_sub; -atomic_sub_acquire :: intrinsics.atomic_sub_acq; -atomic_sub_release :: intrinsics.atomic_sub_rel; -atomic_sub_acqrel :: intrinsics.atomic_sub_acqrel; -atomic_sub_relaxed :: intrinsics.atomic_sub_relaxed; -atomic_and :: intrinsics.atomic_and; -atomic_and_acquire :: intrinsics.atomic_and_acq; -atomic_and_release :: intrinsics.atomic_and_rel; -atomic_and_acqrel :: intrinsics.atomic_and_acqrel; -atomic_and_relaxed :: intrinsics.atomic_and_relaxed; -atomic_nand :: intrinsics.atomic_nand; -atomic_nand_acquire :: intrinsics.atomic_nand_acq; -atomic_nand_release :: intrinsics.atomic_nand_rel; -atomic_nand_acqrel :: intrinsics.atomic_nand_acqrel; -atomic_nand_relaxed :: intrinsics.atomic_nand_relaxed; -atomic_or :: intrinsics.atomic_or; -atomic_or_acquire :: intrinsics.atomic_or_acq; -atomic_or_release :: intrinsics.atomic_or_rel; -atomic_or_acqrel :: intrinsics.atomic_or_acqrel; -atomic_or_relaxed :: intrinsics.atomic_or_relaxed; -atomic_xor :: intrinsics.atomic_xor; -atomic_xor_acquire :: intrinsics.atomic_xor_acq; -atomic_xor_release :: intrinsics.atomic_xor_rel; -atomic_xor_acqrel :: intrinsics.atomic_xor_acqrel; -atomic_xor_relaxed :: intrinsics.atomic_xor_relaxed; +atomic_add :: intrinsics.atomic_add +atomic_add_acquire :: intrinsics.atomic_add_acq +atomic_add_release :: intrinsics.atomic_add_rel +atomic_add_acqrel :: intrinsics.atomic_add_acqrel +atomic_add_relaxed :: intrinsics.atomic_add_relaxed +atomic_sub :: intrinsics.atomic_sub +atomic_sub_acquire :: intrinsics.atomic_sub_acq +atomic_sub_release :: intrinsics.atomic_sub_rel +atomic_sub_acqrel :: intrinsics.atomic_sub_acqrel +atomic_sub_relaxed :: intrinsics.atomic_sub_relaxed +atomic_and :: intrinsics.atomic_and +atomic_and_acquire :: intrinsics.atomic_and_acq +atomic_and_release :: intrinsics.atomic_and_rel +atomic_and_acqrel :: intrinsics.atomic_and_acqrel +atomic_and_relaxed :: intrinsics.atomic_and_relaxed +atomic_nand :: intrinsics.atomic_nand +atomic_nand_acquire :: intrinsics.atomic_nand_acq +atomic_nand_release :: intrinsics.atomic_nand_rel +atomic_nand_acqrel :: intrinsics.atomic_nand_acqrel +atomic_nand_relaxed :: intrinsics.atomic_nand_relaxed +atomic_or :: intrinsics.atomic_or +atomic_or_acquire :: intrinsics.atomic_or_acq +atomic_or_release :: intrinsics.atomic_or_rel +atomic_or_acqrel :: intrinsics.atomic_or_acqrel +atomic_or_relaxed :: intrinsics.atomic_or_relaxed +atomic_xor :: intrinsics.atomic_xor +atomic_xor_acquire :: intrinsics.atomic_xor_acq +atomic_xor_release :: intrinsics.atomic_xor_rel +atomic_xor_acqrel :: intrinsics.atomic_xor_acqrel +atomic_xor_relaxed :: intrinsics.atomic_xor_relaxed -atomic_exchange :: intrinsics.atomic_xchg; -atomic_exchange_acquire :: intrinsics.atomic_xchg_acq; -atomic_exchange_release :: intrinsics.atomic_xchg_rel; -atomic_exchange_acqrel :: intrinsics.atomic_xchg_acqrel; -atomic_exchange_relaxed :: intrinsics.atomic_xchg_relaxed; +atomic_exchange :: intrinsics.atomic_xchg +atomic_exchange_acquire :: intrinsics.atomic_xchg_acq +atomic_exchange_release :: intrinsics.atomic_xchg_rel +atomic_exchange_acqrel :: intrinsics.atomic_xchg_acqrel +atomic_exchange_relaxed :: intrinsics.atomic_xchg_relaxed // Returns value and optional ok boolean -atomic_compare_exchange_strong :: intrinsics.atomic_cxchg; -atomic_compare_exchange_strong_acquire :: intrinsics.atomic_cxchg_acq; -atomic_compare_exchange_strong_release :: intrinsics.atomic_cxchg_rel; -atomic_compare_exchange_strong_acqrel :: intrinsics.atomic_cxchg_acqrel; -atomic_compare_exchange_strong_relaxed :: intrinsics.atomic_cxchg_relaxed; -atomic_compare_exchange_strong_failrelaxed :: intrinsics.atomic_cxchg_failrelaxed; -atomic_compare_exchange_strong_failacquire :: intrinsics.atomic_cxchg_failacq; -atomic_compare_exchange_strong_acquire_failrelaxed :: intrinsics.atomic_cxchg_acq_failrelaxed; -atomic_compare_exchange_strong_acqrel_failrelaxed :: intrinsics.atomic_cxchg_acqrel_failrelaxed; +atomic_compare_exchange_strong :: intrinsics.atomic_cxchg +atomic_compare_exchange_strong_acquire :: intrinsics.atomic_cxchg_acq +atomic_compare_exchange_strong_release :: intrinsics.atomic_cxchg_rel +atomic_compare_exchange_strong_acqrel :: intrinsics.atomic_cxchg_acqrel +atomic_compare_exchange_strong_relaxed :: intrinsics.atomic_cxchg_relaxed +atomic_compare_exchange_strong_failrelaxed :: intrinsics.atomic_cxchg_failrelaxed +atomic_compare_exchange_strong_failacquire :: intrinsics.atomic_cxchg_failacq +atomic_compare_exchange_strong_acquire_failrelaxed :: intrinsics.atomic_cxchg_acq_failrelaxed +atomic_compare_exchange_strong_acqrel_failrelaxed :: intrinsics.atomic_cxchg_acqrel_failrelaxed // Returns value and optional ok boolean -atomic_compare_exchange_weak :: intrinsics.atomic_cxchgweak; -atomic_compare_exchange_weak_acquire :: intrinsics.atomic_cxchgweak_acq; -atomic_compare_exchange_weak_release :: intrinsics.atomic_cxchgweak_rel; -atomic_compare_exchange_weak_acqrel :: intrinsics.atomic_cxchgweak_acqrel; -atomic_compare_exchange_weak_relaxed :: intrinsics.atomic_cxchgweak_relaxed; -atomic_compare_exchange_weak_failrelaxed :: intrinsics.atomic_cxchgweak_failrelaxed; -atomic_compare_exchange_weak_failacquire :: intrinsics.atomic_cxchgweak_failacq; -atomic_compare_exchange_weak_acquire_failrelaxed :: intrinsics.atomic_cxchgweak_acq_failrelaxed; -atomic_compare_exchange_weak_acqrel_failrelaxed :: intrinsics.atomic_cxchgweak_acqrel_failrelaxed; +atomic_compare_exchange_weak :: intrinsics.atomic_cxchgweak +atomic_compare_exchange_weak_acquire :: intrinsics.atomic_cxchgweak_acq +atomic_compare_exchange_weak_release :: intrinsics.atomic_cxchgweak_rel +atomic_compare_exchange_weak_acqrel :: intrinsics.atomic_cxchgweak_acqrel +atomic_compare_exchange_weak_relaxed :: intrinsics.atomic_cxchgweak_relaxed +atomic_compare_exchange_weak_failrelaxed :: intrinsics.atomic_cxchgweak_failrelaxed +atomic_compare_exchange_weak_failacquire :: intrinsics.atomic_cxchgweak_failacq +atomic_compare_exchange_weak_acquire_failrelaxed :: intrinsics.atomic_cxchgweak_acq_failrelaxed +atomic_compare_exchange_weak_acqrel_failrelaxed :: intrinsics.atomic_cxchgweak_acqrel_failrelaxed diff --git a/core/sync/sync2/extended.odin b/core/sync/sync2/extended.odin index e7acbbbd2..8f99fc0e3 100644 --- a/core/sync/sync2/extended.odin +++ b/core/sync/sync2/extended.odin @@ -11,36 +11,36 @@ Wait_Group :: struct { wait_group_add :: proc(wg: ^Wait_Group, delta: int) { if delta == 0 { - return; + return } - mutex_lock(&wg.mutex); - defer mutex_unlock(&wg.mutex); + mutex_lock(&wg.mutex) + defer mutex_unlock(&wg.mutex) - atomic_add(&wg.counter, delta); + atomic_add(&wg.counter, delta) if wg.counter < 0 { - panic("sync.Wait_Group negative counter"); + panic("sync.Wait_Group negative counter") } if wg.counter == 0 { - cond_broadcast(&wg.cond); + cond_broadcast(&wg.cond) if wg.counter != 0 { - panic("sync.Wait_Group misuse: sync.wait_group_add called concurrently with sync.wait_group_wait"); + panic("sync.Wait_Group misuse: sync.wait_group_add called concurrently with sync.wait_group_wait") } } } wait_group_done :: proc(wg: ^Wait_Group) { - wait_group_add(wg, -1); + wait_group_add(wg, -1) } wait_group_wait :: proc(wg: ^Wait_Group) { - mutex_lock(&wg.mutex); - defer mutex_unlock(&wg.mutex); + mutex_lock(&wg.mutex) + defer mutex_unlock(&wg.mutex) if wg.counter != 0 { - cond_wait(&wg.cond, &wg.mutex); + cond_wait(&wg.cond, &wg.mutex) if wg.counter != 0 { - panic("sync.Wait_Group misuse: sync.wait_group_add called concurrently with sync.wait_group_wait"); + panic("sync.Wait_Group misuse: sync.wait_group_add called concurrently with sync.wait_group_wait") } } } @@ -94,29 +94,29 @@ Barrier :: struct { } barrier_init :: proc(b: ^Barrier, thread_count: int) { - b.index = 0; - b.generation_id = 0; - b.thread_count = thread_count; + b.index = 0 + b.generation_id = 0 + b.thread_count = thread_count } // Block the current thread until all threads have rendezvoused // Barrier can be reused after all threads rendezvoused once, and can be used continuously barrier_wait :: proc(b: ^Barrier) -> (is_leader: bool) { - mutex_lock(&b.mutex); - defer mutex_unlock(&b.mutex); - local_gen := b.generation_id; - b.index += 1; + mutex_lock(&b.mutex) + defer mutex_unlock(&b.mutex) + local_gen := b.generation_id + b.index += 1 if b.index < b.thread_count { for local_gen == b.generation_id && b.index < b.thread_count { - cond_wait(&b.cond, &b.mutex); + cond_wait(&b.cond, &b.mutex) } - return false; + return false } - b.index = 0; - b.generation_id += 1; - cond_broadcast(&b.cond); - return true; + b.index = 0 + b.generation_id += 1 + cond_broadcast(&b.cond) + return true } @@ -129,23 +129,23 @@ Auto_Reset_Event :: struct { } auto_reset_event_signal :: proc(e: ^Auto_Reset_Event) { - old_status := atomic_load_relaxed(&e.status); + old_status := atomic_load_relaxed(&e.status) for { - new_status := old_status + 1 if old_status < 1 else 1; + new_status := old_status + 1 if old_status < 1 else 1 if _, ok := atomic_compare_exchange_weak_release(&e.status, old_status, new_status); ok { - break; + break } if old_status < 0 { - sema_post(&e.sema); + sema_post(&e.sema) } } } auto_reset_event_wait :: proc(e: ^Auto_Reset_Event) { - old_status := atomic_sub_acquire(&e.status, 1); + old_status := atomic_sub_acquire(&e.status, 1) if old_status < 1 { - sema_wait(&e.sema); + sema_wait(&e.sema) } } @@ -157,14 +157,14 @@ Ticket_Mutex :: struct { } ticket_mutex_lock :: #force_inline proc(m: ^Ticket_Mutex) { - ticket := atomic_add_relaxed(&m.ticket, 1); + ticket := atomic_add_relaxed(&m.ticket, 1) for ticket != atomic_load_acquire(&m.serving) { - cpu_relax(); + cpu_relax() } } ticket_mutex_unlock :: #force_inline proc(m: ^Ticket_Mutex) { - atomic_add_relaxed(&m.serving, 1); + atomic_add_relaxed(&m.serving, 1) } @@ -176,18 +176,18 @@ Benaphore :: struct { benaphore_lock :: proc(b: ^Benaphore) { if atomic_add_acquire(&b.counter, 1) > 1 { - sema_wait(&b.sema); + sema_wait(&b.sema) } } benaphore_try_lock :: proc(b: ^Benaphore) -> bool { - v, _ := atomic_compare_exchange_strong_acquire(&b.counter, 1, 0); - return v == 0; + v, _ := atomic_compare_exchange_strong_acquire(&b.counter, 1, 0) + return v == 0 } benaphore_unlock :: proc(b: ^Benaphore) { if atomic_sub_release(&b.counter, 1) > 0 { - sema_post(&b.sema); + sema_post(&b.sema) } } @@ -199,43 +199,43 @@ Recursive_Benaphore :: struct { } recursive_benaphore_lock :: proc(b: ^Recursive_Benaphore) { - tid := current_thread_id(); + tid := current_thread_id() if atomic_add_acquire(&b.counter, 1) > 1 { if tid != b.owner { - sema_wait(&b.sema); + sema_wait(&b.sema) } } // inside the lock - b.owner = tid; - b.recursion += 1; + b.owner = tid + b.recursion += 1 } recursive_benaphore_try_lock :: proc(b: ^Recursive_Benaphore) -> bool { - tid := current_thread_id(); + tid := current_thread_id() if b.owner == tid { - atomic_add_acquire(&b.counter, 1); + atomic_add_acquire(&b.counter, 1) } if v, _ := atomic_compare_exchange_strong_acquire(&b.counter, 1, 0); v != 0 { - return false; + return false } // inside the lock - b.owner = tid; - b.recursion += 1; - return true; + b.owner = tid + b.recursion += 1 + return true } recursive_benaphore_unlock :: proc(b: ^Recursive_Benaphore) { - tid := current_thread_id(); - assert(tid == b.owner); - b.recursion -= 1; - recursion := b.recursion; + tid := current_thread_id() + assert(tid == b.owner) + b.recursion -= 1 + recursion := b.recursion if recursion == 0 { - b.owner = 0; + b.owner = 0 } if atomic_sub_release(&b.counter, 1) > 0 { if recursion == 0 { - sema_post(&b.sema); + sema_post(&b.sema) } } // outside the lock @@ -252,16 +252,16 @@ Once :: struct { once_do :: proc(o: ^Once, fn: proc()) { if atomic_load_acquire(&o.done) == false { - _once_do_slow(o, fn); + _once_do_slow(o, fn) } } @(cold) _once_do_slow :: proc(o: ^Once, fn: proc()) { - mutex_lock(&o.m); - defer mutex_unlock(&o.m); + mutex_lock(&o.m) + defer mutex_unlock(&o.m) if !o.done { - fn(); - atomic_store_release(&o.done, true); + fn() + atomic_store_release(&o.done, true) } } diff --git a/core/sync/sync2/primitives.odin b/core/sync/sync2/primitives.odin index d0a4439d2..7d7115274 100644 --- a/core/sync/sync2/primitives.odin +++ b/core/sync/sync2/primitives.odin @@ -3,7 +3,7 @@ package sync2 import "core:time" current_thread_id :: proc "contextless" () -> int { - return _current_thread_id(); + return _current_thread_id() } // A Mutex is a mutual exclusion lock @@ -16,17 +16,17 @@ Mutex :: struct { // mutex_lock locks m mutex_lock :: proc(m: ^Mutex) { - _mutex_lock(m); + _mutex_lock(m) } // mutex_unlock unlocks m mutex_unlock :: proc(m: ^Mutex) { - _mutex_unlock(m); + _mutex_unlock(m) } // mutex_lock tries to lock m, will return true on success, and false on failure mutex_try_lock :: proc(m: ^Mutex) -> bool { - return _mutex_try_lock(m); + return _mutex_try_lock(m) } // Example: @@ -37,8 +37,8 @@ mutex_try_lock :: proc(m: ^Mutex) -> bool { // @(deferred_in=mutex_unlock) mutex_guard :: proc(m: ^Mutex) -> bool { - mutex_lock(m); - return true; + mutex_lock(m) + return true } // A RW_Mutex is a reader/writer mutual exclusion lock @@ -53,32 +53,32 @@ RW_Mutex :: struct { // rw_mutex_lock locks rw for writing (with a single writer) // If the mutex is already locked for reading or writing, the mutex blocks until the mutex is available. rw_mutex_lock :: proc(rw: ^RW_Mutex) { - _rw_mutex_lock(rw); + _rw_mutex_lock(rw) } // rw_mutex_unlock unlocks rw for writing (with a single writer) rw_mutex_unlock :: proc(rw: ^RW_Mutex) { - _rw_mutex_unlock(rw); + _rw_mutex_unlock(rw) } // rw_mutex_try_lock tries to lock rw for writing (with a single writer) rw_mutex_try_lock :: proc(rw: ^RW_Mutex) -> bool { - return _rw_mutex_try_lock(rw); + return _rw_mutex_try_lock(rw) } // rw_mutex_shared_lock locks rw for reading (with arbitrary number of readers) rw_mutex_shared_lock :: proc(rw: ^RW_Mutex) { - _rw_mutex_shared_lock(rw); + _rw_mutex_shared_lock(rw) } // rw_mutex_shared_unlock unlocks rw for reading (with arbitrary number of readers) rw_mutex_shared_unlock :: proc(rw: ^RW_Mutex) { - _rw_mutex_shared_unlock(rw); + _rw_mutex_shared_unlock(rw) } // rw_mutex_try_shared_lock tries to lock rw for reading (with arbitrary number of readers) rw_mutex_try_shared_lock :: proc(rw: ^RW_Mutex) -> bool { - return _rw_mutex_try_shared_lock(rw); + return _rw_mutex_try_shared_lock(rw) } // Example: @@ -89,8 +89,8 @@ rw_mutex_try_shared_lock :: proc(rw: ^RW_Mutex) -> bool { // @(deferred_in=rw_mutex_unlock) rw_mutex_guard :: proc(m: ^RW_Mutex) -> bool { - rw_mutex_lock(m); - return true; + rw_mutex_lock(m) + return true } // Example: @@ -101,8 +101,8 @@ rw_mutex_guard :: proc(m: ^RW_Mutex) -> bool { // @(deferred_in=rw_mutex_shared_unlock) rw_mutex_shared_guard :: proc(m: ^RW_Mutex) -> bool { - rw_mutex_shared_lock(m); - return true; + rw_mutex_shared_lock(m) + return true } @@ -116,15 +116,15 @@ Recursive_Mutex :: struct { } recursive_mutex_lock :: proc(m: ^Recursive_Mutex) { - _recursive_mutex_lock(m); + _recursive_mutex_lock(m) } recursive_mutex_unlock :: proc(m: ^Recursive_Mutex) { - _recursive_mutex_unlock(m); + _recursive_mutex_unlock(m) } recursive_mutex_try_lock :: proc(m: ^Recursive_Mutex) -> bool { - return _recursive_mutex_try_lock(m); + return _recursive_mutex_try_lock(m) } @@ -136,8 +136,8 @@ recursive_mutex_try_lock :: proc(m: ^Recursive_Mutex) -> bool { // @(deferred_in=recursive_mutex_unlock) recursive_mutex_guard :: proc(m: ^Recursive_Mutex) -> bool { - recursive_mutex_lock(m); - return true; + recursive_mutex_lock(m) + return true } @@ -150,19 +150,19 @@ Cond :: struct { } cond_wait :: proc(c: ^Cond, m: ^Mutex) { - _cond_wait(c, m); + _cond_wait(c, m) } cond_wait_with_timeout :: proc(c: ^Cond, m: ^Mutex, timeout: time.Duration) -> bool { - return _cond_wait_with_timeout(c, m, timeout); + return _cond_wait_with_timeout(c, m, timeout) } cond_signal :: proc(c: ^Cond) { - _cond_signal(c); + _cond_signal(c) } cond_broadcast :: proc(c: ^Cond) { - _cond_broadcast(c); + _cond_broadcast(c) } @@ -177,9 +177,9 @@ Sema :: struct { sema_wait :: proc(s: ^Sema) { - _sema_wait(s); + _sema_wait(s) } sema_post :: proc(s: ^Sema, count := 1) { - _sema_post(s, count); + _sema_post(s, count) } diff --git a/core/sync/sync2/primitives_atomic.odin b/core/sync/sync2/primitives_atomic.odin index 315c21a31..c8c049dde 100644 --- a/core/sync/sync2/primitives_atomic.odin +++ b/core/sync/sync2/primitives_atomic.odin @@ -21,30 +21,30 @@ Atomic_Mutex :: struct { atomic_mutex_lock :: proc(m: ^Atomic_Mutex) { @(cold) lock_slow :: proc(m: ^Atomic_Mutex, curr_state: Atomic_Mutex_State) { - new_state := curr_state; // Make a copy of it + new_state := curr_state // Make a copy of it spin_lock: for spin in 0..<i32(100) { - state, ok := atomic_compare_exchange_weak_acquire(&m.state, .Unlocked, new_state); + state, ok := atomic_compare_exchange_weak_acquire(&m.state, .Unlocked, new_state) if ok { - return; + return } if state == .Waiting { - break spin_lock; + break spin_lock } for i := min(spin+1, 32); i > 0; i -= 1 { - cpu_relax(); + cpu_relax() } } for { if atomic_exchange_acquire(&m.state, .Waiting) == .Unlocked { - return; + return } // TODO(bill): Use a Futex here for Linux to improve performance and error handling - cpu_relax(); + cpu_relax() } } @@ -52,9 +52,9 @@ atomic_mutex_lock :: proc(m: ^Atomic_Mutex) { switch v := atomic_exchange_acquire(&m.state, .Locked); v { case .Unlocked: // Okay - case: fallthrough; + case: fallthrough case .Locked, .Waiting: - lock_slow(m, v); + lock_slow(m, v) } } @@ -68,18 +68,18 @@ atomic_mutex_unlock :: proc(m: ^Atomic_Mutex) { switch atomic_exchange_release(&m.state, .Unlocked) { case .Unlocked: - unreachable(); + unreachable() case .Locked: // Okay case .Waiting: - unlock_slow(m); + unlock_slow(m) } } // atomic_mutex_try_lock tries to lock m, will return true on success, and false on failure atomic_mutex_try_lock :: proc(m: ^Atomic_Mutex) -> bool { - _, ok := atomic_compare_exchange_strong_acquire(&m.state, .Unlocked, .Locked); - return ok; + _, ok := atomic_compare_exchange_strong_acquire(&m.state, .Unlocked, .Locked) + return ok } @@ -91,19 +91,19 @@ atomic_mutex_try_lock :: proc(m: ^Atomic_Mutex) -> bool { // @(deferred_in=atomic_mutex_unlock) atomic_mutex_guard :: proc(m: ^Atomic_Mutex) -> bool { - atomic_mutex_lock(m); - return true; + atomic_mutex_lock(m) + return true } -Atomic_RW_Mutex_State :: distinct uint; -Atomic_RW_Mutex_State_Half_Width :: size_of(Atomic_RW_Mutex_State)*8/2; -Atomic_RW_Mutex_State_Is_Writing :: Atomic_RW_Mutex_State(1); -Atomic_RW_Mutex_State_Writer :: Atomic_RW_Mutex_State(1)<<1; -Atomic_RW_Mutex_State_Reader :: Atomic_RW_Mutex_State(1)<<Atomic_RW_Mutex_State_Half_Width; +Atomic_RW_Mutex_State :: distinct uint +Atomic_RW_Mutex_State_Half_Width :: size_of(Atomic_RW_Mutex_State)*8/2 +Atomic_RW_Mutex_State_Is_Writing :: Atomic_RW_Mutex_State(1) +Atomic_RW_Mutex_State_Writer :: Atomic_RW_Mutex_State(1)<<1 +Atomic_RW_Mutex_State_Reader :: Atomic_RW_Mutex_State(1)<<Atomic_RW_Mutex_State_Half_Width -Atomic_RW_Mutex_State_Writer_Mask :: Atomic_RW_Mutex_State(1<<(Atomic_RW_Mutex_State_Half_Width-1) - 1) << 1; -Atomic_RW_Mutex_State_Reader_Mask :: Atomic_RW_Mutex_State(1<<(Atomic_RW_Mutex_State_Half_Width-1) - 1) << Atomic_RW_Mutex_State_Half_Width; +Atomic_RW_Mutex_State_Writer_Mask :: Atomic_RW_Mutex_State(1<<(Atomic_RW_Mutex_State_Half_Width-1) - 1) << 1 +Atomic_RW_Mutex_State_Reader_Mask :: Atomic_RW_Mutex_State(1<<(Atomic_RW_Mutex_State_Half_Width-1) - 1) << Atomic_RW_Mutex_State_Half_Width // An Atomic_RW_Mutex is a reader/writer mutual exclusion lock @@ -120,77 +120,77 @@ Atomic_RW_Mutex :: struct { // atomic_rw_mutex_lock locks rw for writing (with a single writer) // If the mutex is already locked for reading or writing, the mutex blocks until the mutex is available. atomic_rw_mutex_lock :: proc(rw: ^Atomic_RW_Mutex) { - _ = atomic_add(&rw.state, Atomic_RW_Mutex_State_Writer); - atomic_mutex_lock(&rw.mutex); + _ = atomic_add(&rw.state, Atomic_RW_Mutex_State_Writer) + atomic_mutex_lock(&rw.mutex) - state := atomic_or(&rw.state, Atomic_RW_Mutex_State_Writer); + state := atomic_or(&rw.state, Atomic_RW_Mutex_State_Writer) if state & Atomic_RW_Mutex_State_Reader_Mask != 0 { - atomic_sema_wait(&rw.sema); + atomic_sema_wait(&rw.sema) } } // atomic_rw_mutex_unlock unlocks rw for writing (with a single writer) atomic_rw_mutex_unlock :: proc(rw: ^Atomic_RW_Mutex) { - _ = atomic_and(&rw.state, ~Atomic_RW_Mutex_State_Is_Writing); - atomic_mutex_unlock(&rw.mutex); + _ = atomic_and(&rw.state, ~Atomic_RW_Mutex_State_Is_Writing) + atomic_mutex_unlock(&rw.mutex) } // atomic_rw_mutex_try_lock tries to lock rw for writing (with a single writer) atomic_rw_mutex_try_lock :: proc(rw: ^Atomic_RW_Mutex) -> bool { if atomic_mutex_try_lock(&rw.mutex) { - state := atomic_load(&rw.state); + state := atomic_load(&rw.state) if state & Atomic_RW_Mutex_State_Reader_Mask == 0 { - _ = atomic_or(&rw.state, Atomic_RW_Mutex_State_Is_Writing); - return true; + _ = atomic_or(&rw.state, Atomic_RW_Mutex_State_Is_Writing) + return true } - atomic_mutex_unlock(&rw.mutex); + atomic_mutex_unlock(&rw.mutex) } - return false; + return false } // atomic_rw_mutex_shared_lock locks rw for reading (with arbitrary number of readers) atomic_rw_mutex_shared_lock :: proc(rw: ^Atomic_RW_Mutex) { - state := atomic_load(&rw.state); + state := atomic_load(&rw.state) for state & (Atomic_RW_Mutex_State_Is_Writing|Atomic_RW_Mutex_State_Writer_Mask) == 0 { - ok: bool; - state, ok = atomic_compare_exchange_weak(&rw.state, state, state + Atomic_RW_Mutex_State_Reader); + ok: bool + state, ok = atomic_compare_exchange_weak(&rw.state, state, state + Atomic_RW_Mutex_State_Reader) if ok { - return; + return } } - atomic_mutex_lock(&rw.mutex); - _ = atomic_add(&rw.state, Atomic_RW_Mutex_State_Reader); - atomic_mutex_unlock(&rw.mutex); + atomic_mutex_lock(&rw.mutex) + _ = atomic_add(&rw.state, Atomic_RW_Mutex_State_Reader) + atomic_mutex_unlock(&rw.mutex) } // atomic_rw_mutex_shared_unlock unlocks rw for reading (with arbitrary number of readers) atomic_rw_mutex_shared_unlock :: proc(rw: ^Atomic_RW_Mutex) { - state := atomic_sub(&rw.state, Atomic_RW_Mutex_State_Reader); + state := atomic_sub(&rw.state, Atomic_RW_Mutex_State_Reader) if (state & Atomic_RW_Mutex_State_Reader_Mask == Atomic_RW_Mutex_State_Reader) && (state & Atomic_RW_Mutex_State_Is_Writing != 0) { - atomic_sema_post(&rw.sema); + atomic_sema_post(&rw.sema) } } // atomic_rw_mutex_try_shared_lock tries to lock rw for reading (with arbitrary number of readers) atomic_rw_mutex_try_shared_lock :: proc(rw: ^Atomic_RW_Mutex) -> bool { - state := atomic_load(&rw.state); + state := atomic_load(&rw.state) if state & (Atomic_RW_Mutex_State_Is_Writing|Atomic_RW_Mutex_State_Writer_Mask) == 0 { - _, ok := atomic_compare_exchange_strong(&rw.state, state, state + Atomic_RW_Mutex_State_Reader); + _, ok := atomic_compare_exchange_strong(&rw.state, state, state + Atomic_RW_Mutex_State_Reader) if ok { - return true; + return true } } if atomic_mutex_try_lock(&rw.mutex) { - _ = atomic_add(&rw.state, Atomic_RW_Mutex_State_Reader); - atomic_mutex_unlock(&rw.mutex); - return true; + _ = atomic_add(&rw.state, Atomic_RW_Mutex_State_Reader) + atomic_mutex_unlock(&rw.mutex) + return true } - return false; + return false } @@ -202,8 +202,8 @@ atomic_rw_mutex_try_shared_lock :: proc(rw: ^Atomic_RW_Mutex) -> bool { // @(deferred_in=atomic_rw_mutex_unlock) atomic_rw_mutex_guard :: proc(m: ^Atomic_RW_Mutex) -> bool { - atomic_rw_mutex_lock(m); - return true; + atomic_rw_mutex_lock(m) + return true } // Example: @@ -214,8 +214,8 @@ atomic_rw_mutex_guard :: proc(m: ^Atomic_RW_Mutex) -> bool { // @(deferred_in=atomic_rw_mutex_shared_unlock) atomic_rw_mutex_shared_guard :: proc(m: ^Atomic_RW_Mutex) -> bool { - atomic_rw_mutex_shared_lock(m); - return true; + atomic_rw_mutex_shared_lock(m) + return true } @@ -232,42 +232,42 @@ Atomic_Recursive_Mutex :: struct { } atomic_recursive_mutex_lock :: proc(m: ^Atomic_Recursive_Mutex) { - tid := current_thread_id(); + tid := current_thread_id() if tid != m.owner { - mutex_lock(&m.mutex); + mutex_lock(&m.mutex) } // inside the lock - m.owner = tid; - m.recursion += 1; + m.owner = tid + m.recursion += 1 } atomic_recursive_mutex_unlock :: proc(m: ^Atomic_Recursive_Mutex) { - tid := current_thread_id(); - assert(tid == m.owner); - m.recursion -= 1; - recursion := m.recursion; + tid := current_thread_id() + assert(tid == m.owner) + m.recursion -= 1 + recursion := m.recursion if recursion == 0 { - m.owner = 0; + m.owner = 0 } if recursion == 0 { - mutex_unlock(&m.mutex); + mutex_unlock(&m.mutex) } // outside the lock } atomic_recursive_mutex_try_lock :: proc(m: ^Atomic_Recursive_Mutex) -> bool { - tid := current_thread_id(); + tid := current_thread_id() if m.owner == tid { - return mutex_try_lock(&m.mutex); + return mutex_try_lock(&m.mutex) } if !mutex_try_lock(&m.mutex) { - return false; + return false } // inside the lock - m.owner = tid; - m.recursion += 1; - return true; + m.owner = tid + m.recursion += 1 + return true } @@ -279,8 +279,8 @@ atomic_recursive_mutex_try_lock :: proc(m: ^Atomic_Recursive_Mutex) -> bool { // @(deferred_in=atomic_recursive_mutex_unlock) atomic_recursive_mutex_guard :: proc(m: ^Atomic_Recursive_Mutex) -> bool { - atomic_recursive_mutex_lock(m); - return true; + atomic_recursive_mutex_lock(m) + return true } @@ -296,12 +296,12 @@ Queue_Item :: struct { queue_item_wait :: proc(item: ^Queue_Item) { for atomic_load_acquire(&item.futex) == 0 { // TODO(bill): Use a Futex here for Linux to improve performance and error handling - cpu_relax(); + cpu_relax() } } @(private="file") queue_item_signal :: proc(item: ^Queue_Item) { - atomic_store_release(&item.futex, 1); + atomic_store_release(&item.futex, 1) // TODO(bill): Use a Futex here for Linux to improve performance and error handling } @@ -317,58 +317,58 @@ Atomic_Cond :: struct { } atomic_cond_wait :: proc(c: ^Atomic_Cond, m: ^Atomic_Mutex) { - waiter := &Queue_Item{}; + waiter := &Queue_Item{} - atomic_mutex_lock(&c.queue_mutex); - waiter.next = c.queue_head; - c.queue_head = waiter; + atomic_mutex_lock(&c.queue_mutex) + waiter.next = c.queue_head + c.queue_head = waiter - atomic_store(&c.pending, true); - atomic_mutex_unlock(&c.queue_mutex); + atomic_store(&c.pending, true) + atomic_mutex_unlock(&c.queue_mutex) - atomic_mutex_unlock(m); - queue_item_wait(waiter); - atomic_mutex_lock(m); + atomic_mutex_unlock(m) + queue_item_wait(waiter) + atomic_mutex_lock(m) } atomic_cond_wait_with_timeout :: proc(c: ^Atomic_Cond, m: ^Atomic_Mutex, timeout: time.Duration) -> bool { // TODO(bill): _cond_wait_with_timeout for unix - return false; + return false } atomic_cond_signal :: proc(c: ^Atomic_Cond) { if !atomic_load(&c.pending) { - return; + return } - atomic_mutex_lock(&c.queue_mutex); - waiter := c.queue_head; + atomic_mutex_lock(&c.queue_mutex) + waiter := c.queue_head if c.queue_head != nil { - c.queue_head = c.queue_head.next; + c.queue_head = c.queue_head.next } - atomic_store(&c.pending, c.queue_head != nil); - atomic_mutex_unlock(&c.queue_mutex); + atomic_store(&c.pending, c.queue_head != nil) + atomic_mutex_unlock(&c.queue_mutex) if waiter != nil { - queue_item_signal(waiter); + queue_item_signal(waiter) } } atomic_cond_broadcast :: proc(c: ^Atomic_Cond) { if !atomic_load(&c.pending) { - return; + return } - atomic_store(&c.pending, false); + atomic_store(&c.pending, false) - atomic_mutex_lock(&c.queue_mutex); - waiters := c.queue_head; - c.queue_head = nil; - atomic_mutex_unlock(&c.queue_mutex); + atomic_mutex_lock(&c.queue_mutex) + waiters := c.queue_head + c.queue_head = nil + atomic_mutex_unlock(&c.queue_mutex) for waiters != nil { - queue_item_signal(waiters); - waiters = waiters.next; + queue_item_signal(waiters) + waiters = waiters.next } } @@ -383,24 +383,24 @@ Atomic_Sema :: struct { } atomic_sema_wait :: proc(s: ^Atomic_Sema) { - atomic_mutex_lock(&s.mutex); - defer atomic_mutex_unlock(&s.mutex); + atomic_mutex_lock(&s.mutex) + defer atomic_mutex_unlock(&s.mutex) for s.count == 0 { - atomic_cond_wait(&s.cond, &s.mutex); + atomic_cond_wait(&s.cond, &s.mutex) } - s.count -= 1; + s.count -= 1 if s.count > 0 { - atomic_cond_signal(&s.cond); + atomic_cond_signal(&s.cond) } } atomic_sema_post :: proc(s: ^Atomic_Sema, count := 1) { - atomic_mutex_lock(&s.mutex); - defer atomic_mutex_unlock(&s.mutex); + atomic_mutex_lock(&s.mutex) + defer atomic_mutex_unlock(&s.mutex) - s.count += count; - atomic_cond_signal(&s.cond); + s.count += count + atomic_cond_signal(&s.cond) } diff --git a/core/sync/sync2/primitives_windows.odin b/core/sync/sync2/primitives_windows.odin index 582572aa9..934df6a2a 100644 --- a/core/sync/sync2/primitives_windows.odin +++ b/core/sync/sync2/primitives_windows.odin @@ -6,7 +6,7 @@ import "core:time" import win32 "core:sys/windows" _current_thread_id :: proc "contextless" () -> int { - return int(win32.GetCurrentThreadId()); + return int(win32.GetCurrentThreadId()) } _Mutex :: struct { @@ -14,15 +14,15 @@ _Mutex :: struct { } _mutex_lock :: proc(m: ^Mutex) { - win32.AcquireSRWLockExclusive(&m.impl.srwlock); + win32.AcquireSRWLockExclusive(&m.impl.srwlock) } _mutex_unlock :: proc(m: ^Mutex) { - win32.ReleaseSRWLockExclusive(&m.impl.srwlock); + win32.ReleaseSRWLockExclusive(&m.impl.srwlock) } _mutex_try_lock :: proc(m: ^Mutex) -> bool { - return bool(win32.TryAcquireSRWLockExclusive(&m.impl.srwlock)); + return bool(win32.TryAcquireSRWLockExclusive(&m.impl.srwlock)) } _RW_Mutex :: struct { @@ -30,27 +30,27 @@ _RW_Mutex :: struct { } _rw_mutex_lock :: proc(rw: ^RW_Mutex) { - win32.AcquireSRWLockExclusive(&rw.impl.srwlock); + win32.AcquireSRWLockExclusive(&rw.impl.srwlock) } _rw_mutex_unlock :: proc(rw: ^RW_Mutex) { - win32.ReleaseSRWLockExclusive(&rw.impl.srwlock); + win32.ReleaseSRWLockExclusive(&rw.impl.srwlock) } _rw_mutex_try_lock :: proc(rw: ^RW_Mutex) -> bool { - return bool(win32.TryAcquireSRWLockExclusive(&rw.impl.srwlock)); + return bool(win32.TryAcquireSRWLockExclusive(&rw.impl.srwlock)) } _rw_mutex_shared_lock :: proc(rw: ^RW_Mutex) { - win32.AcquireSRWLockShared(&rw.impl.srwlock); + win32.AcquireSRWLockShared(&rw.impl.srwlock) } _rw_mutex_shared_unlock :: proc(rw: ^RW_Mutex) { - win32.ReleaseSRWLockShared(&rw.impl.srwlock); + win32.ReleaseSRWLockShared(&rw.impl.srwlock) } _rw_mutex_try_shared_lock :: proc(rw: ^RW_Mutex) -> bool { - return bool(win32.TryAcquireSRWLockShared(&rw.impl.srwlock)); + return bool(win32.TryAcquireSRWLockShared(&rw.impl.srwlock)) } @@ -60,14 +60,14 @@ _Recursive_Mutex :: struct { } _recursive_mutex_lock :: proc(m: ^Recursive_Mutex) { - tid := win32.GetCurrentThreadId(); + tid := win32.GetCurrentThreadId() for { - prev_owner := atomic_compare_exchange_strong_acquire(&m.impl.owner, tid, 0); + prev_owner := atomic_compare_exchange_strong_acquire(&m.impl.owner, tid, 0) switch prev_owner { case 0, tid: - m.impl.claim_count += 1; + m.impl.claim_count += 1 // inside the lock - return; + return } win32.WaitOnAddress( @@ -75,31 +75,31 @@ _recursive_mutex_lock :: proc(m: ^Recursive_Mutex) { &prev_owner, size_of(prev_owner), win32.INFINITE, - ); + ) } } _recursive_mutex_unlock :: proc(m: ^Recursive_Mutex) { - m.impl.claim_count -= 1; + m.impl.claim_count -= 1 if m.impl.claim_count != 0 { - return; + return } - atomic_exchange_release(&m.impl.owner, 0); - win32.WakeByAddressSingle(&m.impl.owner); + atomic_exchange_release(&m.impl.owner, 0) + win32.WakeByAddressSingle(&m.impl.owner) // outside the lock } _recursive_mutex_try_lock :: proc(m: ^Recursive_Mutex) -> bool { - tid := win32.GetCurrentThreadId(); - prev_owner := atomic_compare_exchange_strong_acquire(&m.impl.owner, tid, 0); + tid := win32.GetCurrentThreadId() + prev_owner := atomic_compare_exchange_strong_acquire(&m.impl.owner, tid, 0) switch prev_owner { case 0, tid: - m.impl.claim_count += 1; + m.impl.claim_count += 1 // inside the lock - return true; + return true } - return false; + return false } @@ -110,20 +110,20 @@ _Cond :: struct { } _cond_wait :: proc(c: ^Cond, m: ^Mutex) { - _ = win32.SleepConditionVariableSRW(&c.impl.cond, &m.impl.srwlock, win32.INFINITE, 0); + _ = win32.SleepConditionVariableSRW(&c.impl.cond, &m.impl.srwlock, win32.INFINITE, 0) } _cond_wait_with_timeout :: proc(c: ^Cond, m: ^Mutex, timeout: time.Duration) -> bool { - ms := win32.DWORD((max(time.duration_nanoseconds(timeout), 0) + 999999)/1000000); - return cast(bool)win32.SleepConditionVariableSRW(&c.impl.cond, &m.impl.srwlock, ms, 0); + ms := win32.DWORD((max(time.duration_nanoseconds(timeout), 0) + 999999)/1000000) + return cast(bool)win32.SleepConditionVariableSRW(&c.impl.cond, &m.impl.srwlock, ms, 0) } _cond_signal :: proc(c: ^Cond) { - win32.WakeConditionVariable(&c.impl.cond); + win32.WakeConditionVariable(&c.impl.cond) } _cond_broadcast :: proc(c: ^Cond) { - win32.WakeAllConditionVariable(&c.impl.cond); + win32.WakeAllConditionVariable(&c.impl.cond) } @@ -133,27 +133,27 @@ _Sema :: struct { _sema_wait :: proc(s: ^Sema) { for { - original_count := s.impl.count; + original_count := s.impl.count for original_count == 0 { win32.WaitOnAddress( &s.impl.count, &original_count, size_of(original_count), win32.INFINITE, - ); - original_count = s.impl.count; + ) + original_count = s.impl.count } if original_count == atomic_compare_exchange_strong(&s.impl.count, original_count-1, original_count) { - return; + return } } } _sema_post :: proc(s: ^Sema, count := 1) { - atomic_add(&s.impl.count, i32(count)); + atomic_add(&s.impl.count, i32(count)) if count == 1 { - win32.WakeByAddressSingle(&s.impl.count); + win32.WakeByAddressSingle(&s.impl.count) } else { - win32.WakeByAddressAll(&s.impl.count); + win32.WakeByAddressAll(&s.impl.count) } } diff --git a/core/sync/sync_windows.odin b/core/sync/sync_windows.odin index 2bfd82567..0a7cf71b2 100644 --- a/core/sync/sync_windows.odin +++ b/core/sync/sync_windows.odin @@ -5,7 +5,7 @@ import win32 "core:sys/windows" import "core:time" current_thread_id :: proc "contextless" () -> int { - return int(win32.GetCurrentThreadId()); + return int(win32.GetCurrentThreadId()) } @@ -16,21 +16,21 @@ Semaphore :: struct { } semaphore_init :: proc(s: ^Semaphore, initial_count := 0) { - s._handle = win32.CreateSemaphoreW(nil, i32(initial_count), 1<<31-1, nil); + s._handle = win32.CreateSemaphoreW(nil, i32(initial_count), 1<<31-1, nil) } semaphore_destroy :: proc(s: ^Semaphore) { - win32.CloseHandle(s._handle); + win32.CloseHandle(s._handle) } semaphore_post :: proc(s: ^Semaphore, count := 1) { - win32.ReleaseSemaphore(s._handle, i32(count), nil); + win32.ReleaseSemaphore(s._handle, i32(count), nil) } semaphore_wait_for :: proc(s: ^Semaphore) { // NOTE(tetra, 2019-10-30): wait_for_single_object decrements the count before it returns. - result := win32.WaitForSingleObject(s._handle, win32.INFINITE); - assert(result != win32.WAIT_FAILED); + result := win32.WaitForSingleObject(s._handle, win32.INFINITE) + assert(result != win32.WAIT_FAILED) } @@ -40,23 +40,23 @@ Mutex :: struct { mutex_init :: proc(m: ^Mutex, spin_count := 0) { - win32.InitializeCriticalSectionAndSpinCount(&m._critical_section, u32(spin_count)); + win32.InitializeCriticalSectionAndSpinCount(&m._critical_section, u32(spin_count)) } mutex_destroy :: proc(m: ^Mutex) { - win32.DeleteCriticalSection(&m._critical_section); + win32.DeleteCriticalSection(&m._critical_section) } mutex_lock :: proc(m: ^Mutex) { - win32.EnterCriticalSection(&m._critical_section); + win32.EnterCriticalSection(&m._critical_section) } mutex_try_lock :: proc(m: ^Mutex) -> bool { - return bool(win32.TryEnterCriticalSection(&m._critical_section)); + return bool(win32.TryEnterCriticalSection(&m._critical_section)) } mutex_unlock :: proc(m: ^Mutex) { - win32.LeaveCriticalSection(&m._critical_section); + win32.LeaveCriticalSection(&m._critical_section) } Blocking_Mutex :: struct { @@ -65,7 +65,7 @@ Blocking_Mutex :: struct { blocking_mutex_init :: proc(m: ^Blocking_Mutex) { - win32.InitializeSRWLock(&m._handle); + win32.InitializeSRWLock(&m._handle) } blocking_mutex_destroy :: proc(m: ^Blocking_Mutex) { @@ -73,15 +73,15 @@ blocking_mutex_destroy :: proc(m: ^Blocking_Mutex) { } blocking_mutex_lock :: proc(m: ^Blocking_Mutex) { - win32.AcquireSRWLockExclusive(&m._handle); + win32.AcquireSRWLockExclusive(&m._handle) } blocking_mutex_try_lock :: proc(m: ^Blocking_Mutex) -> bool { - return bool(win32.TryAcquireSRWLockExclusive(&m._handle)); + return bool(win32.TryAcquireSRWLockExclusive(&m._handle)) } blocking_mutex_unlock :: proc(m: ^Blocking_Mutex) { - win32.ReleaseSRWLockExclusive(&m._handle); + win32.ReleaseSRWLockExclusive(&m._handle) } @@ -95,10 +95,10 @@ Condition :: struct { condition_init :: proc(c: ^Condition, mutex: Condition_Mutex_Ptr) -> bool { - assert(mutex != nil); - win32.InitializeConditionVariable(&c._handle); - c.mutex = mutex; - return true; + assert(mutex != nil) + win32.InitializeConditionVariable(&c._handle) + c.mutex = mutex + return true } condition_destroy :: proc(c: ^Condition) { @@ -107,38 +107,38 @@ condition_destroy :: proc(c: ^Condition) { condition_signal :: proc(c: ^Condition) -> bool { if c._handle.ptr == nil { - return false; + return false } - win32.WakeConditionVariable(&c._handle); - return true; + win32.WakeConditionVariable(&c._handle) + return true } condition_broadcast :: proc(c: ^Condition) -> bool { if c._handle.ptr == nil { - return false; + return false } - win32.WakeAllConditionVariable(&c._handle); - return true; + win32.WakeAllConditionVariable(&c._handle) + return true } condition_wait_for :: proc(c: ^Condition) -> bool { switch m in &c.mutex { case ^Mutex: - return cast(bool)win32.SleepConditionVariableCS(&c._handle, &m._critical_section, win32.INFINITE); + return cast(bool)win32.SleepConditionVariableCS(&c._handle, &m._critical_section, win32.INFINITE) case ^Blocking_Mutex: - return cast(bool)win32.SleepConditionVariableSRW(&c._handle, &m._handle, win32.INFINITE, 0); + return cast(bool)win32.SleepConditionVariableSRW(&c._handle, &m._handle, win32.INFINITE, 0) } - return false; + return false } condition_wait_for_timeout :: proc(c: ^Condition, duration: time.Duration) -> bool { - ms := win32.DWORD((max(time.duration_nanoseconds(duration), 0) + 999999)/1000000); + ms := win32.DWORD((max(time.duration_nanoseconds(duration), 0) + 999999)/1000000) switch m in &c.mutex { case ^Mutex: - return cast(bool)win32.SleepConditionVariableCS(&c._handle, &m._critical_section, ms); + return cast(bool)win32.SleepConditionVariableCS(&c._handle, &m._critical_section, ms) case ^Blocking_Mutex: - return cast(bool)win32.SleepConditionVariableSRW(&c._handle, &m._handle, ms, 0); + return cast(bool)win32.SleepConditionVariableSRW(&c._handle, &m._handle, ms, 0) } - return false; + return false } @@ -149,32 +149,32 @@ RW_Lock :: struct { } rw_lock_init :: proc(l: ^RW_Lock) { - l._handle = win32.SRWLOCK_INIT; + l._handle = win32.SRWLOCK_INIT } rw_lock_destroy :: proc(l: ^RW_Lock) { // } rw_lock_read :: proc(l: ^RW_Lock) { - win32.AcquireSRWLockShared(&l._handle); + win32.AcquireSRWLockShared(&l._handle) } rw_lock_try_read :: proc(l: ^RW_Lock) -> bool { - return bool(win32.TryAcquireSRWLockShared(&l._handle)); + return bool(win32.TryAcquireSRWLockShared(&l._handle)) } rw_lock_write :: proc(l: ^RW_Lock) { - win32.AcquireSRWLockExclusive(&l._handle); + win32.AcquireSRWLockExclusive(&l._handle) } rw_lock_try_write :: proc(l: ^RW_Lock) -> bool { - return bool(win32.TryAcquireSRWLockExclusive(&l._handle)); + return bool(win32.TryAcquireSRWLockExclusive(&l._handle)) } rw_lock_read_unlock :: proc(l: ^RW_Lock) { - win32.ReleaseSRWLockShared(&l._handle); + win32.ReleaseSRWLockShared(&l._handle) } rw_lock_write_unlock :: proc(l: ^RW_Lock) { - win32.ReleaseSRWLockExclusive(&l._handle); + win32.ReleaseSRWLockExclusive(&l._handle) } thread_yield :: proc() { - win32.SwitchToThread(); + win32.SwitchToThread() } diff --git a/core/sync/wait_group.odin b/core/sync/wait_group.odin index a05ff9d71..63d882ed1 100644 --- a/core/sync/wait_group.odin +++ b/core/sync/wait_group.odin @@ -9,49 +9,49 @@ Wait_Group :: struct { } wait_group_init :: proc(wg: ^Wait_Group) { - wg.counter = 0; - blocking_mutex_init(&wg.mutex); - condition_init(&wg.cond, &wg.mutex); + wg.counter = 0 + blocking_mutex_init(&wg.mutex) + condition_init(&wg.cond, &wg.mutex) } wait_group_destroy :: proc(wg: ^Wait_Group) { - condition_destroy(&wg.cond); - blocking_mutex_destroy(&wg.mutex); + condition_destroy(&wg.cond) + blocking_mutex_destroy(&wg.mutex) } wait_group_add :: proc(wg: ^Wait_Group, delta: int) { if delta == 0 { - return; + return } - blocking_mutex_lock(&wg.mutex); - defer blocking_mutex_unlock(&wg.mutex); + blocking_mutex_lock(&wg.mutex) + defer blocking_mutex_unlock(&wg.mutex) - intrinsics.atomic_add(&wg.counter, delta); + intrinsics.atomic_add(&wg.counter, delta) if wg.counter < 0 { - panic("sync.Wait_Group negative counter"); + panic("sync.Wait_Group negative counter") } if wg.counter == 0 { - condition_broadcast(&wg.cond); + condition_broadcast(&wg.cond) if wg.counter != 0 { - panic("sync.Wait_Group misuse: sync.wait_group_add called concurrently with sync.wait_group_wait"); + panic("sync.Wait_Group misuse: sync.wait_group_add called concurrently with sync.wait_group_wait") } } } wait_group_done :: proc(wg: ^Wait_Group) { - wait_group_add(wg, -1); + wait_group_add(wg, -1) } wait_group_wait :: proc(wg: ^Wait_Group) { - blocking_mutex_lock(&wg.mutex); - defer blocking_mutex_unlock(&wg.mutex); + blocking_mutex_lock(&wg.mutex) + defer blocking_mutex_unlock(&wg.mutex) if wg.counter != 0 { - condition_wait_for(&wg.cond); + condition_wait_for(&wg.cond) if wg.counter != 0 { - panic("sync.Wait_Group misuse: sync.wait_group_add called concurrently with sync.wait_group_wait"); + panic("sync.Wait_Group misuse: sync.wait_group_add called concurrently with sync.wait_group_wait") } } } diff --git a/core/sys/win32/comdlg32.odin b/core/sys/win32/comdlg32.odin index ccb684551..7b4d06d80 100644 --- a/core/sys/win32/comdlg32.odin +++ b/core/sys/win32/comdlg32.odin @@ -4,7 +4,7 @@ package win32 foreign import "system:comdlg32.lib" import "core:strings" -OFN_Hook_Proc :: #type proc "stdcall" (hdlg: Hwnd, msg: u32, wparam: Wparam, lparam: Lparam) -> Uint_Ptr; +OFN_Hook_Proc :: #type proc "stdcall" (hdlg: Hwnd, msg: u32, wparam: Wparam, lparam: Lparam) -> Uint_Ptr Open_File_Name_A :: struct { struct_size: u32, @@ -67,13 +67,13 @@ foreign comdlg32 { @(link_name="CommDlgExtendedError") comm_dlg_extended_error :: proc() -> u32 --- } -OPEN_TITLE :: "Select file to open"; -OPEN_FLAGS :: u32(OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST); -OPEN_FLAGS_MULTI :: OPEN_FLAGS | OFN_ALLOWMULTISELECT | OFN_EXPLORER; +OPEN_TITLE :: "Select file to open" +OPEN_FLAGS :: u32(OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST) +OPEN_FLAGS_MULTI :: OPEN_FLAGS | OFN_ALLOWMULTISELECT | OFN_EXPLORER -SAVE_TITLE :: "Select file to save"; -SAVE_FLAGS :: u32(OFN_OVERWRITEPROMPT | OFN_EXPLORER); -SAVE_EXT :: "txt"; +SAVE_TITLE :: "Select file to save" +SAVE_FLAGS :: u32(OFN_OVERWRITEPROMPT | OFN_EXPLORER) +SAVE_EXT :: "txt" Open_Save_Mode :: enum { Open = 0, @@ -84,15 +84,15 @@ _open_file_dialog :: proc(title: string, dir: string, filters: []string, default_filter: u32, flags: u32, default_ext: string, mode: Open_Save_Mode, allocator := context.temp_allocator) -> (path: string, ok: bool = true) { - file_buf := make([]u16, MAX_PATH_WIDE, allocator); + file_buf := make([]u16, MAX_PATH_WIDE, allocator) // Filters need to be passed as a pair of strings (title, filter) - filter_len := u32(len(filters)); - if filter_len % 2 != 0 do return "", false; + filter_len := u32(len(filters)) + if filter_len % 2 != 0 do return "", false - filter: string; - filter = strings.join(filters, "\u0000", context.temp_allocator); - filter = strings.concatenate({filter, "\u0000"}, context.temp_allocator); + filter: string + filter = strings.join(filters, "\u0000", context.temp_allocator) + filter = strings.concatenate({filter, "\u0000"}, context.temp_allocator) ofn := Open_File_Name_W{ struct_size = size_of(Open_File_Name_W), @@ -104,33 +104,33 @@ _open_file_dialog :: proc(title: string, dir: string, filter_index = u32(clamp(default_filter, 1, filter_len / 2)), def_ext = utf8_to_wstring(default_ext, context.temp_allocator), flags = u32(flags), - }; + } switch mode { case .Open: - ok = bool(get_open_file_name_w(&ofn)); + ok = bool(get_open_file_name_w(&ofn)) case .Save: - ok = bool(get_save_file_name_w(&ofn)); + ok = bool(get_save_file_name_w(&ofn)) case: - ok = false; + ok = false } if !ok { - delete(file_buf); - return "", false; + delete(file_buf) + return "", false } - file_name := utf16_to_utf8(file_buf[:], allocator); - path = strings.trim_right_null(file_name); - return; + file_name := utf16_to_utf8(file_buf[:], allocator) + path = strings.trim_right_null(file_name) + return } select_file_to_open :: proc(title := OPEN_TITLE, dir := ".", filters := []string{"All Files", "*.*"}, default_filter := u32(1), flags := OPEN_FLAGS, allocator := context.temp_allocator) -> (path: string, ok: bool) { - path, ok = _open_file_dialog(title, dir, filters, default_filter, flags, "", Open_Save_Mode.Open, allocator); - return; + path, ok = _open_file_dialog(title, dir, filters, default_filter, flags, "", Open_Save_Mode.Open, allocator) + return } select_file_to_save :: proc(title := SAVE_TITLE, dir := ".", @@ -138,51 +138,51 @@ select_file_to_save :: proc(title := SAVE_TITLE, dir := ".", flags := SAVE_FLAGS, default_ext := SAVE_EXT, allocator := context.temp_allocator) -> (path: string, ok: bool) { - path, ok = _open_file_dialog(title, dir, filters, default_filter, flags, default_ext, Open_Save_Mode.Save, allocator); - return; + path, ok = _open_file_dialog(title, dir, filters, default_filter, flags, default_ext, Open_Save_Mode.Save, allocator) + return } // TODO: Implement convenience function for select_file_to_open with ALLOW_MULTI_SELECT that takes // it output of the form "path\u0000\file1u\0000file2" and turns it into []string with the path + file pre-concatenated for you. -OFN_ALLOWMULTISELECT :: 0x00000200; // NOTE(Jeroen): Without OFN_EXPLORER it uses the Win3 dialog. -OFN_CREATEPROMPT :: 0x00002000; -OFN_DONTADDTORECENT :: 0x02000000; -OFN_ENABLEHOOK :: 0x00000020; -OFN_ENABLEINCLUDENOTIFY :: 0x00400000; -OFN_ENABLESIZING :: 0x00800000; -OFN_ENABLETEMPLATE :: 0x00000040; -OFN_ENABLETEMPLATEHANDLE :: 0x00000080; -OFN_EXPLORER :: 0x00080000; -OFN_EXTENSIONDIFFERENT :: 0x00000400; -OFN_FILEMUSTEXIST :: 0x00001000; -OFN_FORCESHOWHIDDEN :: 0x10000000; -OFN_HIDEREADONLY :: 0x00000004; -OFN_LONGNAMES :: 0x00200000; -OFN_NOCHANGEDIR :: 0x00000008; -OFN_NODEREFERENCELINKS :: 0x00100000; -OFN_NOLONGNAMES :: 0x00040000; -OFN_NONETWORKBUTTON :: 0x00020000; -OFN_NOREADONLYRETURN :: 0x00008000; -OFN_NOTESTFILECREATE :: 0x00010000; -OFN_NOVALIDATE :: 0x00000100; -OFN_OVERWRITEPROMPT :: 0x00000002; -OFN_PATHMUSTEXIST :: 0x00000800; -OFN_READONLY :: 0x00000001; -OFN_SHAREAWARE :: 0x00004000; -OFN_SHOWHELP :: 0x00000010; - -CDERR_DIALOGFAILURE :: 0x0000FFFF; -CDERR_GENERALCODES :: 0x00000000; -CDERR_STRUCTSIZE :: 0x00000001; -CDERR_INITIALIZATION :: 0x00000002; -CDERR_NOTEMPLATE :: 0x00000003; -CDERR_NOHINSTANCE :: 0x00000004; -CDERR_LOADSTRFAILURE :: 0x00000005; -CDERR_FINDRESFAILURE :: 0x00000006; -CDERR_LOADRESFAILURE :: 0x00000007; -CDERR_LOCKRESFAILURE :: 0x00000008; -CDERR_MEMALLOCFAILURE :: 0x00000009; -CDERR_MEMLOCKFAILURE :: 0x0000000A; -CDERR_NOHOOK :: 0x0000000B; -CDERR_REGISTERMSGFAIL :: 0x0000000C; +OFN_ALLOWMULTISELECT :: 0x00000200 // NOTE(Jeroen): Without OFN_EXPLORER it uses the Win3 dialog. +OFN_CREATEPROMPT :: 0x00002000 +OFN_DONTADDTORECENT :: 0x02000000 +OFN_ENABLEHOOK :: 0x00000020 +OFN_ENABLEINCLUDENOTIFY :: 0x00400000 +OFN_ENABLESIZING :: 0x00800000 +OFN_ENABLETEMPLATE :: 0x00000040 +OFN_ENABLETEMPLATEHANDLE :: 0x00000080 +OFN_EXPLORER :: 0x00080000 +OFN_EXTENSIONDIFFERENT :: 0x00000400 +OFN_FILEMUSTEXIST :: 0x00001000 +OFN_FORCESHOWHIDDEN :: 0x10000000 +OFN_HIDEREADONLY :: 0x00000004 +OFN_LONGNAMES :: 0x00200000 +OFN_NOCHANGEDIR :: 0x00000008 +OFN_NODEREFERENCELINKS :: 0x00100000 +OFN_NOLONGNAMES :: 0x00040000 +OFN_NONETWORKBUTTON :: 0x00020000 +OFN_NOREADONLYRETURN :: 0x00008000 +OFN_NOTESTFILECREATE :: 0x00010000 +OFN_NOVALIDATE :: 0x00000100 +OFN_OVERWRITEPROMPT :: 0x00000002 +OFN_PATHMUSTEXIST :: 0x00000800 +OFN_READONLY :: 0x00000001 +OFN_SHAREAWARE :: 0x00004000 +OFN_SHOWHELP :: 0x00000010 + +CDERR_DIALOGFAILURE :: 0x0000FFFF +CDERR_GENERALCODES :: 0x00000000 +CDERR_STRUCTSIZE :: 0x00000001 +CDERR_INITIALIZATION :: 0x00000002 +CDERR_NOTEMPLATE :: 0x00000003 +CDERR_NOHINSTANCE :: 0x00000004 +CDERR_LOADSTRFAILURE :: 0x00000005 +CDERR_FINDRESFAILURE :: 0x00000006 +CDERR_LOADRESFAILURE :: 0x00000007 +CDERR_LOCKRESFAILURE :: 0x00000008 +CDERR_MEMALLOCFAILURE :: 0x00000009 +CDERR_MEMLOCKFAILURE :: 0x0000000A +CDERR_NOHOOK :: 0x0000000B +CDERR_REGISTERMSGFAIL :: 0x0000000C diff --git a/core/sys/win32/crt.odin b/core/sys/win32/crt.odin index 983f2505b..b39d35375 100644 --- a/core/sys/win32/crt.odin +++ b/core/sys/win32/crt.odin @@ -1,15 +1,15 @@ // +build windows package win32 -import "core:strings"; +import "core:strings" foreign { @(link_name="_wgetcwd") _get_cwd_wide :: proc(buffer: Wstring, buf_len: int) -> ^Wstring --- } get_cwd :: proc(allocator := context.temp_allocator) -> string { - buffer := make([]u16, MAX_PATH_WIDE, allocator); - _get_cwd_wide(Wstring(&buffer[0]), MAX_PATH_WIDE); - file := utf16_to_utf8(buffer[:], allocator); - return strings.trim_right_null(file); + buffer := make([]u16, MAX_PATH_WIDE, allocator) + _get_cwd_wide(Wstring(&buffer[0]), MAX_PATH_WIDE) + file := utf16_to_utf8(buffer[:], allocator) + return strings.trim_right_null(file) } diff --git a/core/sys/win32/gdi32.odin b/core/sys/win32/gdi32.odin index 4b0e905f5..13bc4796f 100644 --- a/core/sys/win32/gdi32.odin +++ b/core/sys/win32/gdi32.odin @@ -3,12 +3,12 @@ package win32 foreign import "system:gdi32.lib" -WHITENESS :: 0x00FF0062; -BLACKNESS :: 0x00000042; +WHITENESS :: 0x00FF0062 +BLACKNESS :: 0x00000042 @(default_calling_convention = "std") foreign gdi32 { - @(link_name="GetStockObject") get_stock_object :: proc(fn_object: i32) -> Hgdiobj ---; + @(link_name="GetStockObject") get_stock_object :: proc(fn_object: i32) -> Hgdiobj --- @(link_name="StretchDIBits") stretch_dibits :: proc(hdc: Hdc, @@ -16,11 +16,11 @@ foreign gdi32 { x_src, y_src, width_src, header_src: i32, bits: rawptr, bits_info: ^Bitmap_Info, usage: u32, - rop: u32) -> i32 ---; + rop: u32) -> i32 --- - @(link_name="SetPixelFormat") set_pixel_format :: proc(hdc: Hdc, pixel_format: i32, pfd: ^Pixel_Format_Descriptor) -> Bool ---; - @(link_name="ChoosePixelFormat") choose_pixel_format :: proc(hdc: Hdc, pfd: ^Pixel_Format_Descriptor) -> i32 ---; - @(link_name="SwapBuffers") swap_buffers :: proc(hdc: Hdc) -> Bool ---; + @(link_name="SetPixelFormat") set_pixel_format :: proc(hdc: Hdc, pixel_format: i32, pfd: ^Pixel_Format_Descriptor) -> Bool --- + @(link_name="ChoosePixelFormat") choose_pixel_format :: proc(hdc: Hdc, pfd: ^Pixel_Format_Descriptor) -> i32 --- + @(link_name="SwapBuffers") swap_buffers :: proc(hdc: Hdc) -> Bool --- - @(link_name="PatBlt") pat_blt :: proc(hdc: Hdc, x, y, w, h: i32, rop: u32) -> Bool ---; + @(link_name="PatBlt") pat_blt :: proc(hdc: Hdc, x, y, w, h: i32, rop: u32) -> Bool --- } diff --git a/core/sys/win32/general.odin b/core/sys/win32/general.odin index 3f78397f3..5131fa8d8 100644 --- a/core/sys/win32/general.odin +++ b/core/sys/win32/general.odin @@ -1,36 +1,36 @@ // +build windows package win32 -Uint_Ptr :: distinct uintptr; -Int_Ptr :: distinct int; -Long_Ptr :: distinct int; - -Handle :: distinct rawptr; -Hwnd :: distinct Handle; -Hdc :: distinct Handle; -Hinstance :: distinct Handle; -Hicon :: distinct Handle; -Hcursor :: distinct Handle; -Hmenu :: distinct Handle; -Hbitmap :: distinct Handle; -Hbrush :: distinct Handle; -Hgdiobj :: distinct Handle; -Hmodule :: distinct Handle; -Hmonitor :: distinct Handle; -Hrawinput :: distinct Handle; -Hresult :: distinct i32; -HKL :: distinct Handle; -Wparam :: distinct Uint_Ptr; -Lparam :: distinct Long_Ptr; -Lresult :: distinct Long_Ptr; -Wnd_Proc :: distinct #type proc "std" (Hwnd, u32, Wparam, Lparam) -> Lresult; -Monitor_Enum_Proc :: distinct #type proc "std" (Hmonitor, Hdc, ^Rect, Lparam) -> bool; - - - -Bool :: distinct b32; - -Wstring :: distinct ^u16; +Uint_Ptr :: distinct uintptr +Int_Ptr :: distinct int +Long_Ptr :: distinct int + +Handle :: distinct rawptr +Hwnd :: distinct Handle +Hdc :: distinct Handle +Hinstance :: distinct Handle +Hicon :: distinct Handle +Hcursor :: distinct Handle +Hmenu :: distinct Handle +Hbitmap :: distinct Handle +Hbrush :: distinct Handle +Hgdiobj :: distinct Handle +Hmodule :: distinct Handle +Hmonitor :: distinct Handle +Hrawinput :: distinct Handle +Hresult :: distinct i32 +HKL :: distinct Handle +Wparam :: distinct Uint_Ptr +Lparam :: distinct Long_Ptr +Lresult :: distinct Long_Ptr +Wnd_Proc :: distinct #type proc "std" (Hwnd, u32, Wparam, Lparam) -> Lresult +Monitor_Enum_Proc :: distinct #type proc "std" (Hmonitor, Hdc, ^Rect, Lparam) -> bool + + + +Bool :: distinct b32 + +Wstring :: distinct ^u16 Point :: struct { x, y: i32, @@ -246,7 +246,7 @@ Critical_Section_Debug :: struct { spare_word: u16, } -List_Entry :: struct {flink, blink: ^List_Entry}; +List_Entry :: struct {flink, blink: ^List_Entry} Raw_Input_Device :: struct { @@ -358,83 +358,83 @@ OS_Version_Info_Ex_A :: struct { reserved: u8, } -MAPVK_VK_TO_VSC :: 0; -MAPVK_VSC_TO_VK :: 1; -MAPVK_VK_TO_CHAR :: 2; -MAPVK_VSC_TO_VK_EX :: 3; +MAPVK_VK_TO_VSC :: 0 +MAPVK_VSC_TO_VK :: 1 +MAPVK_VK_TO_CHAR :: 2 +MAPVK_VSC_TO_VK_EX :: 3 //WinUser.h -VK_LBUTTON :: 0x01; -VK_RBUTTON :: 0x02; -VK_CANCEL :: 0x03; -VK_MBUTTON :: 0x04; /* NOT contiguous with L & RBUTTON */ -VK_XBUTTON1 :: 0x05; /* NOT contiguous with L & RBUTTON */ -VK_XBUTTON2 :: 0x06; /* NOT contiguous with L & RBUTTON */ +VK_LBUTTON :: 0x01 +VK_RBUTTON :: 0x02 +VK_CANCEL :: 0x03 +VK_MBUTTON :: 0x04 /* NOT contiguous with L & RBUTTON */ +VK_XBUTTON1 :: 0x05 /* NOT contiguous with L & RBUTTON */ +VK_XBUTTON2 :: 0x06 /* NOT contiguous with L & RBUTTON */ /* * :: 0x07 : reserved */ -VK_BACK :: 0x08; -VK_TAB :: 0x09; +VK_BACK :: 0x08 +VK_TAB :: 0x09 /* * :: 0x0A - :: 0x0B : reserved */ -VK_CLEAR :: 0x0C; -VK_RETURN :: 0x0D; +VK_CLEAR :: 0x0C +VK_RETURN :: 0x0D /* * :: 0x0E - :: 0x0F : unassigned */ -VK_SHIFT :: 0x10; -VK_CONTROL :: 0x11; -VK_MENU :: 0x12; -VK_PAUSE :: 0x13; -VK_CAPITAL :: 0x14; +VK_SHIFT :: 0x10 +VK_CONTROL :: 0x11 +VK_MENU :: 0x12 +VK_PAUSE :: 0x13 +VK_CAPITAL :: 0x14 -VK_KANA :: 0x15; -VK_HANGEUL :: 0x15; /* old name - should be here for compatibility */ -VK_HANGUL :: 0x15; +VK_KANA :: 0x15 +VK_HANGEUL :: 0x15 /* old name - should be here for compatibility */ +VK_HANGUL :: 0x15 /* * :: 0x16 : unassigned */ -VK_JUNJA :: 0x17; -VK_FINAL :: 0x18; -VK_HANJA :: 0x19; -VK_KANJI :: 0x19; +VK_JUNJA :: 0x17 +VK_FINAL :: 0x18 +VK_HANJA :: 0x19 +VK_KANJI :: 0x19 /* * :: 0x1A : unassigned */ -VK_ESCAPE :: 0x1B; - -VK_CONVERT :: 0x1C; -VK_NONCONVERT :: 0x1D; -VK_ACCEPT :: 0x1E; -VK_MODECHANGE :: 0x1F; - -VK_SPACE :: 0x20; -VK_PRIOR :: 0x21; -VK_NEXT :: 0x22; -VK_END :: 0x23; -VK_HOME :: 0x24; -VK_LEFT :: 0x25; -VK_UP :: 0x26; -VK_RIGHT :: 0x27; -VK_DOWN :: 0x28; -VK_SELECT :: 0x29; -VK_PRINT :: 0x2A; -VK_EXECUTE :: 0x2B; -VK_SNAPSHOT :: 0x2C; -VK_INSERT :: 0x2D; -VK_DELETE :: 0x2E; -VK_HELP :: 0x2F; +VK_ESCAPE :: 0x1B + +VK_CONVERT :: 0x1C +VK_NONCONVERT :: 0x1D +VK_ACCEPT :: 0x1E +VK_MODECHANGE :: 0x1F + +VK_SPACE :: 0x20 +VK_PRIOR :: 0x21 +VK_NEXT :: 0x22 +VK_END :: 0x23 +VK_HOME :: 0x24 +VK_LEFT :: 0x25 +VK_UP :: 0x26 +VK_RIGHT :: 0x27 +VK_DOWN :: 0x28 +VK_SELECT :: 0x29 +VK_PRINT :: 0x2A +VK_EXECUTE :: 0x2B +VK_SNAPSHOT :: 0x2C +VK_INSERT :: 0x2D +VK_DELETE :: 0x2E +VK_HELP :: 0x2F /* * VK_0 - VK_9 are the same as ASCII '0' - '9' (:: 0x30 - :: 0x39) @@ -442,376 +442,376 @@ VK_HELP :: 0x2F; * VK_A - VK_Z are the same as ASCII 'A' - 'Z' (:: 0x41 - :: 0x5A) */ -VK_LWIN :: 0x5B; -VK_RWIN :: 0x5C; -VK_APPS :: 0x5D; +VK_LWIN :: 0x5B +VK_RWIN :: 0x5C +VK_APPS :: 0x5D /* * :: 0x5E : reserved */ -VK_SLEEP :: 0x5F; - -VK_NUMPAD0 :: 0x60; -VK_NUMPAD1 :: 0x61; -VK_NUMPAD2 :: 0x62; -VK_NUMPAD3 :: 0x63; -VK_NUMPAD4 :: 0x64; -VK_NUMPAD5 :: 0x65; -VK_NUMPAD6 :: 0x66; -VK_NUMPAD7 :: 0x67; -VK_NUMPAD8 :: 0x68; -VK_NUMPAD9 :: 0x69; -VK_MULTIPLY :: 0x6A; -VK_ADD :: 0x6B; -VK_SEPARATOR :: 0x6C; -VK_SUBTRACT :: 0x6D; -VK_DECIMAL :: 0x6E; -VK_DIVIDE :: 0x6F; -VK_F1 :: 0x70; -VK_F2 :: 0x71; -VK_F3 :: 0x72; -VK_F4 :: 0x73; -VK_F5 :: 0x74; -VK_F6 :: 0x75; -VK_F7 :: 0x76; -VK_F8 :: 0x77; -VK_F9 :: 0x78; -VK_F10 :: 0x79; -VK_F11 :: 0x7A; -VK_F12 :: 0x7B; -VK_F13 :: 0x7C; -VK_F14 :: 0x7D; -VK_F15 :: 0x7E; -VK_F16 :: 0x7F; -VK_F17 :: 0x80; -VK_F18 :: 0x81; -VK_F19 :: 0x82; -VK_F20 :: 0x83; -VK_F21 :: 0x84; -VK_F22 :: 0x85; -VK_F23 :: 0x86; -VK_F24 :: 0x87; - -INVALID_HANDLE :: Handle(~uintptr(0)); - -CREATE_SUSPENDED :: 0x00000004; -STACK_SIZE_PARAM_IS_A_RESERVATION :: 0x00010000; -WAIT_ABANDONED :: 0x00000080; -WAIT_OBJECT_0 :: 0; -WAIT_TIMEOUT :: 0x00000102; -WAIT_FAILED :: 0xffffffff; - -CS_VREDRAW :: 0x0001; -CS_HREDRAW :: 0x0002; -CS_OWNDC :: 0x0020; -CW_USEDEFAULT :: -0x80000000; - -WS_OVERLAPPED :: 0; -WS_MAXIMIZEBOX :: 0x00010000; -WS_MINIMIZEBOX :: 0x00020000; -WS_THICKFRAME :: 0x00040000; -WS_SYSMENU :: 0x00080000; -WS_BORDER :: 0x00800000; -WS_CAPTION :: 0x00C00000; -WS_VISIBLE :: 0x10000000; -WS_POPUP :: 0x80000000; -WS_MAXIMIZE :: 0x01000000; -WS_MINIMIZE :: 0x20000000; -WS_OVERLAPPEDWINDOW :: WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX; -WS_POPUPWINDOW :: WS_POPUP | WS_BORDER | WS_SYSMENU; - -WS_EX_DLGMODALFRAME :: 0x00000001; -WS_EX_NOPARENTNOTIFY :: 0x00000004; -WS_EX_TOPMOST :: 0x00000008; -WS_EX_ACCEPTFILES :: 0x00000010; -WS_EX_TRANSPARENT :: 0x00000020; -WS_EX_MDICHILD :: 0x00000040; -WS_EX_TOOLWINDOW :: 0x00000080; -WS_EX_WINDOWEDGE :: 0x00000100; -WS_EX_CLIENTEDGE :: 0x00000200; -WS_EX_CONTEXTHELP :: 0x00000400; -WS_EX_RIGHT :: 0x00001000; -WS_EX_LEFT :: 0x00000000; -WS_EX_RTLREADING :: 0x00002000; -WS_EX_LTRREADING :: 0x00000000; -WS_EX_LEFTSCROLLBAR :: 0x00004000; -WS_EX_RIGHTSCROLLBAR :: 0x00000000; -WS_EX_CONTROLPARENT :: 0x00010000; -WS_EX_STATICEDGE :: 0x00020000; -WS_EX_APPWINDOW :: 0x00040000; -WS_EX_OVERLAPPEDWINDOW :: WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE; -WS_EX_PALETTEWINDOW :: WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST; -WS_EX_LAYERED :: 0x00080000; -WS_EX_NOINHERITLAYOUT :: 0x00100000; // Disable inheritence of mirroring by children -WS_EX_NOREDIRECTIONBITMAP :: 0x00200000; -WS_EX_LAYOUTRTL :: 0x00400000; // Right to left mirroring -WS_EX_COMPOSITED :: 0x02000000; -WS_EX_NOACTIVATE :: 0x08000000; - -WM_ACTIVATE :: 0x0006; -WM_ACTIVATEAPP :: 0x001C; -WM_CHAR :: 0x0102; -WM_CLOSE :: 0x0010; -WM_CREATE :: 0x0001; -WM_DESTROY :: 0x0002; -WM_INPUT :: 0x00FF; -WM_KEYDOWN :: 0x0100; -WM_KEYUP :: 0x0101; -WM_KILLFOCUS :: 0x0008; -WM_QUIT :: 0x0012; -WM_SETCURSOR :: 0x0020; -WM_SETFOCUS :: 0x0007; -WM_SIZE :: 0x0005; -WM_SIZING :: 0x0214; -WM_SYSKEYDOWN :: 0x0104; -WM_SYSKEYUP :: 0x0105; -WM_USER :: 0x0400; -WM_WINDOWPOSCHANGED :: 0x0047; -WM_COMMAND :: 0x0111; -WM_PAINT :: 0x000F; - -WM_MOUSEWHEEL :: 0x020A; -WM_MOUSEMOVE :: 0x0200; -WM_LBUTTONDOWN :: 0x0201; -WM_LBUTTONUP :: 0x0202; -WM_LBUTTONDBLCLK :: 0x0203; -WM_RBUTTONDOWN :: 0x0204; -WM_RBUTTONUP :: 0x0205; -WM_RBUTTONDBLCLK :: 0x0206; -WM_MBUTTONDOWN :: 0x0207; -WM_MBUTTONUP :: 0x0208; -WM_MBUTTONDBLCLK :: 0x0209; - -PM_NOREMOVE :: 0x0000; -PM_REMOVE :: 0x0001; -PM_NOYIELD :: 0x0002; - -BLACK_BRUSH :: 4; - -SM_CXSCREEN :: 0; -SM_CYSCREEN :: 1; - -SW_SHOW :: 5; - -COLOR_BACKGROUND :: Hbrush(uintptr(1)); - -INVALID_SET_FILE_POINTER :: ~u32(0); -HEAP_ZERO_MEMORY :: 0x00000008; -INFINITE :: 0xffffffff; -GWL_EXSTYLE :: -20; -GWLP_HINSTANCE :: -6; -GWLP_ID :: -12; -GWL_STYLE :: -16; -GWLP_USERDATA :: -21; -GWLP_WNDPROC :: -4; -Hwnd_TOP :: Hwnd(uintptr(0)); - -BI_RGB :: 0; -DIB_RGB_COLORS :: 0x00; -SRCCOPY: u32 : 0x00cc0020; - - -MONITOR_DEFAULTTONULL :: 0x00000000; -MONITOR_DEFAULTTOPRIMARY :: 0x00000001; -MONITOR_DEFAULTTONEAREST :: 0x00000002; - -SWP_FRAMECHANGED :: 0x0020; -SWP_NOOWNERZORDER :: 0x0200; -SWP_NOZORDER :: 0x0004; -SWP_NOSIZE :: 0x0001; -SWP_NOMOVE :: 0x0002; +VK_SLEEP :: 0x5F + +VK_NUMPAD0 :: 0x60 +VK_NUMPAD1 :: 0x61 +VK_NUMPAD2 :: 0x62 +VK_NUMPAD3 :: 0x63 +VK_NUMPAD4 :: 0x64 +VK_NUMPAD5 :: 0x65 +VK_NUMPAD6 :: 0x66 +VK_NUMPAD7 :: 0x67 +VK_NUMPAD8 :: 0x68 +VK_NUMPAD9 :: 0x69 +VK_MULTIPLY :: 0x6A +VK_ADD :: 0x6B +VK_SEPARATOR :: 0x6C +VK_SUBTRACT :: 0x6D +VK_DECIMAL :: 0x6E +VK_DIVIDE :: 0x6F +VK_F1 :: 0x70 +VK_F2 :: 0x71 +VK_F3 :: 0x72 +VK_F4 :: 0x73 +VK_F5 :: 0x74 +VK_F6 :: 0x75 +VK_F7 :: 0x76 +VK_F8 :: 0x77 +VK_F9 :: 0x78 +VK_F10 :: 0x79 +VK_F11 :: 0x7A +VK_F12 :: 0x7B +VK_F13 :: 0x7C +VK_F14 :: 0x7D +VK_F15 :: 0x7E +VK_F16 :: 0x7F +VK_F17 :: 0x80 +VK_F18 :: 0x81 +VK_F19 :: 0x82 +VK_F20 :: 0x83 +VK_F21 :: 0x84 +VK_F22 :: 0x85 +VK_F23 :: 0x86 +VK_F24 :: 0x87 + +INVALID_HANDLE :: Handle(~uintptr(0)) + +CREATE_SUSPENDED :: 0x00000004 +STACK_SIZE_PARAM_IS_A_RESERVATION :: 0x00010000 +WAIT_ABANDONED :: 0x00000080 +WAIT_OBJECT_0 :: 0 +WAIT_TIMEOUT :: 0x00000102 +WAIT_FAILED :: 0xffffffff + +CS_VREDRAW :: 0x0001 +CS_HREDRAW :: 0x0002 +CS_OWNDC :: 0x0020 +CW_USEDEFAULT :: -0x80000000 + +WS_OVERLAPPED :: 0 +WS_MAXIMIZEBOX :: 0x00010000 +WS_MINIMIZEBOX :: 0x00020000 +WS_THICKFRAME :: 0x00040000 +WS_SYSMENU :: 0x00080000 +WS_BORDER :: 0x00800000 +WS_CAPTION :: 0x00C00000 +WS_VISIBLE :: 0x10000000 +WS_POPUP :: 0x80000000 +WS_MAXIMIZE :: 0x01000000 +WS_MINIMIZE :: 0x20000000 +WS_OVERLAPPEDWINDOW :: WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX +WS_POPUPWINDOW :: WS_POPUP | WS_BORDER | WS_SYSMENU + +WS_EX_DLGMODALFRAME :: 0x00000001 +WS_EX_NOPARENTNOTIFY :: 0x00000004 +WS_EX_TOPMOST :: 0x00000008 +WS_EX_ACCEPTFILES :: 0x00000010 +WS_EX_TRANSPARENT :: 0x00000020 +WS_EX_MDICHILD :: 0x00000040 +WS_EX_TOOLWINDOW :: 0x00000080 +WS_EX_WINDOWEDGE :: 0x00000100 +WS_EX_CLIENTEDGE :: 0x00000200 +WS_EX_CONTEXTHELP :: 0x00000400 +WS_EX_RIGHT :: 0x00001000 +WS_EX_LEFT :: 0x00000000 +WS_EX_RTLREADING :: 0x00002000 +WS_EX_LTRREADING :: 0x00000000 +WS_EX_LEFTSCROLLBAR :: 0x00004000 +WS_EX_RIGHTSCROLLBAR :: 0x00000000 +WS_EX_CONTROLPARENT :: 0x00010000 +WS_EX_STATICEDGE :: 0x00020000 +WS_EX_APPWINDOW :: 0x00040000 +WS_EX_OVERLAPPEDWINDOW :: WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE +WS_EX_PALETTEWINDOW :: WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST +WS_EX_LAYERED :: 0x00080000 +WS_EX_NOINHERITLAYOUT :: 0x00100000 // Disable inheritence of mirroring by children +WS_EX_NOREDIRECTIONBITMAP :: 0x00200000 +WS_EX_LAYOUTRTL :: 0x00400000 // Right to left mirroring +WS_EX_COMPOSITED :: 0x02000000 +WS_EX_NOACTIVATE :: 0x08000000 + +WM_ACTIVATE :: 0x0006 +WM_ACTIVATEAPP :: 0x001C +WM_CHAR :: 0x0102 +WM_CLOSE :: 0x0010 +WM_CREATE :: 0x0001 +WM_DESTROY :: 0x0002 +WM_INPUT :: 0x00FF +WM_KEYDOWN :: 0x0100 +WM_KEYUP :: 0x0101 +WM_KILLFOCUS :: 0x0008 +WM_QUIT :: 0x0012 +WM_SETCURSOR :: 0x0020 +WM_SETFOCUS :: 0x0007 +WM_SIZE :: 0x0005 +WM_SIZING :: 0x0214 +WM_SYSKEYDOWN :: 0x0104 +WM_SYSKEYUP :: 0x0105 +WM_USER :: 0x0400 +WM_WINDOWPOSCHANGED :: 0x0047 +WM_COMMAND :: 0x0111 +WM_PAINT :: 0x000F + +WM_MOUSEWHEEL :: 0x020A +WM_MOUSEMOVE :: 0x0200 +WM_LBUTTONDOWN :: 0x0201 +WM_LBUTTONUP :: 0x0202 +WM_LBUTTONDBLCLK :: 0x0203 +WM_RBUTTONDOWN :: 0x0204 +WM_RBUTTONUP :: 0x0205 +WM_RBUTTONDBLCLK :: 0x0206 +WM_MBUTTONDOWN :: 0x0207 +WM_MBUTTONUP :: 0x0208 +WM_MBUTTONDBLCLK :: 0x0209 + +PM_NOREMOVE :: 0x0000 +PM_REMOVE :: 0x0001 +PM_NOYIELD :: 0x0002 + +BLACK_BRUSH :: 4 + +SM_CXSCREEN :: 0 +SM_CYSCREEN :: 1 + +SW_SHOW :: 5 + +COLOR_BACKGROUND :: Hbrush(uintptr(1)) + +INVALID_SET_FILE_POINTER :: ~u32(0) +HEAP_ZERO_MEMORY :: 0x00000008 +INFINITE :: 0xffffffff +GWL_EXSTYLE :: -20 +GWLP_HINSTANCE :: -6 +GWLP_ID :: -12 +GWL_STYLE :: -16 +GWLP_USERDATA :: -21 +GWLP_WNDPROC :: -4 +Hwnd_TOP :: Hwnd(uintptr(0)) + +BI_RGB :: 0 +DIB_RGB_COLORS :: 0x00 +SRCCOPY: u32 : 0x00cc0020 + + +MONITOR_DEFAULTTONULL :: 0x00000000 +MONITOR_DEFAULTTOPRIMARY :: 0x00000001 +MONITOR_DEFAULTTONEAREST :: 0x00000002 + +SWP_FRAMECHANGED :: 0x0020 +SWP_NOOWNERZORDER :: 0x0200 +SWP_NOZORDER :: 0x0004 +SWP_NOSIZE :: 0x0001 +SWP_NOMOVE :: 0x0002 // Raw Input -RID_HEADER :: 0x10000005; -RID_INPUT :: 0x10000003; +RID_HEADER :: 0x10000005 +RID_INPUT :: 0x10000003 -RIDEV_APPKEYS :: 0x00000400; -RIDEV_CAPTUREMOUSE :: 0x00000200; -RIDEV_DEVNOTIFY :: 0x00002000; -RIDEV_EXCLUDE :: 0x00000010; -RIDEV_EXINPUTSINK :: 0x00001000; -RIDEV_INPUTSINK :: 0x00000100; -RIDEV_NOHOTKEYS :: 0x00000200; -RIDEV_NOLEGACY :: 0x00000030; -RIDEV_PAGEONLY :: 0x00000020; -RIDEV_REMOVE :: 0x00000001; +RIDEV_APPKEYS :: 0x00000400 +RIDEV_CAPTUREMOUSE :: 0x00000200 +RIDEV_DEVNOTIFY :: 0x00002000 +RIDEV_EXCLUDE :: 0x00000010 +RIDEV_EXINPUTSINK :: 0x00001000 +RIDEV_INPUTSINK :: 0x00000100 +RIDEV_NOHOTKEYS :: 0x00000200 +RIDEV_NOLEGACY :: 0x00000030 +RIDEV_PAGEONLY :: 0x00000020 +RIDEV_REMOVE :: 0x00000001 -RIM_TYPEMOUSE :: 0; -RIM_TYPEKEYBOARD :: 1; -RIM_TYPEHID :: 2; +RIM_TYPEMOUSE :: 0 +RIM_TYPEKEYBOARD :: 1 +RIM_TYPEHID :: 2 -MOUSE_ATTRIBUTES_CHANGED :: 0x04; -MOUSE_MOVE_RELATIVE :: 0; -MOUSE_MOVE_ABSOLUTE :: 1; -MOUSE_VIRTUAL_DESKTOP :: 0x02; +MOUSE_ATTRIBUTES_CHANGED :: 0x04 +MOUSE_MOVE_RELATIVE :: 0 +MOUSE_MOVE_ABSOLUTE :: 1 +MOUSE_VIRTUAL_DESKTOP :: 0x02 -RI_MOUSE_BUTTON_1_DOWN :: 0x0001; -RI_MOUSE_BUTTON_1_UP :: 0x0002; -RI_MOUSE_BUTTON_2_DOWN :: 0x0004; -RI_MOUSE_BUTTON_2_UP :: 0x0008; -RI_MOUSE_BUTTON_3_DOWN :: 0x0010; -RI_MOUSE_BUTTON_3_UP :: 0x0020; -RI_MOUSE_BUTTON_4_DOWN :: 0x0040; -RI_MOUSE_BUTTON_4_UP :: 0x0080; -RI_MOUSE_BUTTON_5_DOWN :: 0x0100; -RI_MOUSE_BUTTON_5_UP :: 0x0200; -RI_MOUSE_LEFT_BUTTON_DOWN :: 0x0001; -RI_MOUSE_LEFT_BUTTON_UP :: 0x0002; -RI_MOUSE_MIDDLE_BUTTON_DOWN :: 0x0010; -RI_MOUSE_MIDDLE_BUTTON_UP :: 0x0020; -RI_MOUSE_RIGHT_BUTTON_DOWN :: 0x0004; -RI_MOUSE_RIGHT_BUTTON_UP :: 0x0008; -RI_MOUSE_WHEEL :: 0x0400; +RI_MOUSE_BUTTON_1_DOWN :: 0x0001 +RI_MOUSE_BUTTON_1_UP :: 0x0002 +RI_MOUSE_BUTTON_2_DOWN :: 0x0004 +RI_MOUSE_BUTTON_2_UP :: 0x0008 +RI_MOUSE_BUTTON_3_DOWN :: 0x0010 +RI_MOUSE_BUTTON_3_UP :: 0x0020 +RI_MOUSE_BUTTON_4_DOWN :: 0x0040 +RI_MOUSE_BUTTON_4_UP :: 0x0080 +RI_MOUSE_BUTTON_5_DOWN :: 0x0100 +RI_MOUSE_BUTTON_5_UP :: 0x0200 +RI_MOUSE_LEFT_BUTTON_DOWN :: 0x0001 +RI_MOUSE_LEFT_BUTTON_UP :: 0x0002 +RI_MOUSE_MIDDLE_BUTTON_DOWN :: 0x0010 +RI_MOUSE_MIDDLE_BUTTON_UP :: 0x0020 +RI_MOUSE_RIGHT_BUTTON_DOWN :: 0x0004 +RI_MOUSE_RIGHT_BUTTON_UP :: 0x0008 +RI_MOUSE_WHEEL :: 0x0400 -RI_KEY_MAKE :: 0x00; -RI_KEY_BREAK :: 0x01; -RI_KEY_E0 :: 0x02; -RI_KEY_E1 :: 0x04; -RI_KEY_TERMSRV_SET_LED :: 0x08; -RI_KEY_TERMSRV_SHADOW :: 0x10; +RI_KEY_MAKE :: 0x00 +RI_KEY_BREAK :: 0x01 +RI_KEY_E0 :: 0x02 +RI_KEY_E1 :: 0x04 +RI_KEY_TERMSRV_SET_LED :: 0x08 +RI_KEY_TERMSRV_SHADOW :: 0x10 // Windows OpenGL -PFD_TYPE_RGBA :: 0; -PFD_TYPE_COLORINDEX :: 1; -PFD_MAIN_PLANE :: 0; -PFD_OVERLAY_PLANE :: 1; -PFD_UNDERLAY_PLANE :: -1; -PFD_DOUBLEBUFFER :: 1; -PFD_STEREO :: 2; -PFD_DRAW_TO_WINDOW :: 4; -PFD_DRAW_TO_BITMAP :: 8; -PFD_SUPPORT_GDI :: 16; -PFD_SUPPORT_OPENGL :: 32; -PFD_GENERIC_FORMAT :: 64; -PFD_NEED_PALETTE :: 128; -PFD_NEED_SYSTEM_PALETTE :: 0x00000100; -PFD_SWAP_EXCHANGE :: 0x00000200; -PFD_SWAP_COPY :: 0x00000400; -PFD_SWAP_LAYER_BUFFERS :: 0x00000800; -PFD_GENERIC_ACCELERATED :: 0x00001000; -PFD_DEPTH_DONTCARE :: 0x20000000; -PFD_DOUBLEBUFFER_DONTCARE :: 0x40000000; -PFD_STEREO_DONTCARE :: 0x80000000; - -GET_FILEEX_INFO_LEVELS :: distinct i32; -GetFileExInfoStandard: GET_FILEEX_INFO_LEVELS : 0; -GetFileExMaxInfoLevel: GET_FILEEX_INFO_LEVELS : 1; - -STARTF_USESHOWWINDOW :: 0x00000001; -STARTF_USESIZE :: 0x00000002; -STARTF_USEPOSITION :: 0x00000004; -STARTF_USECOUNTCHARS :: 0x00000008; -STARTF_USEFILLATTRIBUTE :: 0x00000010; -STARTF_RUNFULLSCREEN :: 0x00000020; // ignored for non-x86 platforms -STARTF_FORCEONFEEDBACK :: 0x00000040; -STARTF_FORCEOFFFEEDBACK :: 0x00000080; -STARTF_USESTDHANDLES :: 0x00000100; -STARTF_USEHOTKEY :: 0x00000200; -STARTF_TITLEISLINKNAME :: 0x00000800; -STARTF_TITLEISAPPID :: 0x00001000; -STARTF_PREVENTPINNING :: 0x00002000; -STARTF_UNTRUSTEDSOURCE :: 0x00008000; - - -MOVEFILE_REPLACE_EXISTING :: 0x00000001; -MOVEFILE_COPY_ALLOWED :: 0x00000002; -MOVEFILE_DELAY_UNTIL_REBOOT :: 0x00000004; -MOVEFILE_WRITE_THROUGH :: 0x00000008; -MOVEFILE_CREATE_HARDLINK :: 0x00000010; -MOVEFILE_FAIL_IF_NOT_TRACKABLE :: 0x00000020; - -FILE_NOTIFY_CHANGE_FILE_NAME :: 0x00000001; -FILE_NOTIFY_CHANGE_DIR_NAME :: 0x00000002; -FILE_NOTIFY_CHANGE_ATTRIBUTES :: 0x00000004; -FILE_NOTIFY_CHANGE_SIZE :: 0x00000008; -FILE_NOTIFY_CHANGE_LAST_WRITE :: 0x00000010; -FILE_NOTIFY_CHANGE_LAST_ACCESS :: 0x00000020; -FILE_NOTIFY_CHANGE_CREATION :: 0x00000040; -FILE_NOTIFY_CHANGE_SECURITY :: 0x00000100; - -FILE_FLAG_WRITE_THROUGH :: 0x80000000; -FILE_FLAG_OVERLAPPED :: 0x40000000; -FILE_FLAG_NO_BUFFERING :: 0x20000000; -FILE_FLAG_RANDOM_ACCESS :: 0x10000000; -FILE_FLAG_SEQUENTIAL_SCAN :: 0x08000000; -FILE_FLAG_DELETE_ON_CLOSE :: 0x04000000; -FILE_FLAG_BACKUP_SEMANTICS :: 0x02000000; -FILE_FLAG_POSIX_SEMANTICS :: 0x01000000; -FILE_FLAG_SESSION_AWARE :: 0x00800000; -FILE_FLAG_OPEN_REPARSE_POINT :: 0x00200000; -FILE_FLAG_OPEN_NO_RECALL :: 0x00100000; -FILE_FLAG_FIRST_PIPE_INSTANCE :: 0x00080000; - -FILE_ACTION_ADDED :: 0x00000001; -FILE_ACTION_REMOVED :: 0x00000002; -FILE_ACTION_MODIFIED :: 0x00000003; -FILE_ACTION_RENAMED_OLD_NAME :: 0x00000004; -FILE_ACTION_RENAMED_NEW_NAME :: 0x00000005; - -CP_ACP :: 0; // default to ANSI code page -CP_OEMCP :: 1; // default to OEM code page -CP_MACCP :: 2; // default to MAC code page -CP_THREAD_ACP :: 3; // current thread's ANSI code page -CP_SYMBOL :: 42; // SYMBOL translations -CP_UTF7 :: 65000; // UTF-7 translation -CP_UTF8 :: 65001; // UTF-8 translation - - -MB_ERR_INVALID_CHARS :: 8; -WC_ERR_INVALID_CHARS :: 128; +PFD_TYPE_RGBA :: 0 +PFD_TYPE_COLORINDEX :: 1 +PFD_MAIN_PLANE :: 0 +PFD_OVERLAY_PLANE :: 1 +PFD_UNDERLAY_PLANE :: -1 +PFD_DOUBLEBUFFER :: 1 +PFD_STEREO :: 2 +PFD_DRAW_TO_WINDOW :: 4 +PFD_DRAW_TO_BITMAP :: 8 +PFD_SUPPORT_GDI :: 16 +PFD_SUPPORT_OPENGL :: 32 +PFD_GENERIC_FORMAT :: 64 +PFD_NEED_PALETTE :: 128 +PFD_NEED_SYSTEM_PALETTE :: 0x00000100 +PFD_SWAP_EXCHANGE :: 0x00000200 +PFD_SWAP_COPY :: 0x00000400 +PFD_SWAP_LAYER_BUFFERS :: 0x00000800 +PFD_GENERIC_ACCELERATED :: 0x00001000 +PFD_DEPTH_DONTCARE :: 0x20000000 +PFD_DOUBLEBUFFER_DONTCARE :: 0x40000000 +PFD_STEREO_DONTCARE :: 0x80000000 + +GET_FILEEX_INFO_LEVELS :: distinct i32 +GetFileExInfoStandard: GET_FILEEX_INFO_LEVELS : 0 +GetFileExMaxInfoLevel: GET_FILEEX_INFO_LEVELS : 1 + +STARTF_USESHOWWINDOW :: 0x00000001 +STARTF_USESIZE :: 0x00000002 +STARTF_USEPOSITION :: 0x00000004 +STARTF_USECOUNTCHARS :: 0x00000008 +STARTF_USEFILLATTRIBUTE :: 0x00000010 +STARTF_RUNFULLSCREEN :: 0x00000020 // ignored for non-x86 platforms +STARTF_FORCEONFEEDBACK :: 0x00000040 +STARTF_FORCEOFFFEEDBACK :: 0x00000080 +STARTF_USESTDHANDLES :: 0x00000100 +STARTF_USEHOTKEY :: 0x00000200 +STARTF_TITLEISLINKNAME :: 0x00000800 +STARTF_TITLEISAPPID :: 0x00001000 +STARTF_PREVENTPINNING :: 0x00002000 +STARTF_UNTRUSTEDSOURCE :: 0x00008000 + + +MOVEFILE_REPLACE_EXISTING :: 0x00000001 +MOVEFILE_COPY_ALLOWED :: 0x00000002 +MOVEFILE_DELAY_UNTIL_REBOOT :: 0x00000004 +MOVEFILE_WRITE_THROUGH :: 0x00000008 +MOVEFILE_CREATE_HARDLINK :: 0x00000010 +MOVEFILE_FAIL_IF_NOT_TRACKABLE :: 0x00000020 + +FILE_NOTIFY_CHANGE_FILE_NAME :: 0x00000001 +FILE_NOTIFY_CHANGE_DIR_NAME :: 0x00000002 +FILE_NOTIFY_CHANGE_ATTRIBUTES :: 0x00000004 +FILE_NOTIFY_CHANGE_SIZE :: 0x00000008 +FILE_NOTIFY_CHANGE_LAST_WRITE :: 0x00000010 +FILE_NOTIFY_CHANGE_LAST_ACCESS :: 0x00000020 +FILE_NOTIFY_CHANGE_CREATION :: 0x00000040 +FILE_NOTIFY_CHANGE_SECURITY :: 0x00000100 + +FILE_FLAG_WRITE_THROUGH :: 0x80000000 +FILE_FLAG_OVERLAPPED :: 0x40000000 +FILE_FLAG_NO_BUFFERING :: 0x20000000 +FILE_FLAG_RANDOM_ACCESS :: 0x10000000 +FILE_FLAG_SEQUENTIAL_SCAN :: 0x08000000 +FILE_FLAG_DELETE_ON_CLOSE :: 0x04000000 +FILE_FLAG_BACKUP_SEMANTICS :: 0x02000000 +FILE_FLAG_POSIX_SEMANTICS :: 0x01000000 +FILE_FLAG_SESSION_AWARE :: 0x00800000 +FILE_FLAG_OPEN_REPARSE_POINT :: 0x00200000 +FILE_FLAG_OPEN_NO_RECALL :: 0x00100000 +FILE_FLAG_FIRST_PIPE_INSTANCE :: 0x00080000 + +FILE_ACTION_ADDED :: 0x00000001 +FILE_ACTION_REMOVED :: 0x00000002 +FILE_ACTION_MODIFIED :: 0x00000003 +FILE_ACTION_RENAMED_OLD_NAME :: 0x00000004 +FILE_ACTION_RENAMED_NEW_NAME :: 0x00000005 + +CP_ACP :: 0 // default to ANSI code page +CP_OEMCP :: 1 // default to OEM code page +CP_MACCP :: 2 // default to MAC code page +CP_THREAD_ACP :: 3 // current thread's ANSI code page +CP_SYMBOL :: 42 // SYMBOL translations +CP_UTF7 :: 65000 // UTF-7 translation +CP_UTF8 :: 65001 // UTF-8 translation + + +MB_ERR_INVALID_CHARS :: 8 +WC_ERR_INVALID_CHARS :: 128 utf8_to_utf16 :: proc(s: string, allocator := context.temp_allocator) -> []u16 { if len(s) < 1 { - return nil; + return nil } - b := transmute([]byte)s; - cstr := cstring(&b[0]); - n := multi_byte_to_wide_char(CP_UTF8, MB_ERR_INVALID_CHARS, cstr, i32(len(s)), nil, 0); + b := transmute([]byte)s + cstr := cstring(&b[0]) + n := multi_byte_to_wide_char(CP_UTF8, MB_ERR_INVALID_CHARS, cstr, i32(len(s)), nil, 0) if n == 0 { - return nil; + return nil } - text := make([]u16, n+1, allocator); + text := make([]u16, n+1, allocator) - n1 := multi_byte_to_wide_char(CP_UTF8, MB_ERR_INVALID_CHARS, cstr, i32(len(s)), Wstring(&text[0]), i32(n)); + n1 := multi_byte_to_wide_char(CP_UTF8, MB_ERR_INVALID_CHARS, cstr, i32(len(s)), Wstring(&text[0]), i32(n)) if n1 == 0 { - delete(text, allocator); - return nil; + delete(text, allocator) + return nil } - text[n] = 0; + text[n] = 0 for n >= 1 && text[n-1] == 0 { - n -= 1; + n -= 1 } - return text[:n]; + return text[:n] } utf8_to_wstring :: proc(s: string, allocator := context.temp_allocator) -> Wstring { if res := utf8_to_utf16(s, allocator); res != nil { - return Wstring(&res[0]); + return Wstring(&res[0]) } - return nil; + return nil } wstring_to_utf8 :: proc(s: Wstring, N: int, allocator := context.temp_allocator) -> string { if N == 0 { - return ""; + return "" } - n := wide_char_to_multi_byte(CP_UTF8, WC_ERR_INVALID_CHARS, s, i32(N), nil, 0, nil, nil); + n := wide_char_to_multi_byte(CP_UTF8, WC_ERR_INVALID_CHARS, s, i32(N), nil, 0, nil, nil) if n == 0 { - return ""; + return "" } // If N == -1 the call to wide_char_to_multi_byte assume the wide string is null terminated @@ -819,32 +819,32 @@ wstring_to_utf8 :: proc(s: Wstring, N: int, allocator := context.temp_allocator) // also null terminated. // If N != -1 it assumes the wide string is not null terminated and the resulting string // will not be null terminated, we therefore have to force it to be null terminated manually. - text := make([]byte, n+1 if N != -1 else n, allocator); + text := make([]byte, n+1 if N != -1 else n, allocator) if n1 := wide_char_to_multi_byte(CP_UTF8, WC_ERR_INVALID_CHARS, s, i32(N), cstring(&text[0]), n, nil, nil); n1 == 0 { - delete(text, allocator); - return ""; + delete(text, allocator) + return "" } for i in 0..<n { if text[i] == 0 { - n = i; - break; + n = i + break } } - return string(text[:n]); + return string(text[:n]) } utf16_to_utf8 :: proc(s: []u16, allocator := context.temp_allocator) -> string { - if len(s) == 0 do return ""; - return wstring_to_utf8(cast(Wstring)&s[0], len(s), allocator); + if len(s) == 0 do return "" + return wstring_to_utf8(cast(Wstring)&s[0], len(s), allocator) } get_query_performance_frequency :: proc() -> i64 { - r: i64; - query_performance_frequency(&r); - return r; + r: i64 + query_performance_frequency(&r) + return r } HIWORD_W :: proc(wParam: Wparam) -> u16 { return u16((u32(wParam) >> 16) & 0xffff); } @@ -857,56 +857,56 @@ is_key_down :: #force_inline proc(key: Key_Code) -> bool { return get_async_key_ -MAX_PATH :: 0x00000104; -MAX_PATH_WIDE :: 0x8000; +MAX_PATH :: 0x00000104 +MAX_PATH_WIDE :: 0x8000 -HANDLE_FLAG_INHERIT :: 1; -HANDLE_FLAG_PROTECT_FROM_CLOSE :: 2; +HANDLE_FLAG_INHERIT :: 1 +HANDLE_FLAG_PROTECT_FROM_CLOSE :: 2 -FILE_BEGIN :: 0; -FILE_CURRENT :: 1; -FILE_END :: 2; +FILE_BEGIN :: 0 +FILE_CURRENT :: 1 +FILE_END :: 2 -FILE_SHARE_READ :: 0x00000001; -FILE_SHARE_WRITE :: 0x00000002; -FILE_SHARE_DELETE :: 0x00000004; -FILE_GENERIC_ALL :: 0x10000000; -FILE_GENERIC_EXECUTE :: 0x20000000; -FILE_GENERIC_WRITE :: 0x40000000; -FILE_GENERIC_READ :: 0x80000000; +FILE_SHARE_READ :: 0x00000001 +FILE_SHARE_WRITE :: 0x00000002 +FILE_SHARE_DELETE :: 0x00000004 +FILE_GENERIC_ALL :: 0x10000000 +FILE_GENERIC_EXECUTE :: 0x20000000 +FILE_GENERIC_WRITE :: 0x40000000 +FILE_GENERIC_READ :: 0x80000000 -FILE_APPEND_DATA :: 0x0004; +FILE_APPEND_DATA :: 0x0004 -STD_INPUT_HANDLE :: -10; -STD_OUTPUT_HANDLE :: -11; -STD_ERROR_HANDLE :: -12; +STD_INPUT_HANDLE :: -10 +STD_OUTPUT_HANDLE :: -11 +STD_ERROR_HANDLE :: -12 -CREATE_NEW :: 1; -CREATE_ALWAYS :: 2; -OPEN_EXISTING :: 3; -OPEN_ALWAYS :: 4; -TRUNCATE_EXISTING :: 5; +CREATE_NEW :: 1 +CREATE_ALWAYS :: 2 +OPEN_EXISTING :: 3 +OPEN_ALWAYS :: 4 +TRUNCATE_EXISTING :: 5 -INVALID_FILE_ATTRIBUTES :: -1; +INVALID_FILE_ATTRIBUTES :: -1 -FILE_ATTRIBUTE_READONLY :: 0x00000001; -FILE_ATTRIBUTE_HIDDEN :: 0x00000002; -FILE_ATTRIBUTE_SYSTEM :: 0x00000004; -FILE_ATTRIBUTE_DIRECTORY :: 0x00000010; -FILE_ATTRIBUTE_ARCHIVE :: 0x00000020; -FILE_ATTRIBUTE_DEVICE :: 0x00000040; -FILE_ATTRIBUTE_NORMAL :: 0x00000080; -FILE_ATTRIBUTE_TEMPORARY :: 0x00000100; -FILE_ATTRIBUTE_SPARSE_FILE :: 0x00000200; -FILE_ATTRIBUTE_REPARSE_Point :: 0x00000400; -FILE_ATTRIBUTE_COMPRESSED :: 0x00000800; -FILE_ATTRIBUTE_OFFLINE :: 0x00001000; -FILE_ATTRIBUTE_NOT_CONTENT_INDEXED :: 0x00002000; -FILE_ATTRIBUTE_ENCRYPTED :: 0x00004000; +FILE_ATTRIBUTE_READONLY :: 0x00000001 +FILE_ATTRIBUTE_HIDDEN :: 0x00000002 +FILE_ATTRIBUTE_SYSTEM :: 0x00000004 +FILE_ATTRIBUTE_DIRECTORY :: 0x00000010 +FILE_ATTRIBUTE_ARCHIVE :: 0x00000020 +FILE_ATTRIBUTE_DEVICE :: 0x00000040 +FILE_ATTRIBUTE_NORMAL :: 0x00000080 +FILE_ATTRIBUTE_TEMPORARY :: 0x00000100 +FILE_ATTRIBUTE_SPARSE_FILE :: 0x00000200 +FILE_ATTRIBUTE_REPARSE_Point :: 0x00000400 +FILE_ATTRIBUTE_COMPRESSED :: 0x00000800 +FILE_ATTRIBUTE_OFFLINE :: 0x00001000 +FILE_ATTRIBUTE_NOT_CONTENT_INDEXED :: 0x00002000 +FILE_ATTRIBUTE_ENCRYPTED :: 0x00004000 -FILE_TYPE_DISK :: 0x0001; -FILE_TYPE_CHAR :: 0x0002; -FILE_TYPE_PIPE :: 0x0003; +FILE_TYPE_DISK :: 0x0001 +FILE_TYPE_CHAR :: 0x0002 +FILE_TYPE_PIPE :: 0x0003 Monitor_Info :: struct { diff --git a/core/sys/win32/helpers.odin b/core/sys/win32/helpers.odin index 7e551c077..b04e5db95 100644 --- a/core/sys/win32/helpers.odin +++ b/core/sys/win32/helpers.odin @@ -1,11 +1,11 @@ // +build windows package win32 -import "core:strings"; +import "core:strings" call_external_process :: proc(program, command_line: string) -> bool { - si := Startup_Info{ cb=size_of(Startup_Info) }; - pi := Process_Information{}; + si := Startup_Info{ cb=size_of(Startup_Info) } + pi := Process_Information{} return cast(bool)create_process_w( utf8_to_wstring(program), @@ -18,12 +18,12 @@ call_external_process :: proc(program, command_line: string) -> bool { nil, &si, &pi, - ); + ) } open_website :: proc(url: string) -> bool { - p :: "C:\\Windows\\System32\\cmd.exe"; - arg := []string{"/C", "start", url}; - args := strings.join(arg, " ", context.temp_allocator); - return call_external_process(p, args); + p :: "C:\\Windows\\System32\\cmd.exe" + arg := []string{"/C", "start", url} + args := strings.join(arg, " ", context.temp_allocator) + return call_external_process(p, args) } diff --git a/core/sys/win32/kernel32.odin b/core/sys/win32/kernel32.odin index ba3898730..187bcd06f 100644 --- a/core/sys/win32/kernel32.odin +++ b/core/sys/win32/kernel32.odin @@ -9,188 +9,188 @@ foreign kernel32 { process_attributes, thread_attributes: ^Security_Attributes, inherit_handle: Bool, creation_flags: u32, environment: rawptr, current_directory: cstring, startup_info: ^Startup_Info, - process_information: ^Process_Information) -> Bool ---; + process_information: ^Process_Information) -> Bool --- @(link_name="CreateProcessW") create_process_w :: proc(application_name, command_line: Wstring, process_attributes, thread_attributes: ^Security_Attributes, inherit_handle: Bool, creation_flags: u32, environment: rawptr, current_directory: Wstring, startup_info: ^Startup_Info, - process_information: ^Process_Information) -> Bool ---; - @(link_name="GetExitCodeProcess") get_exit_code_process :: proc(process: Handle, exit: ^u32) -> Bool ---; - @(link_name="ExitProcess") exit_process :: proc(exit_code: u32) ---; - @(link_name="GetModuleHandleA") get_module_handle_a :: proc(module_name: cstring) -> Hmodule ---; - @(link_name="GetModuleHandleW") get_module_handle_w :: proc(module_name: Wstring) -> Hmodule ---; - - @(link_name="GetModuleFileNameA") get_module_file_name_a :: proc(module: Hmodule, filename: cstring, size: u32) -> u32 ---; - @(link_name="GetModuleFileNameW") get_module_file_name_w :: proc(module: Hmodule, filename: Wstring, size: u32) -> u32 ---; - - @(link_name="Sleep") sleep :: proc(ms: u32) ---; - @(link_name="QueryPerformanceFrequency") query_performance_frequency :: proc(result: ^i64) -> i32 ---; - @(link_name="QueryPerformanceCounter") query_performance_counter :: proc(result: ^i64) -> i32 ---; - @(link_name="OutputDebugStringA") output_debug_string_a :: proc(c_str: cstring) ---; - - @(link_name="GetCommandLineA") get_command_line_a :: proc() -> cstring ---; - @(link_name="GetCommandLineW") get_command_line_w :: proc() -> Wstring ---; - @(link_name="GetSystemMetrics") get_system_metrics :: proc(index: i32) -> i32 ---; - @(link_name="GetSystemInfo") get_system_info :: proc(info: ^System_Info) ---; - @(link_name="GetVersionExA") get_version :: proc(osvi: ^OS_Version_Info_Ex_A) ---; - @(link_name="GetCurrentThreadId") get_current_thread_id :: proc() -> u32 ---; + process_information: ^Process_Information) -> Bool --- + @(link_name="GetExitCodeProcess") get_exit_code_process :: proc(process: Handle, exit: ^u32) -> Bool --- + @(link_name="ExitProcess") exit_process :: proc(exit_code: u32) --- + @(link_name="GetModuleHandleA") get_module_handle_a :: proc(module_name: cstring) -> Hmodule --- + @(link_name="GetModuleHandleW") get_module_handle_w :: proc(module_name: Wstring) -> Hmodule --- + + @(link_name="GetModuleFileNameA") get_module_file_name_a :: proc(module: Hmodule, filename: cstring, size: u32) -> u32 --- + @(link_name="GetModuleFileNameW") get_module_file_name_w :: proc(module: Hmodule, filename: Wstring, size: u32) -> u32 --- + + @(link_name="Sleep") sleep :: proc(ms: u32) --- + @(link_name="QueryPerformanceFrequency") query_performance_frequency :: proc(result: ^i64) -> i32 --- + @(link_name="QueryPerformanceCounter") query_performance_counter :: proc(result: ^i64) -> i32 --- + @(link_name="OutputDebugStringA") output_debug_string_a :: proc(c_str: cstring) --- + + @(link_name="GetCommandLineA") get_command_line_a :: proc() -> cstring --- + @(link_name="GetCommandLineW") get_command_line_w :: proc() -> Wstring --- + @(link_name="GetSystemMetrics") get_system_metrics :: proc(index: i32) -> i32 --- + @(link_name="GetSystemInfo") get_system_info :: proc(info: ^System_Info) --- + @(link_name="GetVersionExA") get_version :: proc(osvi: ^OS_Version_Info_Ex_A) --- + @(link_name="GetCurrentThreadId") get_current_thread_id :: proc() -> u32 --- // NOTE(tetra): Not thread safe with SetCurrentDirectory and GetFullPathName; // The current directory is stored as a global variable in the process. - @(link_name="GetCurrentDirectoryW") get_current_directory_w :: proc(len: u32, buf: Wstring) -> u32 ---; - @(link_name="SetCurrentDirectoryW") set_current_directory_w :: proc(buf: Wstring) -> u32 ---; + @(link_name="GetCurrentDirectoryW") get_current_directory_w :: proc(len: u32, buf: Wstring) -> u32 --- + @(link_name="SetCurrentDirectoryW") set_current_directory_w :: proc(buf: Wstring) -> u32 --- - @(link_name="GetSystemTimeAsFileTime") get_system_time_as_file_time :: proc(system_time_as_file_time: ^Filetime) ---; - @(link_name="FileTimeToLocalFileTime") file_time_to_local_file_time :: proc(file_time: ^Filetime, local_file_time: ^Filetime) -> Bool ---; - @(link_name="FileTimeToSystemTime") file_time_to_system_time :: proc(file_time: ^Filetime, system_time: ^Systemtime) -> Bool ---; - @(link_name="SystemTimeToFileTime") system_time_to_file_time :: proc(system_time: ^Systemtime, file_time: ^Filetime) -> Bool ---; + @(link_name="GetSystemTimeAsFileTime") get_system_time_as_file_time :: proc(system_time_as_file_time: ^Filetime) --- + @(link_name="FileTimeToLocalFileTime") file_time_to_local_file_time :: proc(file_time: ^Filetime, local_file_time: ^Filetime) -> Bool --- + @(link_name="FileTimeToSystemTime") file_time_to_system_time :: proc(file_time: ^Filetime, system_time: ^Systemtime) -> Bool --- + @(link_name="SystemTimeToFileTime") system_time_to_file_time :: proc(system_time: ^Systemtime, file_time: ^Filetime) -> Bool --- - @(link_name="GetStdHandle") get_std_handle :: proc(h: i32) -> Handle ---; + @(link_name="GetStdHandle") get_std_handle :: proc(h: i32) -> Handle --- @(link_name="CreateFileA") create_file_a :: proc(filename: cstring, desired_access, share_module: u32, security: rawptr, - creation, flags_and_attribs: u32, template_file: Handle) -> Handle ---; + creation, flags_and_attribs: u32, template_file: Handle) -> Handle --- @(link_name="CreateFileW") create_file_w :: proc(filename: Wstring, desired_access, share_module: u32, security: rawptr, - creation, flags_and_attribs: u32, template_file: Handle) -> Handle ---; + creation, flags_and_attribs: u32, template_file: Handle) -> Handle --- - @(link_name="ReadFile") read_file :: proc(h: Handle, buf: rawptr, to_read: u32, bytes_read: ^i32, overlapped: rawptr) -> Bool ---; - @(link_name="WriteFile") write_file :: proc(h: Handle, buf: rawptr, len: i32, written_result: ^i32, overlapped: rawptr) -> Bool ---; + @(link_name="ReadFile") read_file :: proc(h: Handle, buf: rawptr, to_read: u32, bytes_read: ^i32, overlapped: rawptr) -> Bool --- + @(link_name="WriteFile") write_file :: proc(h: Handle, buf: rawptr, len: i32, written_result: ^i32, overlapped: rawptr) -> Bool --- - @(link_name="GetFileSizeEx") get_file_size_ex :: proc(file_handle: Handle, file_size: ^i64) -> Bool ---; - @(link_name="GetFileInformationByHandle") get_file_information_by_handle :: proc(file_handle: Handle, file_info: ^By_Handle_File_Information) -> Bool ---; + @(link_name="GetFileSizeEx") get_file_size_ex :: proc(file_handle: Handle, file_size: ^i64) -> Bool --- + @(link_name="GetFileInformationByHandle") get_file_information_by_handle :: proc(file_handle: Handle, file_info: ^By_Handle_File_Information) -> Bool --- - @(link_name="CreateDirectoryA") create_directory_a :: proc(path: cstring, security_attributes: ^Security_Attributes) -> Bool ---; - @(link_name="CreateDirectoryW") create_directory_w :: proc(path: Wstring, security_attributes: ^Security_Attributes) -> Bool ---; + @(link_name="CreateDirectoryA") create_directory_a :: proc(path: cstring, security_attributes: ^Security_Attributes) -> Bool --- + @(link_name="CreateDirectoryW") create_directory_w :: proc(path: Wstring, security_attributes: ^Security_Attributes) -> Bool --- - @(link_name="GetFileType") get_file_type :: proc(file_handle: Handle) -> u32 ---; - @(link_name="SetFilePointer") set_file_pointer :: proc(file_handle: Handle, distance_to_move: i32, distance_to_move_high: ^i32, move_method: u32) -> u32 ---; + @(link_name="GetFileType") get_file_type :: proc(file_handle: Handle) -> u32 --- + @(link_name="SetFilePointer") set_file_pointer :: proc(file_handle: Handle, distance_to_move: i32, distance_to_move_high: ^i32, move_method: u32) -> u32 --- - @(link_name="SetHandleInformation") set_handle_information :: proc(obj: Handle, mask, flags: u32) -> Bool ---; + @(link_name="SetHandleInformation") set_handle_information :: proc(obj: Handle, mask, flags: u32) -> Bool --- - @(link_name="FindFirstFileA") find_first_file_a :: proc(file_name: cstring, data: ^Find_Data_A) -> Handle ---; - @(link_name="FindNextFileA") find_next_file_a :: proc(file: Handle, data: ^Find_Data_A) -> Bool ---; + @(link_name="FindFirstFileA") find_first_file_a :: proc(file_name: cstring, data: ^Find_Data_A) -> Handle --- + @(link_name="FindNextFileA") find_next_file_a :: proc(file: Handle, data: ^Find_Data_A) -> Bool --- - @(link_name="FindFirstFileW") find_first_file_w :: proc(file_name: Wstring, data: ^Find_Data_W) -> Handle ---; - @(link_name="FindNextFileW") find_next_file_w :: proc(file: Handle, data: ^Find_Data_W) -> Bool ---; + @(link_name="FindFirstFileW") find_first_file_w :: proc(file_name: Wstring, data: ^Find_Data_W) -> Handle --- + @(link_name="FindNextFileW") find_next_file_w :: proc(file: Handle, data: ^Find_Data_W) -> Bool --- - @(link_name="FindClose") find_close :: proc(file: Handle) -> Bool ---; + @(link_name="FindClose") find_close :: proc(file: Handle) -> Bool --- - @(link_name="MoveFileExA") move_file_ex_a :: proc(existing, new: cstring, flags: u32) -> Bool ---; - @(link_name="DeleteFileA") delete_file_a :: proc(file_name: cstring) -> Bool ---; - @(link_name="CopyFileA") copy_file_a :: proc(existing, new: cstring, fail_if_exists: Bool) -> Bool ---; + @(link_name="MoveFileExA") move_file_ex_a :: proc(existing, new: cstring, flags: u32) -> Bool --- + @(link_name="DeleteFileA") delete_file_a :: proc(file_name: cstring) -> Bool --- + @(link_name="CopyFileA") copy_file_a :: proc(existing, new: cstring, fail_if_exists: Bool) -> Bool --- - @(link_name="MoveFileExW") move_file_ex_w :: proc(existing, new: Wstring, flags: u32) -> Bool ---; - @(link_name="DeleteFileW") delete_file_w :: proc(file_name: Wstring) -> Bool ---; - @(link_name="CopyFileW") copy_file_w :: proc(existing, new: Wstring, fail_if_exists: Bool) -> Bool ---; + @(link_name="MoveFileExW") move_file_ex_w :: proc(existing, new: Wstring, flags: u32) -> Bool --- + @(link_name="DeleteFileW") delete_file_w :: proc(file_name: Wstring) -> Bool --- + @(link_name="CopyFileW") copy_file_w :: proc(existing, new: Wstring, fail_if_exists: Bool) -> Bool --- - @(link_name="HeapAlloc") heap_alloc :: proc(h: Handle, flags: u32, bytes: int) -> rawptr ---; - @(link_name="HeapReAlloc") heap_realloc :: proc(h: Handle, flags: u32, memory: rawptr, bytes: int) -> rawptr ---; - @(link_name="HeapFree") heap_free :: proc(h: Handle, flags: u32, memory: rawptr) -> Bool ---; - @(link_name="GetProcessHeap") get_process_heap :: proc() -> Handle ---; + @(link_name="HeapAlloc") heap_alloc :: proc(h: Handle, flags: u32, bytes: int) -> rawptr --- + @(link_name="HeapReAlloc") heap_realloc :: proc(h: Handle, flags: u32, memory: rawptr, bytes: int) -> rawptr --- + @(link_name="HeapFree") heap_free :: proc(h: Handle, flags: u32, memory: rawptr) -> Bool --- + @(link_name="GetProcessHeap") get_process_heap :: proc() -> Handle --- - @(link_name="LocalAlloc") local_alloc :: proc(flags: u32, bytes: int) -> rawptr ---; - @(link_name="LocalReAlloc") local_realloc :: proc(mem: rawptr, bytes: int, flags: uint) -> rawptr ---; - @(link_name="LocalFree") local_free :: proc(mem: rawptr) -> rawptr ---; + @(link_name="LocalAlloc") local_alloc :: proc(flags: u32, bytes: int) -> rawptr --- + @(link_name="LocalReAlloc") local_realloc :: proc(mem: rawptr, bytes: int, flags: uint) -> rawptr --- + @(link_name="LocalFree") local_free :: proc(mem: rawptr) -> rawptr --- - @(link_name="FindFirstChangeNotificationA") find_first_change_notification_a :: proc(path: cstring, watch_subtree: Bool, filter: u32) -> Handle ---; - @(link_name="FindNextChangeNotification") find_next_change_notification :: proc(h: Handle) -> Bool ---; - @(link_name="FindCloseChangeNotification") find_close_change_notification :: proc(h: Handle) -> Bool ---; + @(link_name="FindFirstChangeNotificationA") find_first_change_notification_a :: proc(path: cstring, watch_subtree: Bool, filter: u32) -> Handle --- + @(link_name="FindNextChangeNotification") find_next_change_notification :: proc(h: Handle) -> Bool --- + @(link_name="FindCloseChangeNotification") find_close_change_notification :: proc(h: Handle) -> Bool --- @(link_name="ReadDirectoryChangesW") read_directory_changes_w :: proc(dir: Handle, buf: rawptr, buf_length: u32, watch_subtree: Bool, notify_filter: u32, bytes_returned: ^u32, overlapped: ^Overlapped, - completion: rawptr) -> Bool ---; + completion: rawptr) -> Bool --- @(link_name="WideCharToMultiByte") wide_char_to_multi_byte :: proc(code_page: u32, flags: u32, wchar_str: Wstring, wchar: i32, multi_str: cstring, multi: i32, - default_char: cstring, used_default_char: ^Bool) -> i32 ---; + default_char: cstring, used_default_char: ^Bool) -> i32 --- @(link_name="MultiByteToWideChar") multi_byte_to_wide_char :: proc(code_page: u32, flags: u32, mb_str: cstring, mb: i32, - wc_str: Wstring, wc: i32) -> i32 ---; + wc_str: Wstring, wc: i32) -> i32 --- - @(link_name="CreateSemaphoreA") create_semaphore_a :: proc(attributes: ^Security_Attributes, initial_count, maximum_count: i32, name: cstring) -> Handle ---; - @(link_name="CreateSemaphoreW") create_semaphore_w :: proc(attributes: ^Security_Attributes, initial_count, maximum_count: i32, name: cstring) -> Handle ---; - @(link_name="ReleaseSemaphore") release_semaphore :: proc(semaphore: Handle, release_count: i32, previous_count: ^i32) -> Bool ---; - @(link_name="WaitForSingleObject") wait_for_single_object :: proc(handle: Handle, milliseconds: u32) -> u32 ---; + @(link_name="CreateSemaphoreA") create_semaphore_a :: proc(attributes: ^Security_Attributes, initial_count, maximum_count: i32, name: cstring) -> Handle --- + @(link_name="CreateSemaphoreW") create_semaphore_w :: proc(attributes: ^Security_Attributes, initial_count, maximum_count: i32, name: cstring) -> Handle --- + @(link_name="ReleaseSemaphore") release_semaphore :: proc(semaphore: Handle, release_count: i32, previous_count: ^i32) -> Bool --- + @(link_name="WaitForSingleObject") wait_for_single_object :: proc(handle: Handle, milliseconds: u32) -> u32 --- } // @(default_calling_convention = "c") foreign kernel32 { - @(link_name="GetLastError") get_last_error :: proc() -> i32 ---; - @(link_name="CloseHandle") close_handle :: proc(h: Handle) -> i32 ---; - - @(link_name="GetFileAttributesA") get_file_attributes_a :: proc(filename: cstring) -> u32 ---; - @(link_name="GetFileAttributesW") get_file_attributes_w :: proc(filename: Wstring) -> u32 ---; - @(link_name="GetFileAttributesExA") get_file_attributes_ex_a :: proc(filename: cstring, info_level_id: GET_FILEEX_INFO_LEVELS, file_info: ^File_Attribute_Data) -> Bool ---; - @(link_name="GetFileAttributesExW") get_file_attributes_ex_w :: proc(filename: Wstring, info_level_id: GET_FILEEX_INFO_LEVELS, file_info: ^File_Attribute_Data) -> Bool ---; - @(link_name="CompareFileTime") compare_file_time :: proc(a, b: ^Filetime) -> i32 ---; + @(link_name="GetLastError") get_last_error :: proc() -> i32 --- + @(link_name="CloseHandle") close_handle :: proc(h: Handle) -> i32 --- + + @(link_name="GetFileAttributesA") get_file_attributes_a :: proc(filename: cstring) -> u32 --- + @(link_name="GetFileAttributesW") get_file_attributes_w :: proc(filename: Wstring) -> u32 --- + @(link_name="GetFileAttributesExA") get_file_attributes_ex_a :: proc(filename: cstring, info_level_id: GET_FILEEX_INFO_LEVELS, file_info: ^File_Attribute_Data) -> Bool --- + @(link_name="GetFileAttributesExW") get_file_attributes_ex_w :: proc(filename: Wstring, info_level_id: GET_FILEEX_INFO_LEVELS, file_info: ^File_Attribute_Data) -> Bool --- + @(link_name="CompareFileTime") compare_file_time :: proc(a, b: ^Filetime) -> i32 --- } @(default_calling_convention = "c") foreign kernel32 { - @(link_name="InterlockedCompareExchange") interlocked_compare_exchange :: proc(dst: ^i32, exchange, comparand: i32) -> i32 ---; - @(link_name="InterlockedExchange") interlocked_exchange :: proc(dst: ^i32, desired: i32) -> i32 ---; - @(link_name="InterlockedExchangeAdd") interlocked_exchange_add :: proc(dst: ^i32, desired: i32) -> i32 ---; - @(link_name="InterlockedAnd") interlocked_and :: proc(dst: ^i32, desired: i32) -> i32 ---; - @(link_name="InterlockedOr") interlocked_or :: proc(dst: ^i32, desired: i32) -> i32 ---; - - @(link_name="InterlockedCompareExchange64") interlocked_compare_exchange64 :: proc(dst: ^i64, exchange, comparand: i64) -> i64 ---; - @(link_name="InterlockedExchange64") interlocked_exchange64 :: proc(dst: ^i64, desired: i64) -> i64 ---; - @(link_name="InterlockedExchangeAdd64") interlocked_exchange_add64 :: proc(dst: ^i64, desired: i64) -> i64 ---; - @(link_name="InterlockedAnd64") interlocked_and64 :: proc(dst: ^i64, desired: i64) -> i64 ---; - @(link_name="InterlockedOr64") interlocked_or64 :: proc(dst: ^i64, desired: i64) -> i64 ---; + @(link_name="InterlockedCompareExchange") interlocked_compare_exchange :: proc(dst: ^i32, exchange, comparand: i32) -> i32 --- + @(link_name="InterlockedExchange") interlocked_exchange :: proc(dst: ^i32, desired: i32) -> i32 --- + @(link_name="InterlockedExchangeAdd") interlocked_exchange_add :: proc(dst: ^i32, desired: i32) -> i32 --- + @(link_name="InterlockedAnd") interlocked_and :: proc(dst: ^i32, desired: i32) -> i32 --- + @(link_name="InterlockedOr") interlocked_or :: proc(dst: ^i32, desired: i32) -> i32 --- + + @(link_name="InterlockedCompareExchange64") interlocked_compare_exchange64 :: proc(dst: ^i64, exchange, comparand: i64) -> i64 --- + @(link_name="InterlockedExchange64") interlocked_exchange64 :: proc(dst: ^i64, desired: i64) -> i64 --- + @(link_name="InterlockedExchangeAdd64") interlocked_exchange_add64 :: proc(dst: ^i64, desired: i64) -> i64 --- + @(link_name="InterlockedAnd64") interlocked_and64 :: proc(dst: ^i64, desired: i64) -> i64 --- + @(link_name="InterlockedOr64") interlocked_or64 :: proc(dst: ^i64, desired: i64) -> i64 --- } @(default_calling_convention = "std") foreign kernel32 { - @(link_name="_mm_pause") mm_pause :: proc() ---; - @(link_name="ReadWriteBarrier") read_write_barrier :: proc() ---; - @(link_name="WriteBarrier") write_barrier :: proc() ---; - @(link_name="ReadBarrier") read_barrier :: proc() ---; + @(link_name="_mm_pause") mm_pause :: proc() --- + @(link_name="ReadWriteBarrier") read_write_barrier :: proc() --- + @(link_name="WriteBarrier") write_barrier :: proc() --- + @(link_name="ReadBarrier") read_barrier :: proc() --- @(link_name="CreateThread") create_thread :: proc(thread_attributes: ^Security_Attributes, stack_size: uint, start_routine: proc "stdcall" (rawptr) -> u32, - parameter: rawptr, creation_flags: u32, thread_id: ^u32) -> Handle ---; - @(link_name="ResumeThread") resume_thread :: proc(thread: Handle) -> u32 ---; - @(link_name="GetThreadPriority") get_thread_priority :: proc(thread: Handle) -> i32 ---; - @(link_name="SetThreadPriority") set_thread_priority :: proc(thread: Handle, priority: i32) -> Bool ---; - @(link_name="GetExitCodeThread") get_exit_code_thread :: proc(thread: Handle, exit_code: ^u32) -> Bool ---; - @(link_name="TerminateThread") terminate_thread :: proc(thread: Handle, exit_code: u32) -> Bool ---; - - @(link_name="InitializeCriticalSection") initialize_critical_section :: proc(critical_section: ^Critical_Section) ---; - @(link_name="InitializeCriticalSectionAndSpinCount") initialize_critical_section_and_spin_count :: proc(critical_section: ^Critical_Section, spin_count: u32) -> b32 ---; - @(link_name="DeleteCriticalSection") delete_critical_section :: proc(critical_section: ^Critical_Section) ---; - @(link_name="SetCriticalSectionSpinCount") set_critical_section_spin_count :: proc(critical_section: ^Critical_Section, spin_count: u32) -> u32 ---; - @(link_name="TryEnterCriticalSection") try_enter_critical_section :: proc(critical_section: ^Critical_Section) -> b8 ---; - @(link_name="EnterCriticalSection") enter_critical_section :: proc(critical_section: ^Critical_Section) ---; - @(link_name="LeaveCriticalSection") leave_critical_section :: proc(critical_section: ^Critical_Section) ---; - - @(link_name="CreateEventA") create_event_a :: proc(event_attributes: ^Security_Attributes, manual_reset, initial_state: Bool, name: cstring) -> Handle ---; - @(link_name="CreateEventW") create_event_w :: proc(event_attributes: ^Security_Attributes, manual_reset, initial_state: Bool, name: Wstring) -> Handle ---; - @(link_name="PulseEvent") pulse_event :: proc(event: Handle) -> Bool ---; - @(link_name="SetEvent") set_event :: proc(event: Handle) -> Bool ---; - @(link_name="ResetEvent") reset_event :: proc(event: Handle) -> Bool ---; - - @(link_name="LoadLibraryA") load_library_a :: proc(c_str: cstring) -> Hmodule ---; - @(link_name="LoadLibraryW") load_library_w :: proc(c_str: Wstring) -> Hmodule ---; - @(link_name="FreeLibrary") free_library :: proc(h: Hmodule) -> Bool ---; - @(link_name="GetProcAddress") get_proc_address :: proc(h: Hmodule, c_str: cstring) -> rawptr ---; - - @(link_name="GetFullPathNameA") get_full_path_name_a :: proc(filename: cstring, buffer_length: u32, buffer: cstring, file_part: ^Wstring) -> u32 ---; - @(link_name="GetFullPathNameW") get_full_path_name_w :: proc(filename: Wstring, buffer_length: u32, buffer: Wstring, file_part: ^Wstring) -> u32 ---; - @(link_name="GetLongPathNameA") get_long_path_name_a :: proc(short, long: cstring, len: u32) -> u32 ---; - @(link_name="GetLongPathNameW") get_long_path_name_w :: proc(short, long: Wstring, len: u32) -> u32 ---; - @(link_name="GetShortPathNameA") get_short_path_name_a :: proc(long, short: cstring, len: u32) -> u32 ---; - @(link_name="GetShortPathNameW") get_short_path_name_w :: proc(long, short: Wstring, len: u32) -> u32 ---; - - @(link_name="GetCurrentDirectoryA") get_current_directory_a :: proc(buffer_length: u32, buffer: cstring) -> u32 ---; + parameter: rawptr, creation_flags: u32, thread_id: ^u32) -> Handle --- + @(link_name="ResumeThread") resume_thread :: proc(thread: Handle) -> u32 --- + @(link_name="GetThreadPriority") get_thread_priority :: proc(thread: Handle) -> i32 --- + @(link_name="SetThreadPriority") set_thread_priority :: proc(thread: Handle, priority: i32) -> Bool --- + @(link_name="GetExitCodeThread") get_exit_code_thread :: proc(thread: Handle, exit_code: ^u32) -> Bool --- + @(link_name="TerminateThread") terminate_thread :: proc(thread: Handle, exit_code: u32) -> Bool --- + + @(link_name="InitializeCriticalSection") initialize_critical_section :: proc(critical_section: ^Critical_Section) --- + @(link_name="InitializeCriticalSectionAndSpinCount") initialize_critical_section_and_spin_count :: proc(critical_section: ^Critical_Section, spin_count: u32) -> b32 --- + @(link_name="DeleteCriticalSection") delete_critical_section :: proc(critical_section: ^Critical_Section) --- + @(link_name="SetCriticalSectionSpinCount") set_critical_section_spin_count :: proc(critical_section: ^Critical_Section, spin_count: u32) -> u32 --- + @(link_name="TryEnterCriticalSection") try_enter_critical_section :: proc(critical_section: ^Critical_Section) -> b8 --- + @(link_name="EnterCriticalSection") enter_critical_section :: proc(critical_section: ^Critical_Section) --- + @(link_name="LeaveCriticalSection") leave_critical_section :: proc(critical_section: ^Critical_Section) --- + + @(link_name="CreateEventA") create_event_a :: proc(event_attributes: ^Security_Attributes, manual_reset, initial_state: Bool, name: cstring) -> Handle --- + @(link_name="CreateEventW") create_event_w :: proc(event_attributes: ^Security_Attributes, manual_reset, initial_state: Bool, name: Wstring) -> Handle --- + @(link_name="PulseEvent") pulse_event :: proc(event: Handle) -> Bool --- + @(link_name="SetEvent") set_event :: proc(event: Handle) -> Bool --- + @(link_name="ResetEvent") reset_event :: proc(event: Handle) -> Bool --- + + @(link_name="LoadLibraryA") load_library_a :: proc(c_str: cstring) -> Hmodule --- + @(link_name="LoadLibraryW") load_library_w :: proc(c_str: Wstring) -> Hmodule --- + @(link_name="FreeLibrary") free_library :: proc(h: Hmodule) -> Bool --- + @(link_name="GetProcAddress") get_proc_address :: proc(h: Hmodule, c_str: cstring) -> rawptr --- + + @(link_name="GetFullPathNameA") get_full_path_name_a :: proc(filename: cstring, buffer_length: u32, buffer: cstring, file_part: ^Wstring) -> u32 --- + @(link_name="GetFullPathNameW") get_full_path_name_w :: proc(filename: Wstring, buffer_length: u32, buffer: Wstring, file_part: ^Wstring) -> u32 --- + @(link_name="GetLongPathNameA") get_long_path_name_a :: proc(short, long: cstring, len: u32) -> u32 --- + @(link_name="GetLongPathNameW") get_long_path_name_w :: proc(short, long: Wstring, len: u32) -> u32 --- + @(link_name="GetShortPathNameA") get_short_path_name_a :: proc(long, short: cstring, len: u32) -> u32 --- + @(link_name="GetShortPathNameW") get_short_path_name_w :: proc(long, short: Wstring, len: u32) -> u32 --- + + @(link_name="GetCurrentDirectoryA") get_current_directory_a :: proc(buffer_length: u32, buffer: cstring) -> u32 --- } Memory_Basic_Information :: struct { @@ -213,23 +213,23 @@ foreign kernel32 { @(link_name="VirtualQuery") virtual_query :: proc(address: rawptr, buffer: ^Memory_Basic_Information, length: uint) -> uint --- } -MEM_COMMIT :: 0x00001000; -MEM_RESERVE :: 0x00002000; -MEM_DECOMMIT :: 0x00004000; -MEM_RELEASE :: 0x00008000; -MEM_RESET :: 0x00080000; -MEM_RESET_UNDO :: 0x01000000; - -MEM_LARGE_PAGES :: 0x20000000; -MEM_PHYSICAL :: 0x00400000; -MEM_TOP_DOWN :: 0x00100000; -MEM_WRITE_WATCH :: 0x00200000; - -PAGE_NOACCESS :: 0x01; -PAGE_READONLY :: 0x02; -PAGE_READWRITE :: 0x04; -PAGE_WRITECOPY :: 0x08; -PAGE_EXECUTE :: 0x10; -PAGE_EXECUTE_READ :: 0x20; -PAGE_EXECUTE_READWRITE :: 0x40; -PAGE_EXECUTE_WRITECOPY :: 0x80; +MEM_COMMIT :: 0x00001000 +MEM_RESERVE :: 0x00002000 +MEM_DECOMMIT :: 0x00004000 +MEM_RELEASE :: 0x00008000 +MEM_RESET :: 0x00080000 +MEM_RESET_UNDO :: 0x01000000 + +MEM_LARGE_PAGES :: 0x20000000 +MEM_PHYSICAL :: 0x00400000 +MEM_TOP_DOWN :: 0x00100000 +MEM_WRITE_WATCH :: 0x00200000 + +PAGE_NOACCESS :: 0x01 +PAGE_READONLY :: 0x02 +PAGE_READWRITE :: 0x04 +PAGE_WRITECOPY :: 0x08 +PAGE_EXECUTE :: 0x10 +PAGE_EXECUTE_READ :: 0x20 +PAGE_EXECUTE_READWRITE :: 0x40 +PAGE_EXECUTE_WRITECOPY :: 0x80 diff --git a/core/sys/win32/ole32.odin b/core/sys/win32/ole32.odin index 4ce3dd93d..f4ee52399 100644 --- a/core/sys/win32/ole32.odin +++ b/core/sys/win32/ole32.odin @@ -9,10 +9,10 @@ Com_Init :: enum { Apartment_Threaded = 0x2, Disable_OLE1_DDE = 0x4, Speed_Over_Memory = 0x8, -}; +} @(default_calling_convention = "std") foreign ole32 { - @(link_name ="CoInitializeEx") com_init_ex :: proc(reserved: rawptr, co_init: Com_Init) ->Hresult ---; - @(link_name = "CoUninitialize") com_shutdown :: proc() ---; + @(link_name ="CoInitializeEx") com_init_ex :: proc(reserved: rawptr, co_init: Com_Init) ->Hresult --- + @(link_name = "CoUninitialize") com_shutdown :: proc() --- } diff --git a/core/sys/win32/shell32.odin b/core/sys/win32/shell32.odin index bb7b555cc..3cedf0527 100644 --- a/core/sys/win32/shell32.odin +++ b/core/sys/win32/shell32.odin @@ -5,5 +5,5 @@ foreign import "system:shell32.lib" @(default_calling_convention = "std") foreign shell32 { - @(link_name="CommandLineToArgvW") command_line_to_argv_w :: proc(cmd_list: Wstring, num_args: ^i32) -> ^Wstring ---; + @(link_name="CommandLineToArgvW") command_line_to_argv_w :: proc(cmd_list: Wstring, num_args: ^i32) -> ^Wstring --- } diff --git a/core/sys/win32/user32.odin b/core/sys/win32/user32.odin index ed05bbbaa..2fbf0a375 100644 --- a/core/sys/win32/user32.odin +++ b/core/sys/win32/user32.odin @@ -41,71 +41,71 @@ Menu_Item_Info_W :: struct { cch: u32, } -MF_BYCOMMAND :: 0x00000000; -MF_BYPOSITION :: 0x00000400; -MF_BITMAP :: 0x00000004; -MF_CHECKED :: 0x00000008; -MF_DISABLED :: 0x00000002; -MF_ENABLED :: 0x00000000; -MF_GRAYED :: 0x00000001; -MF_MENUBARBREAK :: 0x00000020; -MF_MENUBREAK :: 0x00000040; -MF_OWNERDRAW :: 0x00000100; -MF_POPUP :: 0x00000010; -MF_SEPARATOR :: 0x00000800; -MF_STRING :: 0x00000000; -MF_UNCHECKED :: 0x00000000; - -MB_ABORTRETRYIGNORE :: 0x00000002; -MB_CANCELTRYCONTINUE :: 0x00000006; -MB_HELP :: 0x00004000; -MB_OK :: 0x00000000; -MB_OKCANCEL :: 0x00000001; -MB_RETRYCANCEL :: 0x00000005; -MB_YESNO :: 0x00000004; -MB_YESNOCANCEL :: 0x00000003; - -MB_ICONEXCLAMATION :: 0x00000030; -MB_ICONWARNING :: 0x00000030; -MB_ICONINFORMATION :: 0x00000040; -MB_ICONASTERISK :: 0x00000040; -MB_ICONQUESTION :: 0x00000020; -MB_ICONSTOP :: 0x00000010; -MB_ICONERROR :: 0x00000010; -MB_ICONHAND :: 0x00000010; - -MB_DEFBUTTON1 :: 0x00000000; -MB_DEFBUTTON2 :: 0x00000100; -MB_DEFBUTTON3 :: 0x00000200; -MB_DEFBUTTON4 :: 0x00000300; - -MB_APPLMODAL :: 0x00000000; -MB_SYSTEMMODAL :: 0x00001000; -MB_TASKMODAL :: 0x00002000; - -MB_DEFAULT_DESKTOP_ONLY :: 0x00020000; -MB_RIGHT :: 0x00080000; -MB_RTLREADING :: 0x00100000; -MB_SETFOREGROUND :: 0x00010000; -MB_TOPMOST :: 0x00040000; -MB_SERVICE_NOTIFICATION :: 0x00200000; +MF_BYCOMMAND :: 0x00000000 +MF_BYPOSITION :: 0x00000400 +MF_BITMAP :: 0x00000004 +MF_CHECKED :: 0x00000008 +MF_DISABLED :: 0x00000002 +MF_ENABLED :: 0x00000000 +MF_GRAYED :: 0x00000001 +MF_MENUBARBREAK :: 0x00000020 +MF_MENUBREAK :: 0x00000040 +MF_OWNERDRAW :: 0x00000100 +MF_POPUP :: 0x00000010 +MF_SEPARATOR :: 0x00000800 +MF_STRING :: 0x00000000 +MF_UNCHECKED :: 0x00000000 + +MB_ABORTRETRYIGNORE :: 0x00000002 +MB_CANCELTRYCONTINUE :: 0x00000006 +MB_HELP :: 0x00004000 +MB_OK :: 0x00000000 +MB_OKCANCEL :: 0x00000001 +MB_RETRYCANCEL :: 0x00000005 +MB_YESNO :: 0x00000004 +MB_YESNOCANCEL :: 0x00000003 + +MB_ICONEXCLAMATION :: 0x00000030 +MB_ICONWARNING :: 0x00000030 +MB_ICONINFORMATION :: 0x00000040 +MB_ICONASTERISK :: 0x00000040 +MB_ICONQUESTION :: 0x00000020 +MB_ICONSTOP :: 0x00000010 +MB_ICONERROR :: 0x00000010 +MB_ICONHAND :: 0x00000010 + +MB_DEFBUTTON1 :: 0x00000000 +MB_DEFBUTTON2 :: 0x00000100 +MB_DEFBUTTON3 :: 0x00000200 +MB_DEFBUTTON4 :: 0x00000300 + +MB_APPLMODAL :: 0x00000000 +MB_SYSTEMMODAL :: 0x00001000 +MB_TASKMODAL :: 0x00002000 + +MB_DEFAULT_DESKTOP_ONLY :: 0x00020000 +MB_RIGHT :: 0x00080000 +MB_RTLREADING :: 0x00100000 +MB_SETFOREGROUND :: 0x00010000 +MB_TOPMOST :: 0x00040000 +MB_SERVICE_NOTIFICATION :: 0x00200000 @(default_calling_convention = "std") foreign user32 { - @(link_name="GetDesktopWindow") get_desktop_window :: proc() -> Hwnd ---; - @(link_name="ShowCursor") show_cursor :: proc(show: Bool) -> i32 ---; - @(link_name="GetCursorPos") get_cursor_pos :: proc(p: ^Point) -> Bool ---; - @(link_name="SetCursorPos") set_cursor_pos :: proc(x, y: i32) -> Bool ---; - @(link_name="ScreenToClient") screen_to_client :: proc(h: Hwnd, p: ^Point) -> Bool ---; - @(link_name="ClientToScreen") client_to_screen :: proc(h: Hwnd, p: ^Point) -> Bool ---; - @(link_name="PostQuitMessage") post_quit_message :: proc(exit_code: i32) ---; - @(link_name="SetWindowTextA") set_window_text_a :: proc(hwnd: Hwnd, c_string: cstring) -> Bool ---; - @(link_name="SetWindowTextW") set_window_text_w :: proc(hwnd: Hwnd, c_string: Wstring) -> Bool ---; - @(link_name="RegisterClassA") register_class_a :: proc(wc: ^Wnd_Class_A) -> i16 ---; - @(link_name="RegisterClassW") register_class_w :: proc(wc: ^Wnd_Class_W) -> i16 ---; - @(link_name="RegisterClassExA") register_class_ex_a :: proc(wc: ^Wnd_Class_Ex_A) -> i16 ---; - @(link_name="RegisterClassExW") register_class_ex_w :: proc(wc: ^Wnd_Class_Ex_W) -> i16 ---; + @(link_name="GetDesktopWindow") get_desktop_window :: proc() -> Hwnd --- + @(link_name="ShowCursor") show_cursor :: proc(show: Bool) -> i32 --- + @(link_name="GetCursorPos") get_cursor_pos :: proc(p: ^Point) -> Bool --- + @(link_name="SetCursorPos") set_cursor_pos :: proc(x, y: i32) -> Bool --- + @(link_name="ScreenToClient") screen_to_client :: proc(h: Hwnd, p: ^Point) -> Bool --- + @(link_name="ClientToScreen") client_to_screen :: proc(h: Hwnd, p: ^Point) -> Bool --- + @(link_name="PostQuitMessage") post_quit_message :: proc(exit_code: i32) --- + @(link_name="SetWindowTextA") set_window_text_a :: proc(hwnd: Hwnd, c_string: cstring) -> Bool --- + @(link_name="SetWindowTextW") set_window_text_w :: proc(hwnd: Hwnd, c_string: Wstring) -> Bool --- + @(link_name="RegisterClassA") register_class_a :: proc(wc: ^Wnd_Class_A) -> i16 --- + @(link_name="RegisterClassW") register_class_w :: proc(wc: ^Wnd_Class_W) -> i16 --- + @(link_name="RegisterClassExA") register_class_ex_a :: proc(wc: ^Wnd_Class_Ex_A) -> i16 --- + @(link_name="RegisterClassExW") register_class_ex_w :: proc(wc: ^Wnd_Class_Ex_W) -> i16 --- @(link_name="CreateWindowExA") create_window_ex_a :: proc(ex_style: u32, @@ -113,7 +113,7 @@ foreign user32 { style: u32, x, y, w, h: i32, parent: Hwnd, menu: Hmenu, instance: Hinstance, - param: rawptr) -> Hwnd ---; + param: rawptr) -> Hwnd --- @(link_name="CreateWindowExW") create_window_ex_w :: proc(ex_style: u32, @@ -121,82 +121,82 @@ foreign user32 { style: u32, x, y, w, h: i32, parent: Hwnd, menu: Hmenu, instance: Hinstance, - param: rawptr) -> Hwnd ---; + param: rawptr) -> Hwnd --- - @(link_name="ShowWindow") show_window :: proc(hwnd: Hwnd, cmd_show: i32) -> Bool ---; - @(link_name="TranslateMessage") translate_message :: proc(msg: ^Msg) -> Bool ---; - @(link_name="DispatchMessageA") dispatch_message_a :: proc(msg: ^Msg) -> Lresult ---; - @(link_name="DispatchMessageW") dispatch_message_w :: proc(msg: ^Msg) -> Lresult ---; - @(link_name="UpdateWindow") update_window :: proc(hwnd: Hwnd) -> Bool ---; - @(link_name="GetMessageA") get_message_a :: proc(msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max: u32) -> Bool ---; - @(link_name="GetMessageW") get_message_w :: proc(msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max: u32) -> Bool ---; + @(link_name="ShowWindow") show_window :: proc(hwnd: Hwnd, cmd_show: i32) -> Bool --- + @(link_name="TranslateMessage") translate_message :: proc(msg: ^Msg) -> Bool --- + @(link_name="DispatchMessageA") dispatch_message_a :: proc(msg: ^Msg) -> Lresult --- + @(link_name="DispatchMessageW") dispatch_message_w :: proc(msg: ^Msg) -> Lresult --- + @(link_name="UpdateWindow") update_window :: proc(hwnd: Hwnd) -> Bool --- + @(link_name="GetMessageA") get_message_a :: proc(msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max: u32) -> Bool --- + @(link_name="GetMessageW") get_message_w :: proc(msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max: u32) -> Bool --- - @(link_name="PeekMessageA") peek_message_a :: proc(msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max, remove_msg: u32) -> Bool ---; - @(link_name="PeekMessageW") peek_message_w :: proc(msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max, remove_msg: u32) -> Bool ---; + @(link_name="PeekMessageA") peek_message_a :: proc(msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max, remove_msg: u32) -> Bool --- + @(link_name="PeekMessageW") peek_message_w :: proc(msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max, remove_msg: u32) -> Bool --- - @(link_name="PostMessageA") post_message_a :: proc(hwnd: Hwnd, msg: u32, wparam: Wparam, lparam: Lparam) -> Bool ---; - @(link_name="PostMessageW") post_message_w :: proc(hwnd: Hwnd, msg: u32, wparam: Wparam, lparam: Lparam) -> Bool ---; - @(link_name="SendMessageA") send_message_a :: proc(hwnd: Hwnd, msg: u32, wparam: Wparam, lparam: Lparam) -> Lresult ---; - @(link_name="SendMessageW") send_message_w :: proc(hwnd: Hwnd, msg: u32, wparam: Wparam, lparam: Lparam) -> Lresult ---; + @(link_name="PostMessageA") post_message_a :: proc(hwnd: Hwnd, msg: u32, wparam: Wparam, lparam: Lparam) -> Bool --- + @(link_name="PostMessageW") post_message_w :: proc(hwnd: Hwnd, msg: u32, wparam: Wparam, lparam: Lparam) -> Bool --- + @(link_name="SendMessageA") send_message_a :: proc(hwnd: Hwnd, msg: u32, wparam: Wparam, lparam: Lparam) -> Lresult --- + @(link_name="SendMessageW") send_message_w :: proc(hwnd: Hwnd, msg: u32, wparam: Wparam, lparam: Lparam) -> Lresult --- - @(link_name="DefWindowProcA") def_window_proc_a :: proc(hwnd: Hwnd, msg: u32, wparam: Wparam, lparam: Lparam) -> Lresult ---; - @(link_name="DefWindowProcW") def_window_proc_w :: proc(hwnd: Hwnd, msg: u32, wparam: Wparam, lparam: Lparam) -> Lresult ---; + @(link_name="DefWindowProcA") def_window_proc_a :: proc(hwnd: Hwnd, msg: u32, wparam: Wparam, lparam: Lparam) -> Lresult --- + @(link_name="DefWindowProcW") def_window_proc_w :: proc(hwnd: Hwnd, msg: u32, wparam: Wparam, lparam: Lparam) -> Lresult --- - @(link_name="AdjustWindowRect") adjust_window_rect :: proc(rect: ^Rect, style: u32, menu: Bool) -> Bool ---; - @(link_name="GetActiveWindow") get_active_window :: proc() -> Hwnd ---; + @(link_name="AdjustWindowRect") adjust_window_rect :: proc(rect: ^Rect, style: u32, menu: Bool) -> Bool --- + @(link_name="GetActiveWindow") get_active_window :: proc() -> Hwnd --- - @(link_name="DestroyWindow") destroy_window :: proc(wnd: Hwnd) -> Bool ---; - @(link_name="DescribePixelFormat") describe_pixel_format :: proc(dc: Hdc, pixel_format: i32, bytes: u32, pfd: ^Pixel_Format_Descriptor) -> i32 ---; + @(link_name="DestroyWindow") destroy_window :: proc(wnd: Hwnd) -> Bool --- + @(link_name="DescribePixelFormat") describe_pixel_format :: proc(dc: Hdc, pixel_format: i32, bytes: u32, pfd: ^Pixel_Format_Descriptor) -> i32 --- - @(link_name="GetMonitorInfoA") get_monitor_info_a :: proc(monitor: Hmonitor, mi: ^Monitor_Info) -> Bool ---; - @(link_name="MonitorFromWindow") monitor_from_window :: proc(wnd: Hwnd, flags: u32) -> Hmonitor ---; + @(link_name="GetMonitorInfoA") get_monitor_info_a :: proc(monitor: Hmonitor, mi: ^Monitor_Info) -> Bool --- + @(link_name="MonitorFromWindow") monitor_from_window :: proc(wnd: Hwnd, flags: u32) -> Hmonitor --- - @(link_name="SetWindowPos") set_window_pos :: proc(wnd: Hwnd, wndInsertAfter: Hwnd, x, y, width, height: i32, flags: u32) -> Bool ---; + @(link_name="SetWindowPos") set_window_pos :: proc(wnd: Hwnd, wndInsertAfter: Hwnd, x, y, width, height: i32, flags: u32) -> Bool --- - @(link_name="GetWindowPlacement") get_window_placement :: proc(wnd: Hwnd, wndpl: ^Window_Placement) -> Bool ---; - @(link_name="SetWindowPlacement") set_window_placement :: proc(wnd: Hwnd, wndpl: ^Window_Placement) -> Bool ---; - @(link_name="GetWindowRect") get_window_rect :: proc(wnd: Hwnd, rect: ^Rect) -> Bool ---; + @(link_name="GetWindowPlacement") get_window_placement :: proc(wnd: Hwnd, wndpl: ^Window_Placement) -> Bool --- + @(link_name="SetWindowPlacement") set_window_placement :: proc(wnd: Hwnd, wndpl: ^Window_Placement) -> Bool --- + @(link_name="GetWindowRect") get_window_rect :: proc(wnd: Hwnd, rect: ^Rect) -> Bool --- - @(link_name="GetWindowLongPtrA") get_window_long_ptr_a :: proc(wnd: Hwnd, index: i32) -> Long_Ptr ---; - @(link_name="SetWindowLongPtrA") set_window_long_ptr_a :: proc(wnd: Hwnd, index: i32, new: Long_Ptr) -> Long_Ptr ---; - @(link_name="GetWindowLongPtrW") get_window_long_ptr_w :: proc(wnd: Hwnd, index: i32) -> Long_Ptr ---; - @(link_name="SetWindowLongPtrW") set_window_long_ptr_w :: proc(wnd: Hwnd, index: i32, new: Long_Ptr) -> Long_Ptr ---; + @(link_name="GetWindowLongPtrA") get_window_long_ptr_a :: proc(wnd: Hwnd, index: i32) -> Long_Ptr --- + @(link_name="SetWindowLongPtrA") set_window_long_ptr_a :: proc(wnd: Hwnd, index: i32, new: Long_Ptr) -> Long_Ptr --- + @(link_name="GetWindowLongPtrW") get_window_long_ptr_w :: proc(wnd: Hwnd, index: i32) -> Long_Ptr --- + @(link_name="SetWindowLongPtrW") set_window_long_ptr_w :: proc(wnd: Hwnd, index: i32, new: Long_Ptr) -> Long_Ptr --- - @(link_name="GetWindowText") get_window_text :: proc(wnd: Hwnd, str: cstring, maxCount: i32) -> i32 ---; + @(link_name="GetWindowText") get_window_text :: proc(wnd: Hwnd, str: cstring, maxCount: i32) -> i32 --- - @(link_name="GetClientRect") get_client_rect :: proc(hwnd: Hwnd, rect: ^Rect) -> Bool ---; + @(link_name="GetClientRect") get_client_rect :: proc(hwnd: Hwnd, rect: ^Rect) -> Bool --- - @(link_name="GetDC") get_dc :: proc(h: Hwnd) -> Hdc ---; - @(link_name="ReleaseDC") release_dc :: proc(wnd: Hwnd, hdc: Hdc) -> i32 ---; + @(link_name="GetDC") get_dc :: proc(h: Hwnd) -> Hdc --- + @(link_name="ReleaseDC") release_dc :: proc(wnd: Hwnd, hdc: Hdc) -> i32 --- - @(link_name="MapVirtualKeyA") map_virtual_key_a :: proc(scancode: u32, map_type: u32) -> u32 ---; - @(link_name="MapVirtualKeyW") map_virtual_key_w :: proc(scancode: u32, map_type: u32) -> u32 ---; + @(link_name="MapVirtualKeyA") map_virtual_key_a :: proc(scancode: u32, map_type: u32) -> u32 --- + @(link_name="MapVirtualKeyW") map_virtual_key_w :: proc(scancode: u32, map_type: u32) -> u32 --- - @(link_name="GetKeyState") get_key_state :: proc(v_key: i32) -> i16 ---; - @(link_name="GetAsyncKeyState") get_async_key_state :: proc(v_key: i32) -> i16 ---; + @(link_name="GetKeyState") get_key_state :: proc(v_key: i32) -> i16 --- + @(link_name="GetAsyncKeyState") get_async_key_state :: proc(v_key: i32) -> i16 --- - @(link_name="SetForegroundWindow") set_foreground_window :: proc(h: Hwnd) -> Bool ---; - @(link_name="SetFocus") set_focus :: proc(h: Hwnd) -> Hwnd ---; + @(link_name="SetForegroundWindow") set_foreground_window :: proc(h: Hwnd) -> Bool --- + @(link_name="SetFocus") set_focus :: proc(h: Hwnd) -> Hwnd --- - @(link_name="LoadImageA") load_image_a :: proc(instance: Hinstance, name: cstring, type_: u32, x_desired, y_desired : i32, load : u32) -> Handle ---; - @(link_name="LoadIconA") load_icon_a :: proc(instance: Hinstance, icon_name: cstring) -> Hicon ---; - @(link_name="DestroyIcon") destroy_icon :: proc(icon: Hicon) -> Bool ---; + @(link_name="LoadImageA") load_image_a :: proc(instance: Hinstance, name: cstring, type_: u32, x_desired, y_desired : i32, load : u32) -> Handle --- + @(link_name="LoadIconA") load_icon_a :: proc(instance: Hinstance, icon_name: cstring) -> Hicon --- + @(link_name="DestroyIcon") destroy_icon :: proc(icon: Hicon) -> Bool --- - @(link_name="LoadCursorA") load_cursor_a :: proc(instance: Hinstance, cursor_name: cstring) -> Hcursor ---; - @(link_name="LoadCursorW") load_cursor_w :: proc(instance: Hinstance, cursor_name: Wstring) -> Hcursor ---; - @(link_name="GetCursor") get_cursor :: proc() -> Hcursor ---; - @(link_name="SetCursor") set_cursor :: proc(cursor: Hcursor) -> Hcursor ---; + @(link_name="LoadCursorA") load_cursor_a :: proc(instance: Hinstance, cursor_name: cstring) -> Hcursor --- + @(link_name="LoadCursorW") load_cursor_w :: proc(instance: Hinstance, cursor_name: Wstring) -> Hcursor --- + @(link_name="GetCursor") get_cursor :: proc() -> Hcursor --- + @(link_name="SetCursor") set_cursor :: proc(cursor: Hcursor) -> Hcursor --- - @(link_name="RegisterRawInputDevices") register_raw_input_devices :: proc(raw_input_device: ^Raw_Input_Device, num_devices, size: u32) -> Bool ---; + @(link_name="RegisterRawInputDevices") register_raw_input_devices :: proc(raw_input_device: ^Raw_Input_Device, num_devices, size: u32) -> Bool --- - @(link_name="GetRawInputData") get_raw_input_data :: proc(raw_input: Hrawinput, command: u32, data: rawptr, size: ^u32, size_header: u32) -> u32 ---; + @(link_name="GetRawInputData") get_raw_input_data :: proc(raw_input: Hrawinput, command: u32, data: rawptr, size: ^u32, size_header: u32) -> u32 --- - @(link_name="MapVirtualKeyExW") map_virtual_key_ex_w :: proc(code, map_type: u32, hkl: HKL) -> u32 ---; - @(link_name="MapVirtualKeyExA") map_virtual_key_ex_a :: proc(code, map_type: u32, hkl: HKL) -> u32 ---; + @(link_name="MapVirtualKeyExW") map_virtual_key_ex_w :: proc(code, map_type: u32, hkl: HKL) -> u32 --- + @(link_name="MapVirtualKeyExA") map_virtual_key_ex_a :: proc(code, map_type: u32, hkl: HKL) -> u32 --- - @(link_name="EnumDisplayMonitors") enum_display_monitors :: proc(hdc: Hdc, rect: ^Rect, enum_proc: Monitor_Enum_Proc, lparam: Lparam) -> bool ---; + @(link_name="EnumDisplayMonitors") enum_display_monitors :: proc(hdc: Hdc, rect: ^Rect, enum_proc: Monitor_Enum_Proc, lparam: Lparam) -> bool --- } @(default_calling_convention = "std") @@ -244,35 +244,35 @@ foreign user32 { } -_IDC_APPSTARTING := rawptr(uintptr(32650)); -_IDC_ARROW := rawptr(uintptr(32512)); -_IDC_CROSS := rawptr(uintptr(32515)); -_IDC_HAND := rawptr(uintptr(32649)); -_IDC_HELP := rawptr(uintptr(32651)); -_IDC_IBEAM := rawptr(uintptr(32513)); -_IDC_ICON := rawptr(uintptr(32641)); -_IDC_NO := rawptr(uintptr(32648)); -_IDC_SIZE := rawptr(uintptr(32640)); -_IDC_SIZEALL := rawptr(uintptr(32646)); -_IDC_SIZENESW := rawptr(uintptr(32643)); -_IDC_SIZENS := rawptr(uintptr(32645)); -_IDC_SIZENWSE := rawptr(uintptr(32642)); -_IDC_SIZEWE := rawptr(uintptr(32644)); -_IDC_UPARROW := rawptr(uintptr(32516)); -_IDC_WAIT := rawptr(uintptr(32514)); -IDC_APPSTARTING := cstring(_IDC_APPSTARTING); -IDC_ARROW := cstring(_IDC_ARROW); -IDC_CROSS := cstring(_IDC_CROSS); -IDC_HAND := cstring(_IDC_HAND); -IDC_HELP := cstring(_IDC_HELP); -IDC_IBEAM := cstring(_IDC_IBEAM); -IDC_ICON := cstring(_IDC_ICON); -IDC_NO := cstring(_IDC_NO); -IDC_SIZE := cstring(_IDC_SIZE); -IDC_SIZEALL := cstring(_IDC_SIZEALL); -IDC_SIZENESW := cstring(_IDC_SIZENESW); -IDC_SIZENS := cstring(_IDC_SIZENS); -IDC_SIZENWSE := cstring(_IDC_SIZENWSE); -IDC_SIZEWE := cstring(_IDC_SIZEWE); -IDC_UPARROW := cstring(_IDC_UPARROW); -IDC_WAIT := cstring(_IDC_WAIT); +_IDC_APPSTARTING := rawptr(uintptr(32650)) +_IDC_ARROW := rawptr(uintptr(32512)) +_IDC_CROSS := rawptr(uintptr(32515)) +_IDC_HAND := rawptr(uintptr(32649)) +_IDC_HELP := rawptr(uintptr(32651)) +_IDC_IBEAM := rawptr(uintptr(32513)) +_IDC_ICON := rawptr(uintptr(32641)) +_IDC_NO := rawptr(uintptr(32648)) +_IDC_SIZE := rawptr(uintptr(32640)) +_IDC_SIZEALL := rawptr(uintptr(32646)) +_IDC_SIZENESW := rawptr(uintptr(32643)) +_IDC_SIZENS := rawptr(uintptr(32645)) +_IDC_SIZENWSE := rawptr(uintptr(32642)) +_IDC_SIZEWE := rawptr(uintptr(32644)) +_IDC_UPARROW := rawptr(uintptr(32516)) +_IDC_WAIT := rawptr(uintptr(32514)) +IDC_APPSTARTING := cstring(_IDC_APPSTARTING) +IDC_ARROW := cstring(_IDC_ARROW) +IDC_CROSS := cstring(_IDC_CROSS) +IDC_HAND := cstring(_IDC_HAND) +IDC_HELP := cstring(_IDC_HELP) +IDC_IBEAM := cstring(_IDC_IBEAM) +IDC_ICON := cstring(_IDC_ICON) +IDC_NO := cstring(_IDC_NO) +IDC_SIZE := cstring(_IDC_SIZE) +IDC_SIZEALL := cstring(_IDC_SIZEALL) +IDC_SIZENESW := cstring(_IDC_SIZENESW) +IDC_SIZENS := cstring(_IDC_SIZENS) +IDC_SIZENWSE := cstring(_IDC_SIZENWSE) +IDC_SIZEWE := cstring(_IDC_SIZEWE) +IDC_UPARROW := cstring(_IDC_UPARROW) +IDC_WAIT := cstring(_IDC_WAIT) diff --git a/core/sys/win32/wgl.odin b/core/sys/win32/wgl.odin index 0d54f4cb8..e6c414b0e 100644 --- a/core/sys/win32/wgl.odin +++ b/core/sys/win32/wgl.odin @@ -3,16 +3,16 @@ package win32 foreign import "system:opengl32.lib" -CONTEXT_MAJOR_VERSION_ARB :: 0x2091; -CONTEXT_MINOR_VERSION_ARB :: 0x2092; -CONTEXT_FLAGS_ARB :: 0x2094; -CONTEXT_PROFILE_MASK_ARB :: 0x9126; -CONTEXT_FORWARD_COMPATIBLE_BIT_ARB :: 0x0002; -CONTEXT_CORE_PROFILE_BIT_ARB :: 0x00000001; -CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB :: 0x00000002; +CONTEXT_MAJOR_VERSION_ARB :: 0x2091 +CONTEXT_MINOR_VERSION_ARB :: 0x2092 +CONTEXT_FLAGS_ARB :: 0x2094 +CONTEXT_PROFILE_MASK_ARB :: 0x9126 +CONTEXT_FORWARD_COMPATIBLE_BIT_ARB :: 0x0002 +CONTEXT_CORE_PROFILE_BIT_ARB :: 0x00000001 +CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB :: 0x00000002 -Hglrc :: distinct Handle; -Color_Ref :: distinct u32; +Hglrc :: distinct Handle +Color_Ref :: distinct u32 Layer_Plane_Descriptor :: struct { size: u16, @@ -41,7 +41,7 @@ Layer_Plane_Descriptor :: struct { transparent: Color_Ref, } -Point_Float :: struct {x, y: f32}; +Point_Float :: struct {x, y: f32} Glyph_Metrics_Float :: struct { black_box_x: f32, @@ -51,64 +51,64 @@ Glyph_Metrics_Float :: struct { cell_inc_y: f32, } -Create_Context_Attribs_ARB_Type :: #type proc "c" (hdc: Hdc, h_share_context: rawptr, attribList: ^i32) -> Hglrc; -Choose_Pixel_Format_ARB_Type :: #type proc "c" (hdc: Hdc, attrib_i_list: ^i32, attrib_f_list: ^f32, max_formats: u32, formats: ^i32, num_formats : ^u32) -> Bool; -Swap_Interval_EXT_Type :: #type proc "c" (interval: i32) -> bool; -Get_Extensions_String_ARB_Type :: #type proc "c" (Hdc) -> cstring; +Create_Context_Attribs_ARB_Type :: #type proc "c" (hdc: Hdc, h_share_context: rawptr, attribList: ^i32) -> Hglrc +Choose_Pixel_Format_ARB_Type :: #type proc "c" (hdc: Hdc, attrib_i_list: ^i32, attrib_f_list: ^f32, max_formats: u32, formats: ^i32, num_formats : ^u32) -> Bool +Swap_Interval_EXT_Type :: #type proc "c" (interval: i32) -> bool +Get_Extensions_String_ARB_Type :: #type proc "c" (Hdc) -> cstring // Procedures - create_context_attribs_arb: Create_Context_Attribs_ARB_Type; - choose_pixel_format_arb: Choose_Pixel_Format_ARB_Type; - swap_interval_ext: Swap_Interval_EXT_Type; - get_extensions_string_arb: Get_Extensions_String_ARB_Type; + create_context_attribs_arb: Create_Context_Attribs_ARB_Type + choose_pixel_format_arb: Choose_Pixel_Format_ARB_Type + swap_interval_ext: Swap_Interval_EXT_Type + get_extensions_string_arb: Get_Extensions_String_ARB_Type foreign opengl32 { @(link_name="wglCreateContext") - create_context :: proc(hdc: Hdc) -> Hglrc ---; + create_context :: proc(hdc: Hdc) -> Hglrc --- @(link_name="wglMakeCurrent") - make_current :: proc(hdc: Hdc, hglrc: Hglrc) -> Bool ---; + make_current :: proc(hdc: Hdc, hglrc: Hglrc) -> Bool --- @(link_name="wglGetProcAddress") - get_gl_proc_address :: proc(c_str: cstring) -> rawptr ---; + get_gl_proc_address :: proc(c_str: cstring) -> rawptr --- @(link_name="wglDeleteContext") - delete_context :: proc(hglrc: Hglrc) -> Bool ---; + delete_context :: proc(hglrc: Hglrc) -> Bool --- @(link_name="wglCopyContext") - copy_context :: proc(src, dst: Hglrc, mask: u32) -> Bool ---; + copy_context :: proc(src, dst: Hglrc, mask: u32) -> Bool --- @(link_name="wglCreateLayerContext") - create_layer_context :: proc(hdc: Hdc, layer_plane: i32) -> Hglrc ---; + create_layer_context :: proc(hdc: Hdc, layer_plane: i32) -> Hglrc --- @(link_name="wglDescribeLayerPlane") - describe_layer_plane :: proc(hdc: Hdc, pixel_format, layer_plane: i32, bytes: u32, pd: ^Layer_Plane_Descriptor) -> Bool ---; + describe_layer_plane :: proc(hdc: Hdc, pixel_format, layer_plane: i32, bytes: u32, pd: ^Layer_Plane_Descriptor) -> Bool --- @(link_name="wglGetCurrentContext") - get_current_context :: proc() -> Hglrc ---; + get_current_context :: proc() -> Hglrc --- @(link_name="wglGetCurrentDC") - get_current_dc :: proc() -> Hdc ---; + get_current_dc :: proc() -> Hdc --- @(link_name="wglGetLayerPaletteEntries") - get_layer_palette_entries :: proc(hdc: Hdc, layer_plane, start, entries: i32, cr: ^Color_Ref) -> i32 ---; + get_layer_palette_entries :: proc(hdc: Hdc, layer_plane, start, entries: i32, cr: ^Color_Ref) -> i32 --- @(link_name="wglRealizeLayerPalette") - realize_layer_palette :: proc(hdc: Hdc, layer_plane: i32, realize: Bool) -> Bool ---; + realize_layer_palette :: proc(hdc: Hdc, layer_plane: i32, realize: Bool) -> Bool --- @(link_name="wglSetLayerPaletteEntries") - set_layer_palette_entries :: proc(hdc: Hdc, layer_plane, start, entries: i32, cr: ^Color_Ref) -> i32 ---; + set_layer_palette_entries :: proc(hdc: Hdc, layer_plane, start, entries: i32, cr: ^Color_Ref) -> i32 --- @(link_name="wglShareLists") - share_lists :: proc(hglrc1, hglrc2: Hglrc) -> Bool ---; + share_lists :: proc(hglrc1, hglrc2: Hglrc) -> Bool --- @(link_name="wglSwapLayerBuffers") - swap_layer_buffers :: proc(hdc: Hdc, planes: u32) -> Bool ---; + swap_layer_buffers :: proc(hdc: Hdc, planes: u32) -> Bool --- @(link_name="wglUseFontBitmaps") - use_font_bitmaps :: proc(hdc: Hdc, first, count, list_base: u32) -> Bool ---; + use_font_bitmaps :: proc(hdc: Hdc, first, count, list_base: u32) -> Bool --- @(link_name="wglUseFontOutlines") - use_font_outlines :: proc(hdc: Hdc, first, count, list_base: u32, deviation, extrusion: f32, format: i32, gmf: ^Glyph_Metrics_Float) -> Bool ---; + use_font_outlines :: proc(hdc: Hdc, first, count, list_base: u32, deviation, extrusion: f32, format: i32, gmf: ^Glyph_Metrics_Float) -> Bool --- } diff --git a/core/sys/win32/winmm.odin b/core/sys/win32/winmm.odin index af017aab4..05d099a1a 100644 --- a/core/sys/win32/winmm.odin +++ b/core/sys/win32/winmm.odin @@ -6,5 +6,5 @@ foreign import "system:winmm.lib" @(default_calling_convention = "std") foreign winmm { - @(link_name="timeGetTime") time_get_time :: proc() -> u32 ---; + @(link_name="timeGetTime") time_get_time :: proc() -> u32 --- } diff --git a/core/sys/windows/advapi32.odin b/core/sys/windows/advapi32.odin index 7e14aa3f8..a2a24242f 100644 --- a/core/sys/windows/advapi32.odin +++ b/core/sys/windows/advapi32.odin @@ -63,5 +63,5 @@ foreign advapi32 { lpCurrentDirectory: wstring, lpStartupInfo: LPSTARTUPINFO, lpProcessInformation: LPPROCESS_INFORMATION, - ) -> BOOL ---; + ) -> BOOL --- }
\ No newline at end of file diff --git a/core/sys/windows/bcrypt.odin b/core/sys/windows/bcrypt.odin index bfb75d259..ed28d5b7f 100644 --- a/core/sys/windows/bcrypt.odin +++ b/core/sys/windows/bcrypt.odin @@ -3,7 +3,7 @@ package sys_windows foreign import bcrypt "system:Bcrypt.lib" -BCRYPT_USE_SYSTEM_PREFERRED_RNG: DWORD : 0x00000002; +BCRYPT_USE_SYSTEM_PREFERRED_RNG: DWORD : 0x00000002 @(default_calling_convention="stdcall") foreign bcrypt { diff --git a/core/sys/windows/kernel32.odin b/core/sys/windows/kernel32.odin index 8b7df931b..94ba191e0 100644 --- a/core/sys/windows/kernel32.odin +++ b/core/sys/windows/kernel32.odin @@ -83,14 +83,14 @@ foreign kernel32 { lpThreadId: LPDWORD, ) -> HANDLE --- SwitchToThread :: proc() -> BOOL --- - ResumeThread :: proc(thread: HANDLE) -> DWORD ---; - GetThreadPriority :: proc(thread: HANDLE) -> c_int ---; - SetThreadPriority :: proc(thread: HANDLE, priority: c_int) -> BOOL ---; - GetExitCodeThread :: proc(thread: HANDLE, exit_code: ^DWORD) -> BOOL ---; - TerminateThread :: proc(thread: HANDLE, exit_code: DWORD) -> BOOL ---; + ResumeThread :: proc(thread: HANDLE) -> DWORD --- + GetThreadPriority :: proc(thread: HANDLE) -> c_int --- + SetThreadPriority :: proc(thread: HANDLE, priority: c_int) -> BOOL --- + GetExitCodeThread :: proc(thread: HANDLE, exit_code: ^DWORD) -> BOOL --- + TerminateThread :: proc(thread: HANDLE, exit_code: DWORD) -> BOOL --- - CreateSemaphoreW :: proc(attributes: LPSECURITY_ATTRIBUTES, initial_count, maximum_count: LONG, name: LPCSTR) -> HANDLE ---; - ReleaseSemaphore :: proc(semaphore: HANDLE, release_count: LONG, previous_count: ^LONG) -> BOOL ---; + CreateSemaphoreW :: proc(attributes: LPSECURITY_ATTRIBUTES, initial_count, maximum_count: LONG, name: LPCSTR) -> HANDLE --- + ReleaseSemaphore :: proc(semaphore: HANDLE, release_count: LONG, previous_count: ^LONG) -> BOOL --- WaitForSingleObject :: proc(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD --- Sleep :: proc(dwMilliseconds: DWORD) --- @@ -285,35 +285,35 @@ foreign kernel32 { } -STANDARD_RIGHTS_REQUIRED :: DWORD(0x000F0000); -SECTION_QUERY :: DWORD(0x0001); -SECTION_MAP_WRITE :: DWORD(0x0002); -SECTION_MAP_READ :: DWORD(0x0004); -SECTION_MAP_EXECUTE :: DWORD(0x0008); -SECTION_EXTEND_SIZE :: DWORD(0x0010); -SECTION_ALL_ACCESS :: STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_WRITE | SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_EXTEND_SIZE; -SECTION_MAP_EXECUTE_EXPLICIT :: DWORD(0x0020); - -FILE_MAP_WRITE :: SECTION_MAP_WRITE; -FILE_MAP_READ :: SECTION_MAP_READ; -FILE_MAP_ALL_ACCESS :: SECTION_ALL_ACCESS; -FILE_MAP_EXECUTE :: SECTION_MAP_EXECUTE_EXPLICIT; -FILE_MAP_COPY :: DWORD(0x00000001); -FILE_MAP_RESERVE :: DWORD(0x80000000); -FILE_MAP_TARGETS_INVALID :: DWORD(0x40000000); -FILE_MAP_LARGE_PAGES :: DWORD(0x20000000); - -PAGE_NOACCESS :: 0x01; -PAGE_READONLY :: 0x02; -PAGE_READWRITE :: 0x04; -PAGE_WRITECOPY :: 0x08; -PAGE_EXECUTE :: 0x10; -PAGE_EXECUTE_READ :: 0x20; -PAGE_EXECUTE_READWRITE :: 0x40; -PAGE_EXECUTE_WRITECOPY :: 0x80; -PAGE_GUARD :: 0x100; -PAGE_NOCACHE :: 0x200; -PAGE_WRITECOMBINE :: 0x400; +STANDARD_RIGHTS_REQUIRED :: DWORD(0x000F0000) +SECTION_QUERY :: DWORD(0x0001) +SECTION_MAP_WRITE :: DWORD(0x0002) +SECTION_MAP_READ :: DWORD(0x0004) +SECTION_MAP_EXECUTE :: DWORD(0x0008) +SECTION_EXTEND_SIZE :: DWORD(0x0010) +SECTION_ALL_ACCESS :: STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_WRITE | SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_EXTEND_SIZE +SECTION_MAP_EXECUTE_EXPLICIT :: DWORD(0x0020) + +FILE_MAP_WRITE :: SECTION_MAP_WRITE +FILE_MAP_READ :: SECTION_MAP_READ +FILE_MAP_ALL_ACCESS :: SECTION_ALL_ACCESS +FILE_MAP_EXECUTE :: SECTION_MAP_EXECUTE_EXPLICIT +FILE_MAP_COPY :: DWORD(0x00000001) +FILE_MAP_RESERVE :: DWORD(0x80000000) +FILE_MAP_TARGETS_INVALID :: DWORD(0x40000000) +FILE_MAP_LARGE_PAGES :: DWORD(0x20000000) + +PAGE_NOACCESS :: 0x01 +PAGE_READONLY :: 0x02 +PAGE_READWRITE :: 0x04 +PAGE_WRITECOPY :: 0x08 +PAGE_EXECUTE :: 0x10 +PAGE_EXECUTE_READ :: 0x20 +PAGE_EXECUTE_READWRITE :: 0x40 +PAGE_EXECUTE_WRITECOPY :: 0x80 +PAGE_GUARD :: 0x100 +PAGE_NOCACHE :: 0x200 +PAGE_WRITECOMBINE :: 0x400 MEMORY_BASIC_INFORMATION :: struct { BaseAddress: PVOID, @@ -325,20 +325,20 @@ MEMORY_BASIC_INFORMATION :: struct { Protect: DWORD, Type: DWORD, } -PMEMORY_BASIC_INFORMATION :: ^MEMORY_BASIC_INFORMATION; -LPMEMORY_BASIC_INFORMATION :: ^MEMORY_BASIC_INFORMATION; - -MEM_COMMIT :: 0x1000; -MEM_RESERVE :: 0x2000; -MEM_DECOMMIT :: 0x4000; -MEM_RELEASE :: 0x8000; -MEM_FREE :: 0x10000; -MEM_PRIVATE :: 0x20000; -MEM_MAPPED :: 0x40000; -MEM_RESET :: 0x80000; -MEM_TOP_DOWN :: 0x100000; -MEM_LARGE_PAGES :: 0x20000000; -MEM_4MB_PAGES :: 0x80000000; +PMEMORY_BASIC_INFORMATION :: ^MEMORY_BASIC_INFORMATION +LPMEMORY_BASIC_INFORMATION :: ^MEMORY_BASIC_INFORMATION + +MEM_COMMIT :: 0x1000 +MEM_RESERVE :: 0x2000 +MEM_DECOMMIT :: 0x4000 +MEM_RELEASE :: 0x8000 +MEM_FREE :: 0x10000 +MEM_PRIVATE :: 0x20000 +MEM_MAPPED :: 0x40000 +MEM_RESET :: 0x80000 +MEM_TOP_DOWN :: 0x100000 +MEM_LARGE_PAGES :: 0x20000000 +MEM_4MB_PAGES :: 0x80000000 foreign kernel32 { VirtualAlloc :: proc( @@ -346,63 +346,63 @@ foreign kernel32 { dwSize: SIZE_T, flAllocationType: DWORD, flProtect: DWORD, - ) -> LPVOID ---; + ) -> LPVOID --- VirtualProtect :: proc( lpAddress: LPVOID, dwSize: SIZE_T, flNewProtect: DWORD, lpflOldProtect: PDWORD, - ) -> BOOL ---; + ) -> BOOL --- VirtualFree :: proc( lpAddress: LPVOID, dwSize: SIZE_T, dwFreeType: DWORD, - ) -> BOOL ---; + ) -> BOOL --- VirtualQuery :: proc( lpAddress: LPCVOID, lpBuffer: PMEMORY_BASIC_INFORMATION, dwLength: SIZE_T, - ) -> SIZE_T ---; + ) -> SIZE_T --- VirtualAllocEx :: proc( hProcess: HANDLE, lpAddress: LPVOID, dwSize: SIZE_T, flAllocationType: DWORD, flProtect: DWORD, - ) -> LPVOID ---; + ) -> LPVOID --- VirtualFreeEx :: proc( hProcess: HANDLE, lpAddress: LPVOID, dwSize: SIZE_T, dwFreeType: DWORD, - ) -> BOOL ---; + ) -> BOOL --- VirtualProtectEx :: proc( hProcess: HANDLE, lpAddress: LPVOID, dwSize: SIZE_T, flNewProtect: DWORD, lpflOldProtect: PDWORD, - ) -> BOOL ---; + ) -> BOOL --- VirtualQueryEx :: proc( hProcess: HANDLE, lpAddress: LPCVOID, lpBuffer: PMEMORY_BASIC_INFORMATION, dwLength: SIZE_T, - ) -> SIZE_T ---; + ) -> SIZE_T --- ReadProcessMemory :: proc( hProcess: HANDLE, lpBaseAddress: LPCVOID, lpBuffer: LPVOID, nSize: SIZE_T, lpNumberOfBytesRead: ^SIZE_T, - ) -> BOOL ---; + ) -> BOOL --- WriteProcessMemory :: proc( hProcess: HANDLE, lpBaseAddress: LPVOID, lpBuffer: LPCVOID, nSize: SIZE_T, lpNumberOfBytesWritten: ^SIZE_T, - ) -> BOOL ---; + ) -> BOOL --- CreateFileMappingW :: proc( hFile: HANDLE, lpFileMappingAttributes: LPSECURITY_ATTRIBUTES, @@ -410,19 +410,19 @@ foreign kernel32 { dwMaximumSizeHigh: DWORD, dwMaximumSizeLow: DWORD, lpName: LPCWSTR, - ) -> HANDLE ---; + ) -> HANDLE --- OpenFileMappingW :: proc( dwDesiredAccess: DWORD, bInheritHandle: BOOL, lpName: LPCWSTR, - ) -> HANDLE ---; + ) -> HANDLE --- MapViewOfFile :: proc( hFileMappingObject: HANDLE, dwDesiredAccess: DWORD, dwFileOffsetHigh: DWORD, dwFileOffsetLow: DWORD, dwNumberOfBytesToMap: SIZE_T, - ) -> LPVOID ---; + ) -> LPVOID --- MapViewOfFileEx :: proc( hFileMappingObject: HANDLE, dwDesiredAccess: DWORD, @@ -430,35 +430,35 @@ foreign kernel32 { dwFileOffsetLow: DWORD, dwNumberOfBytesToMap: SIZE_T, lpBaseAddress: LPVOID, - ) -> LPVOID ---; + ) -> LPVOID --- FlushViewOfFile :: proc( lpBaseAddress: LPCVOID, dwNumberOfBytesToFlush: SIZE_T, - ) -> BOOL ---; + ) -> BOOL --- UnmapViewOfFile :: proc( lpBaseAddress: LPCVOID, - ) -> BOOL ---; - GetLargePageMinimum :: proc() -> SIZE_T ---; + ) -> BOOL --- + GetLargePageMinimum :: proc() -> SIZE_T --- GetProcessWorkingSetSizeEx :: proc( hProcess: HANDLE, lpMinimumWorkingSetSize: PSIZE_T, lpMaximumWorkingSetSize: PSIZE_T, Flags: PDWORD, - ) -> BOOL ---; + ) -> BOOL --- SetProcessWorkingSetSizeEx :: proc( hProcess: HANDLE, dwMinimumWorkingSetSize: SIZE_T, dwMaximumWorkingSetSize: SIZE_T, Flags: DWORD, - ) -> BOOL ---; + ) -> BOOL --- VirtualLock :: proc( lpAddress: LPVOID, dwSize: SIZE_T, - ) -> BOOL ---; + ) -> BOOL --- VirtualUnlock :: proc( lpAddress: LPVOID, dwSize: SIZE_T, - ) -> BOOL ---; + ) -> BOOL --- GetWriteWatch :: proc( dwFlags: DWORD, lpBaseAddress: PVOID, @@ -466,11 +466,11 @@ foreign kernel32 { lpAddresses: ^PVOID, lpdwCount: ^ULONG_PTR, lpdwGranularity: LPDWORD, - ) -> UINT ---; + ) -> UINT --- ResetWriteWatch :: proc( lpBaseAddress: LPVOID, dwRegionSize: SIZE_T, - ) -> UINT ---; + ) -> UINT --- } @@ -478,36 +478,36 @@ MEMORY_RESOURCE_NOTIFICATION_TYPE :: enum c_int { LowMemoryResourceNotification, HighMemoryResourceNotification, } -LowMemoryResourceNotification :: MEMORY_RESOURCE_NOTIFICATION_TYPE.LowMemoryResourceNotification; -HighMemoryResourceNotification :: MEMORY_RESOURCE_NOTIFICATION_TYPE.HighMemoryResourceNotification; +LowMemoryResourceNotification :: MEMORY_RESOURCE_NOTIFICATION_TYPE.LowMemoryResourceNotification +HighMemoryResourceNotification :: MEMORY_RESOURCE_NOTIFICATION_TYPE.HighMemoryResourceNotification foreign kernel32 { CreateMemoryResourceNotification :: proc( NotificationType: MEMORY_RESOURCE_NOTIFICATION_TYPE, - ) -> HANDLE ---; + ) -> HANDLE --- QueryMemoryResourceNotification :: proc( ResourceNotificationHandle: HANDLE, ResourceState: PBOOL, - ) -> BOOL ---; + ) -> BOOL --- } -FILE_CACHE_MAX_HARD_ENABLE :: DWORD(0x00000001); -FILE_CACHE_MAX_HARD_DISABLE :: DWORD(0x00000002); -FILE_CACHE_MIN_HARD_ENABLE :: DWORD(0x00000004); -FILE_CACHE_MIN_HARD_DISABLE :: DWORD(0x00000008); +FILE_CACHE_MAX_HARD_ENABLE :: DWORD(0x00000001) +FILE_CACHE_MAX_HARD_DISABLE :: DWORD(0x00000002) +FILE_CACHE_MIN_HARD_ENABLE :: DWORD(0x00000004) +FILE_CACHE_MIN_HARD_DISABLE :: DWORD(0x00000008) foreign kernel32 { GetSystemFileCacheSize :: proc( lpMinimumFileCacheSize: PSIZE_T, lpMaximumFileCacheSize: PSIZE_T, lpFlags: PDWORD, - ) -> BOOL ---; + ) -> BOOL --- SetSystemFileCacheSize :: proc( MinimumFileCacheSize: SIZE_T, MaximumFileCacheSize: SIZE_T, Flags: DWORD, - ) -> BOOL ---; + ) -> BOOL --- CreateFileMappingNumaW :: proc( hFile: HANDLE, lpFileMappingAttributes: LPSECURITY_ATTRIBUTES, @@ -516,7 +516,7 @@ foreign kernel32 { dwMaximumSizeLow: DWORD, lpName: LPCWSTR, nndPreferred: DWORD, - ) -> HANDLE ---; + ) -> HANDLE --- } WIN32_MEMORY_RANGE_ENTRY :: struct { @@ -524,7 +524,7 @@ WIN32_MEMORY_RANGE_ENTRY :: struct { NumberOfBytes: SIZE_T, } -PWIN32_MEMORY_RANGE_ENTRY :: ^WIN32_MEMORY_RANGE_ENTRY; +PWIN32_MEMORY_RANGE_ENTRY :: ^WIN32_MEMORY_RANGE_ENTRY foreign kernel32 { PrefetchVirtualMemory :: proc( @@ -532,45 +532,45 @@ foreign kernel32 { NumberOfEntries: ULONG_PTR, VirtualAddresses: PWIN32_MEMORY_RANGE_ENTRY, Flags: ULONG, - ) -> BOOL ---; + ) -> BOOL --- CreateFileMappingFromApp :: proc( hFile: HANDLE, SecurityAttributes: PSECURITY_ATTRIBUTES, PageProtection: ULONG, MaximumSize: ULONG64, Name: PCWSTR, - ) -> HANDLE ---; + ) -> HANDLE --- MapViewOfFileFromApp :: proc( hFileMappingObject: HANDLE, DesiredAccess: ULONG, FileOffset: ULONG64, NumberOfBytesToMap: SIZE_T, - ) -> PVOID ---; + ) -> PVOID --- UnmapViewOfFileEx :: proc( BaseAddress: PVOID, UnmapFlags: ULONG, - ) -> BOOL ---; + ) -> BOOL --- AllocateUserPhysicalPages :: proc( hProcess: HANDLE, NumberOfPages: PULONG_PTR, PageArray: PULONG_PTR, - ) -> BOOL ---; + ) -> BOOL --- FreeUserPhysicalPages :: proc( hProcess: HANDLE, NumberOfPages: PULONG_PTR, PageArray: PULONG_PTR, - ) -> BOOL ---; + ) -> BOOL --- MapUserPhysicalPages :: proc( VirtualAddress: PVOID, NumberOfPages: ULONG_PTR, PageArray: PULONG_PTR, - ) -> BOOL ---; + ) -> BOOL --- AllocateUserPhysicalPagesNuma :: proc( hProcess: HANDLE, NumberOfPages: PULONG_PTR, PageArray: PULONG_PTR, nndPreferred: DWORD, - ) -> BOOL ---; + ) -> BOOL --- VirtualAllocExNuma :: proc( hProcess: HANDLE, lpAddress: LPVOID, @@ -578,26 +578,26 @@ foreign kernel32 { flAllocationType: DWORD, flProtect: DWORD, nndPreferred: DWORD, - ) -> LPVOID ---; + ) -> LPVOID --- } -MEHC_PATROL_SCRUBBER_PRESENT :: ULONG(0x1); +MEHC_PATROL_SCRUBBER_PRESENT :: ULONG(0x1) foreign kernel32 { GetMemoryErrorHandlingCapabilities :: proc( Capabilities: PULONG, - ) -> BOOL ---; + ) -> BOOL --- } -PBAD_MEMORY_CALLBACK_ROUTINE :: #type proc "stdcall" (); +PBAD_MEMORY_CALLBACK_ROUTINE :: #type proc "stdcall" () foreign kernel32 { RegisterBadMemoryNotification :: proc( Callback: PBAD_MEMORY_CALLBACK_ROUTINE, - ) -> PVOID ---; + ) -> PVOID --- UnregisterBadMemoryNotification :: proc( RegistrationHandle: PVOID, - ) -> BOOL ---; + ) -> BOOL --- } OFFER_PRIORITY :: enum c_int { @@ -606,48 +606,48 @@ OFFER_PRIORITY :: enum c_int { VmOfferPriorityBelowNormal, VmOfferPriorityNormal, } -VmOfferPriorityVeryLow :: OFFER_PRIORITY.VmOfferPriorityVeryLow; -VmOfferPriorityLow :: OFFER_PRIORITY.VmOfferPriorityLow; -VmOfferPriorityBelowNormal :: OFFER_PRIORITY.VmOfferPriorityBelowNormal; -VmOfferPriorityNormal :: OFFER_PRIORITY.VmOfferPriorityNormal; +VmOfferPriorityVeryLow :: OFFER_PRIORITY.VmOfferPriorityVeryLow +VmOfferPriorityLow :: OFFER_PRIORITY.VmOfferPriorityLow +VmOfferPriorityBelowNormal :: OFFER_PRIORITY.VmOfferPriorityBelowNormal +VmOfferPriorityNormal :: OFFER_PRIORITY.VmOfferPriorityNormal foreign kernel32 { OfferVirtualMemory :: proc( VirtualAddress: PVOID, Size: SIZE_T, Priority: OFFER_PRIORITY, - ) -> DWORD ---; + ) -> DWORD --- ReclaimVirtualMemory :: proc( VirtualAddress: PVOID, Size: SIZE_T, - ) -> DWORD ---; + ) -> DWORD --- DiscardVirtualMemory :: proc( VirtualAddress: PVOID, Size: SIZE_T, - ) -> DWORD ---; + ) -> DWORD --- VirtualAllocFromApp :: proc( BaseAddress: PVOID, Size: SIZE_T, AllocationType: ULONG, Protection: ULONG, - ) -> PVOID ---; + ) -> PVOID --- VirtualProtectFromApp :: proc( Address: PVOID, Size: SIZE_T, NewProtection: ULONG, OldProtection: PULONG, - ) -> BOOL ---; + ) -> BOOL --- OpenFileMappingFromApp :: proc( DesiredAccess: ULONG, InheritHandle: BOOL, Name: PCWSTR, - ) -> HANDLE ---; + ) -> HANDLE --- } WIN32_MEMORY_INFORMATION_CLASS :: enum c_int { MemoryRegionInfo, } -MemoryRegionInfo :: WIN32_MEMORY_INFORMATION_CLASS.MemoryRegionInfo; +MemoryRegionInfo :: WIN32_MEMORY_INFORMATION_CLASS.MemoryRegionInfo WIN32_MEMORY_REGION_INFORMATION :: struct { AllocationBase: PVOID, @@ -664,7 +664,7 @@ WIN32_MEMORY_REGION_INFORMATION_u :: struct #raw_union { WIN32_MEMORY_REGION_INFORMATION_u_s :: struct { Bitfield: ULONG, } -WIN32_MEMORY_REGION_INFORMATION_u_s_Bitfield :: distinct ULONG; +WIN32_MEMORY_REGION_INFORMATION_u_s_Bitfield :: distinct ULONG /*bit_field #align align_of(ULONG) { Private : 1-0, MappedDataFile : 2-1, @@ -697,7 +697,7 @@ foreign kernel32 { } -NUMA_NO_PREFERRED_NODE :: 0xffffffff; +NUMA_NO_PREFERRED_NODE :: 0xffffffff MapViewOfFile2 :: #force_inline proc( FileMappingHandle: HANDLE, @@ -717,7 +717,7 @@ MapViewOfFile2 :: #force_inline proc( AllocationType, PageProtection, NUMA_NO_PREFERRED_NODE, - ); + ) } foreign kernel32 { @@ -725,5 +725,5 @@ foreign kernel32 { ProcessHandle: HANDLE, BaseAddress: PVOID, UnmapFlags: ULONG, - ) -> BOOL ---; + ) -> BOOL --- } diff --git a/core/sys/windows/netapi32.odin b/core/sys/windows/netapi32.odin index bc77b3ffd..0df277181 100644 --- a/core/sys/windows/netapi32.odin +++ b/core/sys/windows/netapi32.odin @@ -10,29 +10,29 @@ foreign netapi32 { level: DWORD, user_info: ^USER_INFO_1, // Perhaps make this a #raw_union with USER_INFO1..4 when we need the other levels. parm_err: ^DWORD, - ) -> NET_API_STATUS ---; + ) -> NET_API_STATUS --- NetUserDel :: proc( servername: wstring, username: wstring, - ) -> NET_API_STATUS ---; + ) -> NET_API_STATUS --- NetUserGetInfo :: proc( servername: wstring, username: wstring, level: DWORD, user_info: ^USER_INFO_1, - ) -> NET_API_STATUS ---; + ) -> NET_API_STATUS --- NetLocalGroupAddMembers :: proc( servername: wstring, groupname: wstring, level: DWORD, group_members_info: ^LOCALGROUP_MEMBERS_INFO_0, // Actually a variably sized array of these. totalentries: DWORD, - ) -> NET_API_STATUS ---; + ) -> NET_API_STATUS --- NetLocalGroupDelMembers :: proc( servername: wstring, groupname: wstring, level: DWORD, group_members_info: ^LOCALGROUP_MEMBERS_INFO_0, // Actually a variably sized array of these. totalentries: DWORD, - ) -> NET_API_STATUS ---; + ) -> NET_API_STATUS --- }
\ No newline at end of file diff --git a/core/sys/windows/ntdll.odin b/core/sys/windows/ntdll.odin index 7bbe44e59..5deffd9f9 100644 --- a/core/sys/windows/ntdll.odin +++ b/core/sys/windows/ntdll.odin @@ -5,5 +5,5 @@ foreign import ntdll_lib "system:ntdll.lib" @(default_calling_convention="std") foreign ntdll_lib { - RtlGetVersion :: proc(lpVersionInformation: ^OSVERSIONINFOEXW) -> NTSTATUS ---; + RtlGetVersion :: proc(lpVersionInformation: ^OSVERSIONINFOEXW) -> NTSTATUS --- }
\ No newline at end of file diff --git a/core/sys/windows/types.odin b/core/sys/windows/types.odin index 9e55a463d..823535575 100644 --- a/core/sys/windows/types.odin +++ b/core/sys/windows/types.odin @@ -3,179 +3,179 @@ package sys_windows import "core:c" -c_char :: c.char; -c_uchar :: c.uchar; -c_int :: c.int; -c_uint :: c.uint; -c_long :: c.long; -c_longlong :: c.longlong; -c_ulong :: c.ulong; -c_short :: c.short; -c_ushort :: c.ushort; -size_t :: c.size_t; -wchar_t :: c.wchar_t; - -DWORD :: c_ulong; -HANDLE :: distinct LPVOID; -HINSTANCE :: HANDLE; -HMODULE :: distinct HINSTANCE; -HRESULT :: distinct LONG; -HWND :: distinct HANDLE; -HMONITOR :: distinct HANDLE; -BOOL :: distinct b32; -BYTE :: distinct u8; -BOOLEAN :: distinct b8; -GROUP :: distinct c_uint; -LARGE_INTEGER :: distinct c_longlong; -LONG :: c_long; -UINT :: c_uint; -INT :: c_int; -SHORT :: c_short; -USHORT :: c_ushort; -WCHAR :: wchar_t; -SIZE_T :: uint; -PSIZE_T :: ^SIZE_T; -WORD :: u16; -CHAR :: c_char; -ULONG_PTR :: uint; -PULONG_PTR :: ^ULONG_PTR; -LPULONG_PTR :: ^ULONG_PTR; -DWORD_PTR :: ULONG_PTR; -LONG_PTR :: int; -ULONG :: c_ulong; -UCHAR :: BYTE; -NTSTATUS :: c.long; - -UINT8 :: u8; -UINT16 :: u16; -UINT32 :: u32; -UINT64 :: u64; - -INT8 :: i8; -INT16 :: i16; -INT32 :: i32; -INT64 :: i64; - - -ULONG64 :: u64; -LONG64 :: i64; - -PDWORD_PTR :: ^DWORD_PTR; -ATOM :: distinct WORD; - -wstring :: [^]WCHAR; - -PBYTE :: ^BYTE; -LPBYTE :: ^BYTE; -PBOOL :: ^BOOL; -LPBOOL :: ^BOOL; -LPCSTR :: cstring; -LPCWSTR :: wstring; -LPDWORD :: ^DWORD; -PCSTR :: cstring; -PCWSTR :: wstring; -PDWORD :: ^DWORD; -LPHANDLE :: ^HANDLE; -LPOVERLAPPED :: ^OVERLAPPED; -LPPROCESS_INFORMATION :: ^PROCESS_INFORMATION; -PSECURITY_ATTRIBUTES :: ^SECURITY_ATTRIBUTES; -LPSECURITY_ATTRIBUTES :: ^SECURITY_ATTRIBUTES; -LPSTARTUPINFO :: ^STARTUPINFO; -PVOID :: rawptr; -LPVOID :: rawptr; -PINT :: ^INT; -LPINT :: ^INT; -PUINT :: ^UINT; -LPUINT :: ^UINT; -LPWCH :: ^WCHAR; -LPWORD :: ^WORD; -PULONG :: ^ULONG; -LPWIN32_FIND_DATAW :: ^WIN32_FIND_DATAW; -LPWSADATA :: ^WSADATA; -LPWSAPROTOCOL_INFO :: ^WSAPROTOCOL_INFO; -LPSTR :: ^CHAR; -LPWSTR :: ^WCHAR; -LPFILETIME :: ^FILETIME; -LPWSABUF :: ^WSABUF; -LPWSAOVERLAPPED :: distinct rawptr; -LPWSAOVERLAPPED_COMPLETION_ROUTINE :: distinct rawptr; -LPCVOID :: rawptr; - -PCONDITION_VARIABLE :: ^CONDITION_VARIABLE; -PLARGE_INTEGER :: ^LARGE_INTEGER; -PSRWLOCK :: ^SRWLOCK; - -SOCKET :: distinct uintptr; // TODO -socklen_t :: c_int; -ADDRESS_FAMILY :: USHORT; - -TRUE :: BOOL(true); -FALSE :: BOOL(false); +c_char :: c.char +c_uchar :: c.uchar +c_int :: c.int +c_uint :: c.uint +c_long :: c.long +c_longlong :: c.longlong +c_ulong :: c.ulong +c_short :: c.short +c_ushort :: c.ushort +size_t :: c.size_t +wchar_t :: c.wchar_t + +DWORD :: c_ulong +HANDLE :: distinct LPVOID +HINSTANCE :: HANDLE +HMODULE :: distinct HINSTANCE +HRESULT :: distinct LONG +HWND :: distinct HANDLE +HMONITOR :: distinct HANDLE +BOOL :: distinct b32 +BYTE :: distinct u8 +BOOLEAN :: distinct b8 +GROUP :: distinct c_uint +LARGE_INTEGER :: distinct c_longlong +LONG :: c_long +UINT :: c_uint +INT :: c_int +SHORT :: c_short +USHORT :: c_ushort +WCHAR :: wchar_t +SIZE_T :: uint +PSIZE_T :: ^SIZE_T +WORD :: u16 +CHAR :: c_char +ULONG_PTR :: uint +PULONG_PTR :: ^ULONG_PTR +LPULONG_PTR :: ^ULONG_PTR +DWORD_PTR :: ULONG_PTR +LONG_PTR :: int +ULONG :: c_ulong +UCHAR :: BYTE +NTSTATUS :: c.long + +UINT8 :: u8 +UINT16 :: u16 +UINT32 :: u32 +UINT64 :: u64 + +INT8 :: i8 +INT16 :: i16 +INT32 :: i32 +INT64 :: i64 + + +ULONG64 :: u64 +LONG64 :: i64 + +PDWORD_PTR :: ^DWORD_PTR +ATOM :: distinct WORD + +wstring :: [^]WCHAR + +PBYTE :: ^BYTE +LPBYTE :: ^BYTE +PBOOL :: ^BOOL +LPBOOL :: ^BOOL +LPCSTR :: cstring +LPCWSTR :: wstring +LPDWORD :: ^DWORD +PCSTR :: cstring +PCWSTR :: wstring +PDWORD :: ^DWORD +LPHANDLE :: ^HANDLE +LPOVERLAPPED :: ^OVERLAPPED +LPPROCESS_INFORMATION :: ^PROCESS_INFORMATION +PSECURITY_ATTRIBUTES :: ^SECURITY_ATTRIBUTES +LPSECURITY_ATTRIBUTES :: ^SECURITY_ATTRIBUTES +LPSTARTUPINFO :: ^STARTUPINFO +PVOID :: rawptr +LPVOID :: rawptr +PINT :: ^INT +LPINT :: ^INT +PUINT :: ^UINT +LPUINT :: ^UINT +LPWCH :: ^WCHAR +LPWORD :: ^WORD +PULONG :: ^ULONG +LPWIN32_FIND_DATAW :: ^WIN32_FIND_DATAW +LPWSADATA :: ^WSADATA +LPWSAPROTOCOL_INFO :: ^WSAPROTOCOL_INFO +LPSTR :: ^CHAR +LPWSTR :: ^WCHAR +LPFILETIME :: ^FILETIME +LPWSABUF :: ^WSABUF +LPWSAOVERLAPPED :: distinct rawptr +LPWSAOVERLAPPED_COMPLETION_ROUTINE :: distinct rawptr +LPCVOID :: rawptr + +PCONDITION_VARIABLE :: ^CONDITION_VARIABLE +PLARGE_INTEGER :: ^LARGE_INTEGER +PSRWLOCK :: ^SRWLOCK + +SOCKET :: distinct uintptr // TODO +socklen_t :: c_int +ADDRESS_FAMILY :: USHORT + +TRUE :: BOOL(true) +FALSE :: BOOL(false) SIZE :: struct { cx: LONG, cy: LONG, } -PSIZE :: ^SIZE; -LPSIZE :: ^SIZE; - -FILE_ATTRIBUTE_READONLY: DWORD : 0x00000001; -FILE_ATTRIBUTE_HIDDEN: DWORD : 0x00000002; -FILE_ATTRIBUTE_SYSTEM: DWORD : 0x00000004; -FILE_ATTRIBUTE_DIRECTORY: DWORD : 0x00000010; -FILE_ATTRIBUTE_ARCHIVE: DWORD : 0x00000020; -FILE_ATTRIBUTE_DEVICE: DWORD : 0x00000040; -FILE_ATTRIBUTE_NORMAL: DWORD : 0x00000080; -FILE_ATTRIBUTE_TEMPORARY: DWORD : 0x00000100; -FILE_ATTRIBUTE_SPARSE_FILE: DWORD : 0x00000200; -FILE_ATTRIBUTE_REPARSE_Point: DWORD : 0x00000400; -FILE_ATTRIBUTE_REPARSE_POINT: DWORD : 0x00000400; -FILE_ATTRIBUTE_COMPRESSED: DWORD : 0x00000800; -FILE_ATTRIBUTE_OFFLINE: DWORD : 0x00001000; -FILE_ATTRIBUTE_NOT_CONTENT_INDEXED: DWORD : 0x00002000; -FILE_ATTRIBUTE_ENCRYPTED: DWORD : 0x00004000; - -FILE_SHARE_READ: DWORD : 0x00000001; -FILE_SHARE_WRITE: DWORD : 0x00000002; -FILE_SHARE_DELETE: DWORD : 0x00000004; -FILE_GENERIC_ALL: DWORD : 0x10000000; -FILE_GENERIC_EXECUTE: DWORD : 0x20000000; -FILE_GENERIC_READ: DWORD : 0x80000000; - -CREATE_NEW: DWORD : 1; -CREATE_ALWAYS: DWORD : 2; -OPEN_ALWAYS: DWORD : 4; -OPEN_EXISTING: DWORD : 3; -TRUNCATE_EXISTING: DWORD : 5; - - - -FILE_WRITE_DATA: DWORD : 0x00000002; -FILE_APPEND_DATA: DWORD : 0x00000004; -FILE_WRITE_EA: DWORD : 0x00000010; -FILE_WRITE_ATTRIBUTES: DWORD : 0x00000100; -READ_CONTROL: DWORD : 0x00020000; -SYNCHRONIZE: DWORD : 0x00100000; -GENERIC_READ: DWORD : 0x80000000; -GENERIC_WRITE: DWORD : 0x40000000; -STANDARD_RIGHTS_WRITE: DWORD : READ_CONTROL; +PSIZE :: ^SIZE +LPSIZE :: ^SIZE + +FILE_ATTRIBUTE_READONLY: DWORD : 0x00000001 +FILE_ATTRIBUTE_HIDDEN: DWORD : 0x00000002 +FILE_ATTRIBUTE_SYSTEM: DWORD : 0x00000004 +FILE_ATTRIBUTE_DIRECTORY: DWORD : 0x00000010 +FILE_ATTRIBUTE_ARCHIVE: DWORD : 0x00000020 +FILE_ATTRIBUTE_DEVICE: DWORD : 0x00000040 +FILE_ATTRIBUTE_NORMAL: DWORD : 0x00000080 +FILE_ATTRIBUTE_TEMPORARY: DWORD : 0x00000100 +FILE_ATTRIBUTE_SPARSE_FILE: DWORD : 0x00000200 +FILE_ATTRIBUTE_REPARSE_Point: DWORD : 0x00000400 +FILE_ATTRIBUTE_REPARSE_POINT: DWORD : 0x00000400 +FILE_ATTRIBUTE_COMPRESSED: DWORD : 0x00000800 +FILE_ATTRIBUTE_OFFLINE: DWORD : 0x00001000 +FILE_ATTRIBUTE_NOT_CONTENT_INDEXED: DWORD : 0x00002000 +FILE_ATTRIBUTE_ENCRYPTED: DWORD : 0x00004000 + +FILE_SHARE_READ: DWORD : 0x00000001 +FILE_SHARE_WRITE: DWORD : 0x00000002 +FILE_SHARE_DELETE: DWORD : 0x00000004 +FILE_GENERIC_ALL: DWORD : 0x10000000 +FILE_GENERIC_EXECUTE: DWORD : 0x20000000 +FILE_GENERIC_READ: DWORD : 0x80000000 + +CREATE_NEW: DWORD : 1 +CREATE_ALWAYS: DWORD : 2 +OPEN_ALWAYS: DWORD : 4 +OPEN_EXISTING: DWORD : 3 +TRUNCATE_EXISTING: DWORD : 5 + + + +FILE_WRITE_DATA: DWORD : 0x00000002 +FILE_APPEND_DATA: DWORD : 0x00000004 +FILE_WRITE_EA: DWORD : 0x00000010 +FILE_WRITE_ATTRIBUTES: DWORD : 0x00000100 +READ_CONTROL: DWORD : 0x00020000 +SYNCHRONIZE: DWORD : 0x00100000 +GENERIC_READ: DWORD : 0x80000000 +GENERIC_WRITE: DWORD : 0x40000000 +STANDARD_RIGHTS_WRITE: DWORD : READ_CONTROL FILE_GENERIC_WRITE: DWORD : STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA | - SYNCHRONIZE; + SYNCHRONIZE -FILE_FLAG_OPEN_REPARSE_POINT: DWORD : 0x00200000; -FILE_FLAG_BACKUP_SEMANTICS: DWORD : 0x02000000; -SECURITY_SQOS_PRESENT: DWORD : 0x00100000; +FILE_FLAG_OPEN_REPARSE_POINT: DWORD : 0x00200000 +FILE_FLAG_BACKUP_SEMANTICS: DWORD : 0x02000000 +SECURITY_SQOS_PRESENT: DWORD : 0x00100000 -FIONBIO: c_ulong : 0x8004667e; +FIONBIO: c_ulong : 0x8004667e -GET_FILEEX_INFO_LEVELS :: distinct i32; -GetFileExInfoStandard: GET_FILEEX_INFO_LEVELS : 0; -GetFileExMaxInfoLevel: GET_FILEEX_INFO_LEVELS : 1; +GET_FILEEX_INFO_LEVELS :: distinct i32 +GetFileExInfoStandard: GET_FILEEX_INFO_LEVELS : 0 +GetFileExMaxInfoLevel: GET_FILEEX_INFO_LEVELS : 1 WIN32_FIND_DATAW :: struct { @@ -191,126 +191,126 @@ WIN32_FIND_DATAW :: struct { cAlternateFileName: [14]wchar_t, } -WSA_FLAG_OVERLAPPED: DWORD : 0x01; -WSA_FLAG_NO_HANDLE_INHERIT: DWORD : 0x80; - -WSADESCRIPTION_LEN :: 256; -WSASYS_STATUS_LEN :: 128; -WSAPROTOCOL_LEN: DWORD : 255; -INVALID_SOCKET :: ~SOCKET(0); - -WSAEACCES: c_int : 10013; -WSAEINVAL: c_int : 10022; -WSAEWOULDBLOCK: c_int : 10035; -WSAEPROTOTYPE: c_int : 10041; -WSAEADDRINUSE: c_int : 10048; -WSAEADDRNOTAVAIL: c_int : 10049; -WSAECONNABORTED: c_int : 10053; -WSAECONNRESET: c_int : 10054; -WSAENOTCONN: c_int : 10057; -WSAESHUTDOWN: c_int : 10058; -WSAETIMEDOUT: c_int : 10060; -WSAECONNREFUSED: c_int : 10061; - -MAX_PROTOCOL_CHAIN: DWORD : 7; - -MAXIMUM_REPARSE_DATA_BUFFER_SIZE :: 16 * 1024; -FSCTL_GET_REPARSE_POINT: DWORD : 0x900a8; -IO_REPARSE_TAG_SYMLINK: DWORD : 0xa000000c; -IO_REPARSE_TAG_MOUNT_POINT: DWORD : 0xa0000003; -SYMLINK_FLAG_RELATIVE: DWORD : 0x00000001; -FSCTL_SET_REPARSE_POINT: DWORD : 0x900a4; - -SYMBOLIC_LINK_FLAG_DIRECTORY: DWORD : 0x1; -SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE: DWORD : 0x2; - -STD_INPUT_HANDLE: DWORD : ~DWORD(0) -10 + 1; -STD_OUTPUT_HANDLE: DWORD : ~DWORD(0) -11 + 1; -STD_ERROR_HANDLE: DWORD : ~DWORD(0) -12 + 1; - -PROGRESS_CONTINUE: DWORD : 0; - -ERROR_FILE_NOT_FOUND: DWORD : 2; -ERROR_PATH_NOT_FOUND: DWORD : 3; -ERROR_ACCESS_DENIED: DWORD : 5; -ERROR_NOT_ENOUGH_MEMORY: DWORD : 8; -ERROR_INVALID_HANDLE: DWORD : 6; -ERROR_NO_MORE_FILES: DWORD : 18; -ERROR_SHARING_VIOLATION: DWORD : 32; -ERROR_LOCK_VIOLATION: DWORD : 33; -ERROR_HANDLE_EOF: DWORD : 38; -ERROR_NOT_SUPPORTED: DWORD : 50; -ERROR_FILE_EXISTS: DWORD : 80; -ERROR_INVALID_PARAMETER: DWORD : 87; -ERROR_BROKEN_PIPE: DWORD : 109; -ERROR_CALL_NOT_IMPLEMENTED: DWORD : 120; -ERROR_INSUFFICIENT_BUFFER: DWORD : 122; -ERROR_INVALID_NAME: DWORD : 123; -ERROR_LOCK_FAILED: DWORD : 167; -ERROR_ALREADY_EXISTS: DWORD : 183; -ERROR_NO_DATA: DWORD : 232; -ERROR_ENVVAR_NOT_FOUND: DWORD : 203; -ERROR_OPERATION_ABORTED: DWORD : 995; -ERROR_IO_PENDING: DWORD : 997; -ERROR_TIMEOUT: DWORD : 0x5B4; -ERROR_NO_UNICODE_TRANSLATION: DWORD : 1113; - -E_NOTIMPL :: HRESULT(-0x7fff_bfff); // 0x8000_4001 - -INVALID_HANDLE :: HANDLE(~uintptr(0)); -INVALID_HANDLE_VALUE :: INVALID_HANDLE; - -FACILITY_NT_BIT: DWORD : 0x1000_0000; - -FORMAT_MESSAGE_FROM_SYSTEM: DWORD : 0x00001000; -FORMAT_MESSAGE_FROM_HMODULE: DWORD : 0x00000800; -FORMAT_MESSAGE_IGNORE_INSERTS: DWORD : 0x00000200; - -TLS_OUT_OF_INDEXES: DWORD : 0xFFFFFFFF; - -DLL_THREAD_DETACH: DWORD : 3; -DLL_PROCESS_DETACH: DWORD : 0; -CREATE_SUSPENDED :: DWORD(0x00000004); - -INFINITE :: ~DWORD(0); - -DUPLICATE_SAME_ACCESS: DWORD : 0x00000002; - -CONDITION_VARIABLE_INIT :: CONDITION_VARIABLE{}; -SRWLOCK_INIT :: SRWLOCK{}; - -DETACHED_PROCESS: DWORD : 0x00000008; -CREATE_NEW_PROCESS_GROUP: DWORD : 0x00000200; -CREATE_UNICODE_ENVIRONMENT: DWORD : 0x00000400; -STARTF_USESTDHANDLES: DWORD : 0x00000100; - -AF_INET: c_int : 2; -AF_INET6: c_int : 23; -SD_BOTH: c_int : 2; -SD_RECEIVE: c_int : 0; -SD_SEND: c_int : 1; -SOCK_DGRAM: c_int : 2; -SOCK_STREAM: c_int : 1; -SOL_SOCKET: c_int : 0xffff; -SO_RCVTIMEO: c_int : 0x1006; -SO_SNDTIMEO: c_int : 0x1005; -SO_REUSEADDR: c_int : 0x0004; -IPPROTO_IP: c_int : 0; -IPPROTO_TCP: c_int : 6; -IPPROTO_IPV6: c_int : 41; -TCP_NODELAY: c_int : 0x0001; -IP_TTL: c_int : 4; -IPV6_V6ONLY: c_int : 27; -SO_ERROR: c_int : 0x1007; -SO_BROADCAST: c_int : 0x0020; -IP_MULTICAST_LOOP: c_int : 11; -IPV6_MULTICAST_LOOP: c_int : 11; -IP_MULTICAST_TTL: c_int : 10; -IP_ADD_MEMBERSHIP: c_int : 12; -IP_DROP_MEMBERSHIP: c_int : 13; -IPV6_ADD_MEMBERSHIP: c_int : 12; -IPV6_DROP_MEMBERSHIP: c_int : 13; -MSG_PEEK: c_int : 0x2; +WSA_FLAG_OVERLAPPED: DWORD : 0x01 +WSA_FLAG_NO_HANDLE_INHERIT: DWORD : 0x80 + +WSADESCRIPTION_LEN :: 256 +WSASYS_STATUS_LEN :: 128 +WSAPROTOCOL_LEN: DWORD : 255 +INVALID_SOCKET :: ~SOCKET(0) + +WSAEACCES: c_int : 10013 +WSAEINVAL: c_int : 10022 +WSAEWOULDBLOCK: c_int : 10035 +WSAEPROTOTYPE: c_int : 10041 +WSAEADDRINUSE: c_int : 10048 +WSAEADDRNOTAVAIL: c_int : 10049 +WSAECONNABORTED: c_int : 10053 +WSAECONNRESET: c_int : 10054 +WSAENOTCONN: c_int : 10057 +WSAESHUTDOWN: c_int : 10058 +WSAETIMEDOUT: c_int : 10060 +WSAECONNREFUSED: c_int : 10061 + +MAX_PROTOCOL_CHAIN: DWORD : 7 + +MAXIMUM_REPARSE_DATA_BUFFER_SIZE :: 16 * 1024 +FSCTL_GET_REPARSE_POINT: DWORD : 0x900a8 +IO_REPARSE_TAG_SYMLINK: DWORD : 0xa000000c +IO_REPARSE_TAG_MOUNT_POINT: DWORD : 0xa0000003 +SYMLINK_FLAG_RELATIVE: DWORD : 0x00000001 +FSCTL_SET_REPARSE_POINT: DWORD : 0x900a4 + +SYMBOLIC_LINK_FLAG_DIRECTORY: DWORD : 0x1 +SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE: DWORD : 0x2 + +STD_INPUT_HANDLE: DWORD : ~DWORD(0) -10 + 1 +STD_OUTPUT_HANDLE: DWORD : ~DWORD(0) -11 + 1 +STD_ERROR_HANDLE: DWORD : ~DWORD(0) -12 + 1 + +PROGRESS_CONTINUE: DWORD : 0 + +ERROR_FILE_NOT_FOUND: DWORD : 2 +ERROR_PATH_NOT_FOUND: DWORD : 3 +ERROR_ACCESS_DENIED: DWORD : 5 +ERROR_NOT_ENOUGH_MEMORY: DWORD : 8 +ERROR_INVALID_HANDLE: DWORD : 6 +ERROR_NO_MORE_FILES: DWORD : 18 +ERROR_SHARING_VIOLATION: DWORD : 32 +ERROR_LOCK_VIOLATION: DWORD : 33 +ERROR_HANDLE_EOF: DWORD : 38 +ERROR_NOT_SUPPORTED: DWORD : 50 +ERROR_FILE_EXISTS: DWORD : 80 +ERROR_INVALID_PARAMETER: DWORD : 87 +ERROR_BROKEN_PIPE: DWORD : 109 +ERROR_CALL_NOT_IMPLEMENTED: DWORD : 120 +ERROR_INSUFFICIENT_BUFFER: DWORD : 122 +ERROR_INVALID_NAME: DWORD : 123 +ERROR_LOCK_FAILED: DWORD : 167 +ERROR_ALREADY_EXISTS: DWORD : 183 +ERROR_NO_DATA: DWORD : 232 +ERROR_ENVVAR_NOT_FOUND: DWORD : 203 +ERROR_OPERATION_ABORTED: DWORD : 995 +ERROR_IO_PENDING: DWORD : 997 +ERROR_TIMEOUT: DWORD : 0x5B4 +ERROR_NO_UNICODE_TRANSLATION: DWORD : 1113 + +E_NOTIMPL :: HRESULT(-0x7fff_bfff) // 0x8000_4001 + +INVALID_HANDLE :: HANDLE(~uintptr(0)) +INVALID_HANDLE_VALUE :: INVALID_HANDLE + +FACILITY_NT_BIT: DWORD : 0x1000_0000 + +FORMAT_MESSAGE_FROM_SYSTEM: DWORD : 0x00001000 +FORMAT_MESSAGE_FROM_HMODULE: DWORD : 0x00000800 +FORMAT_MESSAGE_IGNORE_INSERTS: DWORD : 0x00000200 + +TLS_OUT_OF_INDEXES: DWORD : 0xFFFFFFFF + +DLL_THREAD_DETACH: DWORD : 3 +DLL_PROCESS_DETACH: DWORD : 0 +CREATE_SUSPENDED :: DWORD(0x00000004) + +INFINITE :: ~DWORD(0) + +DUPLICATE_SAME_ACCESS: DWORD : 0x00000002 + +CONDITION_VARIABLE_INIT :: CONDITION_VARIABLE{} +SRWLOCK_INIT :: SRWLOCK{} + +DETACHED_PROCESS: DWORD : 0x00000008 +CREATE_NEW_PROCESS_GROUP: DWORD : 0x00000200 +CREATE_UNICODE_ENVIRONMENT: DWORD : 0x00000400 +STARTF_USESTDHANDLES: DWORD : 0x00000100 + +AF_INET: c_int : 2 +AF_INET6: c_int : 23 +SD_BOTH: c_int : 2 +SD_RECEIVE: c_int : 0 +SD_SEND: c_int : 1 +SOCK_DGRAM: c_int : 2 +SOCK_STREAM: c_int : 1 +SOL_SOCKET: c_int : 0xffff +SO_RCVTIMEO: c_int : 0x1006 +SO_SNDTIMEO: c_int : 0x1005 +SO_REUSEADDR: c_int : 0x0004 +IPPROTO_IP: c_int : 0 +IPPROTO_TCP: c_int : 6 +IPPROTO_IPV6: c_int : 41 +TCP_NODELAY: c_int : 0x0001 +IP_TTL: c_int : 4 +IPV6_V6ONLY: c_int : 27 +SO_ERROR: c_int : 0x1007 +SO_BROADCAST: c_int : 0x0020 +IP_MULTICAST_LOOP: c_int : 11 +IPV6_MULTICAST_LOOP: c_int : 11 +IP_MULTICAST_TTL: c_int : 10 +IP_ADD_MEMBERSHIP: c_int : 12 +IP_DROP_MEMBERSHIP: c_int : 13 +IPV6_ADD_MEMBERSHIP: c_int : 12 +IPV6_DROP_MEMBERSHIP: c_int : 13 +MSG_PEEK: c_int : 0x2 ip_mreq :: struct { imr_multiaddr: in_addr, @@ -322,59 +322,59 @@ ipv6_mreq :: struct { ipv6mr_interface: c_uint, } -VOLUME_NAME_DOS: DWORD : 0x0; -MOVEFILE_REPLACE_EXISTING: DWORD : 1; +VOLUME_NAME_DOS: DWORD : 0x0 +MOVEFILE_REPLACE_EXISTING: DWORD : 1 -FILE_BEGIN: DWORD : 0; -FILE_CURRENT: DWORD : 1; -FILE_END: DWORD : 2; +FILE_BEGIN: DWORD : 0 +FILE_CURRENT: DWORD : 1 +FILE_END: DWORD : 2 -WAIT_OBJECT_0: DWORD : 0x00000000; -WAIT_TIMEOUT: DWORD : 258; -WAIT_FAILED: DWORD : 0xFFFFFFFF; +WAIT_OBJECT_0: DWORD : 0x00000000 +WAIT_TIMEOUT: DWORD : 258 +WAIT_FAILED: DWORD : 0xFFFFFFFF -PIPE_ACCESS_INBOUND: DWORD : 0x00000001; -PIPE_ACCESS_OUTBOUND: DWORD : 0x00000002; -FILE_FLAG_FIRST_PIPE_INSTANCE: DWORD : 0x00080000; -FILE_FLAG_OVERLAPPED: DWORD : 0x40000000; -PIPE_WAIT: DWORD : 0x00000000; -PIPE_TYPE_BYTE: DWORD : 0x00000000; -PIPE_REJECT_REMOTE_CLIENTS: DWORD : 0x00000008; -PIPE_READMODE_BYTE: DWORD : 0x00000000; +PIPE_ACCESS_INBOUND: DWORD : 0x00000001 +PIPE_ACCESS_OUTBOUND: DWORD : 0x00000002 +FILE_FLAG_FIRST_PIPE_INSTANCE: DWORD : 0x00080000 +FILE_FLAG_OVERLAPPED: DWORD : 0x40000000 +PIPE_WAIT: DWORD : 0x00000000 +PIPE_TYPE_BYTE: DWORD : 0x00000000 +PIPE_REJECT_REMOTE_CLIENTS: DWORD : 0x00000008 +PIPE_READMODE_BYTE: DWORD : 0x00000000 -FD_SETSIZE :: 64; +FD_SETSIZE :: 64 -STACK_SIZE_PARAM_IS_A_RESERVATION: DWORD : 0x00010000; +STACK_SIZE_PARAM_IS_A_RESERVATION: DWORD : 0x00010000 -INVALID_SET_FILE_POINTER :: ~DWORD(0); +INVALID_SET_FILE_POINTER :: ~DWORD(0) -HEAP_ZERO_MEMORY: DWORD : 0x00000008; +HEAP_ZERO_MEMORY: DWORD : 0x00000008 -HANDLE_FLAG_INHERIT: DWORD : 0x00000001; -HANDLE_FLAG_PROTECT_FROM_CLOSE :: 0x00000002; +HANDLE_FLAG_INHERIT: DWORD : 0x00000001 +HANDLE_FLAG_PROTECT_FROM_CLOSE :: 0x00000002 -TOKEN_READ: DWORD : 0x20008; +TOKEN_READ: DWORD : 0x20008 -CP_ACP :: 0; // default to ANSI code page -CP_OEMCP :: 1; // default to OEM code page -CP_MACCP :: 2; // default to MAC code page -CP_THREAD_ACP :: 3; // current thread's ANSI code page -CP_SYMBOL :: 42; // SYMBOL translations -CP_UTF7 :: 65000; // UTF-7 translation -CP_UTF8 :: 65001; // UTF-8 translation +CP_ACP :: 0 // default to ANSI code page +CP_OEMCP :: 1 // default to OEM code page +CP_MACCP :: 2 // default to MAC code page +CP_THREAD_ACP :: 3 // current thread's ANSI code page +CP_SYMBOL :: 42 // SYMBOL translations +CP_UTF7 :: 65000 // UTF-7 translation +CP_UTF8 :: 65001 // UTF-8 translation -MB_ERR_INVALID_CHARS :: 8; -WC_ERR_INVALID_CHARS :: 128; +MB_ERR_INVALID_CHARS :: 8 +WC_ERR_INVALID_CHARS :: 128 -MAX_PATH :: 0x00000104; -MAX_PATH_WIDE :: 0x8000; +MAX_PATH :: 0x00000104 +MAX_PATH_WIDE :: 0x8000 -INVALID_FILE_ATTRIBUTES :: -1; +INVALID_FILE_ATTRIBUTES :: -1 -FILE_TYPE_DISK :: 0x0001; -FILE_TYPE_CHAR :: 0x0002; -FILE_TYPE_PIPE :: 0x0003; +FILE_TYPE_DISK :: 0x0001 +FILE_TYPE_CHAR :: 0x0002 +FILE_TYPE_PIPE :: 0x0003 when size_of(uintptr) == 4 { @@ -509,7 +509,7 @@ LPPROGRESS_ROUTINE :: #type proc "stdcall" ( hSourceFile: HANDLE, hDestinationFile: HANDLE, lpData: LPVOID, -) -> DWORD; +) -> DWORD CONDITION_VARIABLE :: struct { ptr: LPVOID, @@ -548,12 +548,12 @@ LUID :: struct { HighPart: LONG, } -PLUID :: ^LUID; +PLUID :: ^LUID -PGUID :: ^GUID; -PCGUID :: ^GUID; -LPGUID :: ^GUID; -LPCGUID :: ^GUID; +PGUID :: ^GUID +PCGUID :: ^GUID +LPGUID :: ^GUID +LPCGUID :: ^GUID WSAPROTOCOLCHAIN :: struct { @@ -607,8 +607,8 @@ FILETIME :: struct { } FILETIME_as_unix_nanoseconds :: proc "contextless" (ft: FILETIME) -> i64 { - t := i64(u64(ft.dwLowDateTime) | u64(ft.dwHighDateTime) << 32); - return (t - 0x019db1ded53e8000) * 100; + t := i64(u64(ft.dwLowDateTime) | u64(ft.dwHighDateTime) << 32) + return (t - 0x019db1ded53e8000) * 100 } OVERLAPPED :: struct { @@ -685,21 +685,21 @@ timeval :: struct { } -EXCEPTION_CONTINUE_SEARCH: LONG : 0; -EXCEPTION_CONTINUE_EXECUTION: LONG : -1; -EXCEPTION_EXECUTE_HANDLER: LONG : 1; +EXCEPTION_CONTINUE_SEARCH: LONG : 0 +EXCEPTION_CONTINUE_EXECUTION: LONG : -1 +EXCEPTION_EXECUTE_HANDLER: LONG : 1 -EXCEPTION_MAXIMUM_PARAMETERS :: 15; +EXCEPTION_MAXIMUM_PARAMETERS :: 15 -EXCEPTION_DATATYPE_MISALIGNMENT :: 0x80000002; -EXCEPTION_BREAKPOINT :: 0x80000003; -EXCEPTION_ACCESS_VIOLATION :: 0xC0000005; -EXCEPTION_ILLEGAL_INSTRUCTION :: 0xC000001D; -EXCEPTION_ARRAY_BOUNDS_EXCEEDED :: 0xC000008C; -EXCEPTION_INT_DIVIDE_BY_ZERO :: 0xC0000094; -EXCEPTION_INT_OVERFLOW :: 0xC0000095; -EXCEPTION_STACK_OVERFLOW :: 0xC00000FD; -STATUS_PRIVILEGED_INSTRUCTION :: 0xC0000096; +EXCEPTION_DATATYPE_MISALIGNMENT :: 0x80000002 +EXCEPTION_BREAKPOINT :: 0x80000003 +EXCEPTION_ACCESS_VIOLATION :: 0xC0000005 +EXCEPTION_ILLEGAL_INSTRUCTION :: 0xC000001D +EXCEPTION_ARRAY_BOUNDS_EXCEEDED :: 0xC000008C +EXCEPTION_INT_DIVIDE_BY_ZERO :: 0xC0000094 +EXCEPTION_INT_OVERFLOW :: 0xC0000095 +EXCEPTION_STACK_OVERFLOW :: 0xC00000FD +STATUS_PRIVILEGED_INSTRUCTION :: 0xC0000096 EXCEPTION_RECORD :: struct { @@ -711,14 +711,14 @@ EXCEPTION_RECORD :: struct { ExceptionInformation: [EXCEPTION_MAXIMUM_PARAMETERS]LPVOID, } -CONTEXT :: struct{}; // TODO(bill) +CONTEXT :: struct{} // TODO(bill) EXCEPTION_POINTERS :: struct { ExceptionRecord: ^EXCEPTION_RECORD, ContextRecord: ^CONTEXT, } -PVECTORED_EXCEPTION_HANDLER :: #type proc "stdcall" (ExceptionInfo: ^EXCEPTION_POINTERS) -> LONG; +PVECTORED_EXCEPTION_HANDLER :: #type proc "stdcall" (ExceptionInfo: ^EXCEPTION_POINTERS) -> LONG CONSOLE_READCONSOLE_CONTROL :: struct { nLength: ULONG, @@ -727,7 +727,7 @@ CONSOLE_READCONSOLE_CONTROL :: struct { dwControlKeyState: ULONG, } -PCONSOLE_READCONSOLE_CONTROL :: ^CONSOLE_READCONSOLE_CONTROL; +PCONSOLE_READCONSOLE_CONTROL :: ^CONSOLE_READCONSOLE_CONTROL BY_HANDLE_FILE_INFORMATION :: struct { dwFileAttributes: DWORD, @@ -742,7 +742,7 @@ BY_HANDLE_FILE_INFORMATION :: struct { nFileIndexLow: DWORD, } -LPBY_HANDLE_FILE_INFORMATION :: ^BY_HANDLE_FILE_INFORMATION; +LPBY_HANDLE_FILE_INFORMATION :: ^BY_HANDLE_FILE_INFORMATION FILE_STANDARD_INFO :: struct { AllocationSize: LARGE_INTEGER, @@ -792,7 +792,7 @@ OSVERSIONINFOEXW :: struct { wSuiteMask: USHORT, wProductType: UCHAR, wReserved: UCHAR, -}; +} // https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-quota_limits // Used in LogonUserExW @@ -803,7 +803,7 @@ PQUOTA_LIMITS :: struct { MaximumWorkingSetSize: SIZE_T, PagefileLimit: SIZE_T, TimeLimit: LARGE_INTEGER, -}; +} Logon32_Type :: enum DWORD { INTERACTIVE = 2, @@ -835,10 +835,10 @@ PROFILEINFOW :: struct { lpServerName: LPWSTR, lpPolicyPath: LPWSTR, hProfile: HANDLE, -}; +} // Used in LookupAccountNameW -SID_NAME_USE :: distinct DWORD; +SID_NAME_USE :: distinct DWORD SID_TYPE :: enum SID_NAME_USE { User = 1, @@ -854,7 +854,7 @@ SID_TYPE :: enum SID_NAME_USE { LogonSession, } -SECURITY_MAX_SID_SIZE :: 68; +SECURITY_MAX_SID_SIZE :: 68 // https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-sid SID :: struct #packed { @@ -862,25 +862,25 @@ SID :: struct #packed { SubAuthorityCount: byte, IdentifierAuthority: SID_IDENTIFIER_AUTHORITY, SubAuthority: [15]DWORD, // Array of DWORDs -}; +} #assert(size_of(SID) == SECURITY_MAX_SID_SIZE); SID_IDENTIFIER_AUTHORITY :: struct #packed { Value: [6]u8, -}; +} // For NetAPI32 // https://github.com/tpn/winsdk-10/blob/master/Include/10.0.14393.0/shared/lmerr.h // https://github.com/tpn/winsdk-10/blob/master/Include/10.0.14393.0/shared/LMaccess.h -UNLEN :: 256; // Maximum user name length -LM20_UNLEN :: 20; // LM 2.0 Maximum user name length +UNLEN :: 256 // Maximum user name length +LM20_UNLEN :: 20 // LM 2.0 Maximum user name length -GNLEN :: UNLEN; // Group name -LM20_GNLEN :: LM20_UNLEN; // LM 2.0 Group name +GNLEN :: UNLEN // Group name +LM20_GNLEN :: LM20_UNLEN // LM 2.0 Group name -PWLEN :: 256; // Maximum password length -LM20_PWLEN :: 14; // LM 2.0 Maximum password length +PWLEN :: 256 // Maximum password length +LM20_PWLEN :: 14 // LM 2.0 Maximum password length USER_PRIV :: enum DWORD { Guest = 0, @@ -904,7 +904,7 @@ USER_INFO_FLAG :: enum DWORD { Workstation_Trust_Account = 12, // 1 << 12: 0x1000, Server_Trust_Account = 13, // 1 << 13: 0x2000, } -USER_INFO_FLAGS :: distinct bit_set[USER_INFO_FLAG]; +USER_INFO_FLAGS :: distinct bit_set[USER_INFO_FLAG] USER_INFO_1 :: struct #packed { name: LPWSTR, @@ -915,12 +915,12 @@ USER_INFO_1 :: struct #packed { comment: LPWSTR, flags: USER_INFO_FLAGS, script_path: LPWSTR, -}; +} #assert(size_of(USER_INFO_1) == 50); LOCALGROUP_MEMBERS_INFO_0 :: struct #packed { sid: ^SID, -}; +} NET_API_STATUS :: enum DWORD { Success = 0, diff --git a/core/sys/windows/util.odin b/core/sys/windows/util.odin index ea395359c..efb37dbc0 100644 --- a/core/sys/windows/util.odin +++ b/core/sys/windows/util.odin @@ -5,54 +5,54 @@ import "core:strings" import "core:sys/win32" LOWORD :: #force_inline proc "contextless" (x: DWORD) -> WORD { - return WORD(x & 0xffff); + return WORD(x & 0xffff) } HIWORD :: #force_inline proc "contextless" (x: DWORD) -> WORD { - return WORD(x >> 16); + return WORD(x >> 16) } utf8_to_utf16 :: proc(s: string, allocator := context.temp_allocator) -> []u16 { if len(s) < 1 { - return nil; + return nil } - b := transmute([]byte)s; - cstr := raw_data(b); - n := MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, cstr, i32(len(s)), nil, 0); + b := transmute([]byte)s + cstr := raw_data(b) + n := MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, cstr, i32(len(s)), nil, 0) if n == 0 { - return nil; + return nil } - text := make([]u16, n+1, allocator); + text := make([]u16, n+1, allocator) - n1 := MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, cstr, i32(len(s)), raw_data(text), n); + n1 := MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, cstr, i32(len(s)), raw_data(text), n) if n1 == 0 { - delete(text, allocator); - return nil; + delete(text, allocator) + return nil } - text[n] = 0; + text[n] = 0 for n >= 1 && text[n-1] == 0 { - n -= 1; + n -= 1 } - return text[:n]; + return text[:n] } utf8_to_wstring :: proc(s: string, allocator := context.temp_allocator) -> wstring { if res := utf8_to_utf16(s, allocator); res != nil { - return &res[0]; + return &res[0] } - return nil; + return nil } wstring_to_utf8 :: proc(s: wstring, N: int, allocator := context.temp_allocator) -> string { if N <= 0 { - return ""; + return "" } - n := WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, s, i32(N), nil, 0, nil, nil); + n := WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, s, i32(N), nil, 0, nil, nil) if n == 0 { - return ""; + return "" } // If N == -1 the call to WideCharToMultiByte assume the wide string is null terminated @@ -60,29 +60,29 @@ wstring_to_utf8 :: proc(s: wstring, N: int, allocator := context.temp_allocator) // also null terminated. // If N != -1 it assumes the wide string is not null terminated and the resulting string // will not be null terminated, we therefore have to force it to be null terminated manually. - text := make([]byte, n+1 if N != -1 else n, allocator); + text := make([]byte, n+1 if N != -1 else n, allocator) - n1 := WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, s, i32(N), raw_data(text), n, nil, nil); + n1 := WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, s, i32(N), raw_data(text), n, nil, nil) if n1 == 0 { - delete(text, allocator); - return ""; + delete(text, allocator) + return "" } for i in 0..<n { if text[i] == 0 { - n = i; - break; + n = i + break } } - return string(text[:n]); + return string(text[:n]) } utf16_to_utf8 :: proc(s: []u16, allocator := context.temp_allocator) -> string { if len(s) == 0 { - return ""; + return "" } - return wstring_to_utf8(raw_data(s), len(s), allocator); + return wstring_to_utf8(raw_data(s), len(s), allocator) } // AdvAPI32, NetAPI32 and UserENV helpers. @@ -94,58 +94,58 @@ allowed_username :: proc(username: string) -> bool { ", /, , [, ], :, |, <, >, +, =, ;, ?, *. Names also cannot include characters in the range 1-31, which are nonprintable. */ - _DISALLOWED :: "\"/ []:|<>+=;?*,"; + _DISALLOWED :: "\"/ []:|<>+=;?*," if len(username) > LM20_UNLEN || len(username) == 0 { - return false; + return false } if username[len(username)-1] == '.' { - return false; + return false } for r in username { if r > 0 && r < 32 { - return false; + return false } } if strings.contains_any(username, _DISALLOWED) { - return false; + return false } - return true; + return true } // Returns .Success on success. _add_user :: proc(servername: string, username: string, password: string) -> (ok: NET_API_STATUS) { - servername_w: wstring; - username_w: []u16; - password_w: []u16; + servername_w: wstring + username_w: []u16 + password_w: []u16 if len(servername) == 0 { // Create account on this computer - servername_w = nil; + servername_w = nil } else { - server := utf8_to_utf16(servername, context.temp_allocator); - servername_w = &server[0]; + server := utf8_to_utf16(servername, context.temp_allocator) + servername_w = &server[0] } if len(username) == 0 || len(username) > LM20_UNLEN { - return .BadUsername; + return .BadUsername } if !allowed_username(username) { - return .BadUsername; + return .BadUsername } if len(password) == 0 || len(password) > LM20_PWLEN { - return .BadPassword; + return .BadPassword } - username_w = utf8_to_utf16(username, context.temp_allocator); - password_w = utf8_to_utf16(password, context.temp_allocator); + username_w = utf8_to_utf16(username, context.temp_allocator) + password_w = utf8_to_utf16(password, context.temp_allocator) - level := DWORD(1); - parm_err: DWORD; + level := DWORD(1) + parm_err: DWORD user_info := USER_INFO_1{ name = &username_w[0], @@ -156,24 +156,24 @@ _add_user :: proc(servername: string, username: string, password: string) -> (ok comment = nil, flags = {.Script, .Normal_Account}, script_path = nil, - }; + } ok = NetUserAdd( servername_w, level, &user_info, &parm_err, - ); + ) - return; + return } get_computer_name_and_account_sid :: proc(username: string) -> (computer_name: string, sid := SID{}, ok: bool) { - username_w := utf8_to_utf16(username, context.temp_allocator); - cbsid: DWORD; - computer_name_size: DWORD; - pe_use := SID_TYPE.User; + username_w := utf8_to_utf16(username, context.temp_allocator) + cbsid: DWORD + computer_name_size: DWORD + pe_use := SID_TYPE.User res := LookupAccountNameW( nil, // Look on this computer first @@ -183,13 +183,13 @@ get_computer_name_and_account_sid :: proc(username: string) -> (computer_name: s nil, &computer_name_size, &pe_use, - ); + ) if computer_name_size == 0 { // User didn't exist, or we'd have a size here. - return "", {}, false; + return "", {}, false } - cname_w := make([]u16, min(computer_name_size, 1), context.temp_allocator); + cname_w := make([]u16, min(computer_name_size, 1), context.temp_allocator) res = LookupAccountNameW( nil, @@ -199,23 +199,23 @@ get_computer_name_and_account_sid :: proc(username: string) -> (computer_name: s &cname_w[0], &computer_name_size, &pe_use, - ); + ) if !res { - return "", {}, false; + return "", {}, false } - computer_name = utf16_to_utf8(cname_w, context.temp_allocator); + computer_name = utf16_to_utf8(cname_w, context.temp_allocator) - ok = true; - return; + ok = true + return } get_sid :: proc(username: string, sid: ^SID) -> (ok: bool) { - username_w := utf8_to_utf16(username, context.temp_allocator); - cbsid: DWORD; - computer_name_size: DWORD; - pe_use := SID_TYPE.User; + username_w := utf8_to_utf16(username, context.temp_allocator) + cbsid: DWORD + computer_name_size: DWORD + pe_use := SID_TYPE.User res := LookupAccountNameW( nil, // Look on this computer first @@ -225,13 +225,13 @@ get_sid :: proc(username: string, sid: ^SID) -> (ok: bool) { nil, &computer_name_size, &pe_use, - ); + ) if computer_name_size == 0 { // User didn't exist, or we'd have a size here. - return false; + return false } - cname_w := make([]u16, min(computer_name_size, 1), context.temp_allocator); + cname_w := make([]u16, min(computer_name_size, 1), context.temp_allocator) res = LookupAccountNameW( nil, @@ -241,97 +241,97 @@ get_sid :: proc(username: string, sid: ^SID) -> (ok: bool) { &cname_w[0], &computer_name_size, &pe_use, - ); + ) if !res { - return false; + return false } - ok = true; - return; + ok = true + return } add_user_to_group :: proc(sid: ^SID, group: string) -> (ok: NET_API_STATUS) { group_member := LOCALGROUP_MEMBERS_INFO_0{ sid = sid, - }; - group_name := utf8_to_utf16(group, context.temp_allocator); + } + group_name := utf8_to_utf16(group, context.temp_allocator) ok = NetLocalGroupAddMembers( nil, &group_name[0], 0, &group_member, 1, - ); - return; + ) + return } add_del_from_group :: proc(sid: ^SID, group: string) -> (ok: NET_API_STATUS) { group_member := LOCALGROUP_MEMBERS_INFO_0{ sid = sid, - }; - group_name := utf8_to_utf16(group, context.temp_allocator); + } + group_name := utf8_to_utf16(group, context.temp_allocator) ok = NetLocalGroupDelMembers( nil, &group_name[0], 0, &group_member, 1, - ); - return; + ) + return } add_user_profile :: proc(username: string) -> (ok: bool, profile_path: string) { - username_w := utf8_to_utf16(username, context.temp_allocator); + username_w := utf8_to_utf16(username, context.temp_allocator) - sid := SID{}; - ok = get_sid(username, &sid); + sid := SID{} + ok = get_sid(username, &sid) if ok == false { - return false, ""; + return false, "" } - sb: wstring; - res := ConvertSidToStringSidW(&sid, &sb); + sb: wstring + res := ConvertSidToStringSidW(&sid, &sb) if res == false { - return false, ""; + return false, "" } - defer win32.local_free(sb); + defer win32.local_free(sb) - pszProfilePath := make([]u16, 257, context.temp_allocator); + pszProfilePath := make([]u16, 257, context.temp_allocator) res2 := CreateProfile( sb, &username_w[0], &pszProfilePath[0], 257, - ); + ) if res2 != 0 { - return false, ""; + return false, "" } - profile_path = wstring_to_utf8(&pszProfilePath[0], 257); + profile_path = wstring_to_utf8(&pszProfilePath[0], 257) - return true, profile_path; + return true, profile_path } delete_user_profile :: proc(username: string) -> (ok: bool) { - sid := SID{}; - ok = get_sid(username, &sid); + sid := SID{} + ok = get_sid(username, &sid) if ok == false { - return false; + return false } - sb: wstring; - res := ConvertSidToStringSidW(&sid, &sb); + sb: wstring + res := ConvertSidToStringSidW(&sid, &sb) if res == false { - return false; + return false } - defer win32.local_free(sb); + defer win32.local_free(sb) res2 := DeleteProfileW( sb, nil, nil, - ); - return bool(res2); + ) + return bool(res2) } add_user :: proc(servername: string, username: string, password: string) -> (ok: bool) { @@ -343,24 +343,24 @@ add_user :: proc(servername: string, username: string, password: string) -> (ok: TODO: SecureZeroMemory the password after use. */ - res := _add_user(servername, username, password); + res := _add_user(servername, username, password) if res != .Success { - return false; + return false } // Grab the SID to add the user to the Users group. - sid: SID; - ok2 := get_sid(username, &sid); + sid: SID + ok2 := get_sid(username, &sid) if ok2 == false { - return false; + return false } - ok3 := add_user_to_group(&sid, "Users"); + ok3 := add_user_to_group(&sid, "Users") if ok3 != .Success { - return false; + return false } - return true; + return true } delete_user :: proc(servername: string, username: string) -> (ok: bool) { @@ -371,24 +371,24 @@ delete_user :: proc(servername: string, username: string) -> (ok: bool) { TODO: Add a bool that governs whether to delete the profile from this wrapper? */ - servername_w: wstring; + servername_w: wstring if len(servername) == 0 { // Delete account on this computer - servername_w = nil; + servername_w = nil } else { - server := utf8_to_utf16(servername, context.temp_allocator); - servername_w = &server[0]; + server := utf8_to_utf16(servername, context.temp_allocator) + servername_w = &server[0] } - username_w := utf8_to_utf16(username); + username_w := utf8_to_utf16(username) res := NetUserDel( servername_w, &username_w[0], - ); + ) if res != .Success { - return false; + return false } - return true; + return true } run_as_user :: proc(username, password, application, commandline: string, pi: ^PROCESS_INFORMATION, wait := true) -> (ok: bool) { @@ -402,17 +402,17 @@ run_as_user :: proc(username, password, application, commandline: string, pi: ^P */ - username_w := utf8_to_utf16(username); - domain_w := utf8_to_utf16("."); - password_w := utf8_to_utf16(password); - app_w := utf8_to_utf16(application); + username_w := utf8_to_utf16(username) + domain_w := utf8_to_utf16(".") + password_w := utf8_to_utf16(password) + app_w := utf8_to_utf16(application) - commandline_w: []u16 = {0}; + commandline_w: []u16 = {0} if len(commandline) > 0 { - commandline_w = utf8_to_utf16(commandline); + commandline_w = utf8_to_utf16(commandline) } - user_token: HANDLE; + user_token: HANDLE ok = bool(LogonUserW( lpszUsername = &username_w[0], @@ -421,16 +421,16 @@ run_as_user :: proc(username, password, application, commandline: string, pi: ^P dwLogonType = .NEW_CREDENTIALS, dwLogonProvider = .WINNT50, phToken = &user_token, - )); + )) if !ok { - return false; + return false // err := GetLastError(); // fmt.printf("GetLastError: %v\n", err); } - si := STARTUPINFO{}; - si.cb = size_of(STARTUPINFO); - pi := pi; + si := STARTUPINFO{} + si.cb = size_of(STARTUPINFO) + pi := pi ok = bool(CreateProcessAsUserW( user_token, @@ -444,15 +444,15 @@ run_as_user :: proc(username, password, application, commandline: string, pi: ^P nil, // current directory: inherit from parent if nil &si, pi, - )); + )) if ok { if wait { - WaitForSingleObject(pi.hProcess, INFINITE); - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); + WaitForSingleObject(pi.hProcess, INFINITE) + CloseHandle(pi.hProcess) + CloseHandle(pi.hThread) } - return true; + return true } else { - return false; + return false } }
\ No newline at end of file diff --git a/core/text/scanner/scanner.odin b/core/text/scanner/scanner.odin index 7c47c2704..bd51b7bf5 100644 --- a/core/text/scanner/scanner.odin +++ b/core/text/scanner/scanner.odin @@ -24,31 +24,31 @@ Position :: struct { // position_is_valid reports where the position is valid position_is_valid :: proc(pos: Position) -> bool { - return pos.line > 0; + return pos.line > 0 } position_to_string :: proc(pos: Position, allocator := context.temp_allocator) -> string { - s := pos.filename; + s := pos.filename if s == "" { - s = "<input>"; + s = "<input>" } - context.allocator = allocator; + context.allocator = allocator if position_is_valid(pos) { - return fmt.aprintf("%s(%d:%d)", s, pos.line, pos.column); + return fmt.aprintf("%s(%d:%d)", s, pos.line, pos.column) } else { - return strings.clone(s); + return strings.clone(s) } } -EOF :: -1; -Ident :: -2; -Int :: -3; -Float :: -4; -Char :: -5; -String :: -6; -Raw_String :: -7; -Comment :: -8; +EOF :: -1 +Ident :: -2 +Int :: -3 +Float :: -4 +Char :: -5 +String :: -6 +Raw_String :: -7 +Comment :: -8 Scan_Flag :: enum u32 { Scan_Idents, @@ -61,17 +61,17 @@ Scan_Flag :: enum u32 { Scan_Comments, Skip_Comments, // if set with .Scan_Comments, comments become white space } -Scan_Flags :: distinct bit_set[Scan_Flag; u32]; +Scan_Flags :: distinct bit_set[Scan_Flag; u32] -Odin_Like_Tokens :: Scan_Flags{.Scan_Idents, .Scan_Ints, .Scan_Floats, .Scan_Chars, .Scan_Strings, .Scan_Raw_Strings, .Scan_Comments, .Skip_Comments}; -C_Like_Tokens :: Scan_Flags{.Scan_Idents, .Scan_Ints, .Scan_C_Int_Prefixes, .Scan_Floats, .Scan_Chars, .Scan_Strings, .Scan_Raw_Strings, .Scan_Comments, .Skip_Comments}; +Odin_Like_Tokens :: Scan_Flags{.Scan_Idents, .Scan_Ints, .Scan_Floats, .Scan_Chars, .Scan_Strings, .Scan_Raw_Strings, .Scan_Comments, .Skip_Comments} +C_Like_Tokens :: Scan_Flags{.Scan_Idents, .Scan_Ints, .Scan_C_Int_Prefixes, .Scan_Floats, .Scan_Chars, .Scan_Strings, .Scan_Raw_Strings, .Scan_Comments, .Skip_Comments} // Only allows for ASCII whitespace -Whitespace :: distinct bit_set['\x00'..<utf8.RUNE_SELF; u128]; +Whitespace :: distinct bit_set['\x00'..<utf8.RUNE_SELF; u128] // Odin_Whitespace is the default value for the Scanner's whitespace field -Odin_Whitespace :: Whitespace{'\t', '\n', '\r', ' '}; -C_Whitespace :: Whitespace{'\t', '\n', '\r', '\v', '\f', ' '}; +Odin_Whitespace :: Whitespace{'\t', '\n', '\r', ' '} +C_Whitespace :: Whitespace{'\t', '\n', '\r', '\v', '\f', ' '} // Scanner allows for the reading of Unicode characters and tokens from a string @@ -121,70 +121,70 @@ Scanner :: struct { // init initializes a scanner with a new source and returns itself. // error_count is set to 0, flags is set to Odin_Like_Tokens, whitespace is set to Odin_Whitespace init :: proc(s: ^Scanner, src: string, filename := "") -> ^Scanner { - s^ = {}; + s^ = {} - s.error_count = 0; - s.src = src; - s.pos.filename = filename; + s.error_count = 0 + s.src = src + s.pos.filename = filename - s.tok_pos = -1; + s.tok_pos = -1 - s.ch = -2; // no char read yet, not an EOF + s.ch = -2 // no char read yet, not an EOF - s.line = 1; + s.line = 1 - s.flags = Odin_Like_Tokens; - s.whitespace = Odin_Whitespace; + s.flags = Odin_Like_Tokens + s.whitespace = Odin_Whitespace - return s; + return s } @(private) advance :: proc(s: ^Scanner) -> rune { if s.src_pos >= len(s.src) { - s.prev_char_len = 0; - return EOF; + s.prev_char_len = 0 + return EOF } - ch, width := rune(s.src[s.src_pos]), 1; + ch, width := rune(s.src[s.src_pos]), 1 if ch >= utf8.RUNE_SELF { - ch, width = utf8.decode_rune_in_string(s.src[s.src_pos:]); + ch, width = utf8.decode_rune_in_string(s.src[s.src_pos:]) if ch == utf8.RUNE_ERROR && width == 1 { - s.src_pos += width; - s.prev_char_len = width; - s.column += 1; - error(s, "invalid UTF-8 encoding"); - return ch; + s.src_pos += width + s.prev_char_len = width + s.column += 1 + error(s, "invalid UTF-8 encoding") + return ch } } - s.src_pos += width; - s.prev_char_len = width; - s.column += 1; + s.src_pos += width + s.prev_char_len = width + s.column += 1 switch ch { case 0: - error(s, "invalid character NUL"); + error(s, "invalid character NUL") case '\n': - s.line += 1; - s.prev_line_len = s.column; - s.column = 0; + s.line += 1 + s.prev_line_len = s.column + s.column = 0 } - return ch; + return ch } // next reads and returns the next Unicode character. It returns EOF at the end of the source. // next does not update the Scanner's pos field. Use 'position(s)' to get the current position next :: proc(s: ^Scanner) -> rune { - s.tok_pos = -1; - s.pos.line = 0; - ch := peek(s); + s.tok_pos = -1 + s.pos.line = 0 + ch := peek(s) if ch != EOF { - s.ch = advance(s); + s.ch = advance(s) } - return ch; + return ch } // peek returns the next Unicode character in the source without advancing the scanner @@ -192,78 +192,78 @@ next :: proc(s: ^Scanner) -> rune { // if n > 0, it call next n times and return the nth Unicode character and then restore the Scanner's state peek :: proc(s: ^Scanner, n := 0) -> (ch: rune) { if s.ch == -2 { - s.ch = advance(s); + s.ch = advance(s) if s.ch == '\ufeff' { // Ignore BOM - s.ch = advance(s); + s.ch = advance(s) } } - ch = s.ch; + ch = s.ch if n > 0 { - prev_s := s^; + prev_s := s^ for in 0..<n { - next(s); + next(s) } - ch = s.ch; - s^ = prev_s; + ch = s.ch + s^ = prev_s } - return ch; + return ch } // peek returns the next token in the source // It returns EOF if the scanner's position is at least the last character of the source // if n > 0, it call next n times and return the nth token and then restore the Scanner's state peek_token :: proc(s: ^Scanner, n := 0) -> (tok: rune) { - assert(n >= 0); - prev_s := s^; + assert(n >= 0) + prev_s := s^ for in 0..<n { - tok = scan(s); + tok = scan(s) } - tok = scan(s); - s^ = prev_s; - return; + tok = scan(s) + s^ = prev_s + return } error :: proc(s: ^Scanner, msg: string) { - s.error_count += 1; + s.error_count += 1 if s.error != nil { - s.error(s, msg); - return; + s.error(s, msg) + return } - p := s.pos; + p := s.pos if !position_is_valid(p) { - p = position(s); + p = position(s) } - s := p.filename; + s := p.filename if s == "" { - s = "<input>"; + s = "<input>" } if position_is_valid(p) { - fmt.eprintf("%s(%d:%d): %s\n", s, p.line, p.column, msg); + fmt.eprintf("%s(%d:%d): %s\n", s, p.line, p.column, msg) } else { - fmt.eprintf("%s: %s\n", s, msg); + fmt.eprintf("%s: %s\n", s, msg) } } errorf :: proc(s: ^Scanner, format: string, args: ..any) { - error(s, fmt.tprintf(format, ..args)); + error(s, fmt.tprintf(format, ..args)) } @(private) is_ident_rune :: proc(s: ^Scanner, ch: rune, i: int) -> bool { if s.is_ident_rune != nil { - return s.is_ident_rune(ch, i); + return s.is_ident_rune(ch, i) } - return ch == '_' || unicode.is_letter(ch) || unicode.is_digit(ch) && i > 0; + return ch == '_' || unicode.is_letter(ch) || unicode.is_digit(ch) && i > 0 } @(private) scan_identifier :: proc(s: ^Scanner) -> rune { - ch := advance(s); + ch := advance(s) for i := 1; is_ident_rune(s, ch, i); i += 1 { - ch = advance(s); + ch = advance(s) } - return ch; + return ch } @(private) lower :: proc(ch: rune) -> rune { return ('a' - 'A') | ch; } @@ -276,239 +276,239 @@ scan_identifier :: proc(s: ^Scanner) -> rune { scan_number :: proc(s: ^Scanner, ch: rune, seen_dot: bool) -> (rune, rune) { lit_name :: proc(prefix: rune) -> string { switch prefix { - case 'b': return "binary literal"; - case 'o': return "octal literal"; - case 'z': return "dozenal literal"; - case 'x': return "hexadecimal literal"; + case 'b': return "binary literal" + case 'o': return "octal literal" + case 'z': return "dozenal literal" + case 'x': return "hexadecimal literal" } - return "decimal literal"; + return "decimal literal" } digits :: proc(s: ^Scanner, ch0: rune, base: int, invalid: ^rune) -> (ch: rune, digsep: int) { - ch = ch0; + ch = ch0 if base <= 10 { - max := rune('0' + base); + max := rune('0' + base) for is_decimal(ch) || ch == '_' { - ds := 1; + ds := 1 if ch == '_' { - ds = 2; + ds = 2 } else if ch >= max && invalid^ == 0 { - invalid^ = ch; + invalid^ = ch } - digsep |= ds; - ch = advance(s); + digsep |= ds + ch = advance(s) } } else { for is_hex(ch) || ch == '_' { - ds := 1; + ds := 1 if ch == '_' { - ds = 2; + ds = 2 } - digsep |= ds; - ch = advance(s); + digsep |= ds + ch = advance(s) } } - return; + return } - ch, seen_dot := ch, seen_dot; + ch, seen_dot := ch, seen_dot - base := 10; - prefix := rune(0); - digsep := 0; - invalid := rune(0); + base := 10 + prefix := rune(0) + digsep := 0 + invalid := rune(0) - tok: rune; - ds: int; + tok: rune + ds: int if !seen_dot { - tok = Int; + tok = Int if ch == '0' { - ch = advance(s); + ch = advance(s) - p := lower(ch); + p := lower(ch) if .Scan_C_Int_Prefixes in s.flags { switch p { case 'b': - ch = advance(s); - base, prefix = 2, 'b'; + ch = advance(s) + base, prefix = 2, 'b' case 'x': - ch = advance(s); - base, prefix = 16, 'x'; + ch = advance(s) + base, prefix = 16, 'x' case: - base, prefix = 8, 'o'; - digsep = 1; // Leading zero + base, prefix = 8, 'o' + digsep = 1 // Leading zero } } else { switch p { case 'b': - ch = advance(s); - base, prefix = 2, 'b'; + ch = advance(s) + base, prefix = 2, 'b' case 'o': - ch = advance(s); - base, prefix = 8, 'o'; + ch = advance(s) + base, prefix = 8, 'o' case 'd': - ch = advance(s); - base, prefix = 10, 'd'; + ch = advance(s) + base, prefix = 10, 'd' case 'z': - ch = advance(s); - base, prefix = 12, 'z'; + ch = advance(s) + base, prefix = 12, 'z' case 'h': - tok = Float; - fallthrough; + tok = Float + fallthrough case 'x': - ch = advance(s); - base, prefix = 16, 'x'; + ch = advance(s) + base, prefix = 16, 'x' case: - digsep = 1; // Leading zero + digsep = 1 // Leading zero } } } - ch, ds = digits(s, ch, base, &invalid); - digsep |= ds; + ch, ds = digits(s, ch, base, &invalid) + digsep |= ds if ch == '.' && .Scan_Floats in s.flags { - ch = advance(s); - seen_dot = true; + ch = advance(s) + seen_dot = true } } if seen_dot { - tok = Float; + tok = Float if prefix != 0 && prefix != 'x' { - errorf(s, "invalid radix point in %s", lit_name(prefix)); + errorf(s, "invalid radix point in %s", lit_name(prefix)) } - ch, ds = digits(s, ch, base, &invalid); - digsep |= ds; + ch, ds = digits(s, ch, base, &invalid) + digsep |= ds } if digsep&1 == 0 { - errorf(s, "%s has no digits", lit_name(prefix)); + errorf(s, "%s has no digits", lit_name(prefix)) } if e := lower(ch); (e == 'e' || e == 'p') && .Scan_Floats in s.flags { switch { case e == 'e' && prefix != 0: - errorf(s, "%q exponent requires decimal mantissa", ch); + errorf(s, "%q exponent requires decimal mantissa", ch) case e == 'p' && prefix != 'x': - errorf(s, "%q exponent requires hexadecimal mantissa", ch); + errorf(s, "%q exponent requires hexadecimal mantissa", ch) } - ch = advance(s); - tok = Float; + ch = advance(s) + tok = Float if ch == '+' || ch == '-' { - ch = advance(s); + ch = advance(s) } - ch, ds = digits(s, ch, 10, nil); - digsep |= ds; + ch, ds = digits(s, ch, 10, nil) + digsep |= ds if ds&1 == 0 { - error(s, "exponent has no digits"); + error(s, "exponent has no digits") } } else if prefix == 'x' && tok == Float { - error(s, "hexadecimal mantissa requires a 'p' exponent"); + error(s, "hexadecimal mantissa requires a 'p' exponent") } if tok == Int && invalid != 0 { - errorf(s, "invalid digit %q in %s", invalid, lit_name(prefix)); + errorf(s, "invalid digit %q in %s", invalid, lit_name(prefix)) } if digsep&2 != 0 { - s.tok_end = s.src_pos - s.prev_char_len; + s.tok_end = s.src_pos - s.prev_char_len } - return tok, ch; + return tok, ch } @(private) scan_string :: proc(s: ^Scanner, quote: rune) -> (n: int) { digit_val :: proc(ch: rune) -> int { switch v := lower(ch); v { - case '0'..='9': return int(v - '0'); - case 'a'..='z': return int(v - 'a'); + case '0'..='9': return int(v - '0') + case 'a'..='z': return int(v - 'a') } - return 16; + return 16 } scan_digits :: proc(s: ^Scanner, ch: rune, base, n: int) -> rune { - ch, n := ch, n; + ch, n := ch, n for n > 0 && digit_val(ch) < base { - ch = advance(s); - n -= 1; + ch = advance(s) + n -= 1 } if n > 0 { - error(s, "invalid char escape"); + error(s, "invalid char escape") } - return ch; + return ch } - ch := advance(s); + ch := advance(s) for ch != quote { if ch == '\n' || ch < 0 { - error(s, "literal no terminated"); - return; + error(s, "literal no terminated") + return } if ch == '\\' { - ch = advance(s); + ch = advance(s) switch ch { case quote, 'a', 'b', 'e', 'f', 'n', 'r', 't', 'v', '\\': - ch = advance(s); - case '0'..='7': ch = scan_digits(s, advance(s), 8, 3); - case 'x': ch = scan_digits(s, advance(s), 16, 2); - case 'u': ch = scan_digits(s, advance(s), 16, 4); - case 'U': ch = scan_digits(s, advance(s), 16, 8); + ch = advance(s) + case '0'..='7': ch = scan_digits(s, advance(s), 8, 3) + case 'x': ch = scan_digits(s, advance(s), 16, 2) + case 'u': ch = scan_digits(s, advance(s), 16, 4) + case 'U': ch = scan_digits(s, advance(s), 16, 8) case: - error(s, "invalid char escape"); + error(s, "invalid char escape") } } else { - ch = advance(s); + ch = advance(s) } - n += 1; + n += 1 } - return; + return } @(private) scan_raw_string :: proc(s: ^Scanner) { - ch := advance(s); + ch := advance(s) for ch != '`' { if ch < 0 { - error(s, "literal not terminated"); - return; + error(s, "literal not terminated") + return } - ch = advance(s); + ch = advance(s) } } @(private) scan_char :: proc(s: ^Scanner) { if scan_string(s, '\'') != 1 { - error(s, "invalid char literal"); + error(s, "invalid char literal") } } @(private) scan_comment :: proc(s: ^Scanner, ch: rune) -> rune { - ch := ch; + ch := ch if ch == '/' { // line comment - ch = advance(s); + ch = advance(s) for ch != '\n' && ch >= 0 { - ch = advance(s); + ch = advance(s) } - return ch; + return ch } // block /**/ comment - ch = advance(s); + ch = advance(s) for { if ch < 0 { - error(s, "comment not terminated"); - break; + error(s, "comment not terminated") + break } - ch0 := ch; - ch = advance(s); + ch0 := ch + ch = advance(s) if ch0 == '*' && ch == '/' { - return advance(s); + return advance(s) } } - return ch; + return ch } // scan reads the next token or Unicode character from source and returns it @@ -516,140 +516,140 @@ scan_comment :: proc(s: ^Scanner, ch: rune) -> rune { // It returns EOF at the end of the source // It reports Scanner errors by calling s.error, if not nil; otherwise it will print the error message to os.stderr scan :: proc(s: ^Scanner) -> (tok: rune) { - ch := peek(s); + ch := peek(s) if ch == EOF { - return ch; + return ch } // reset position - s.tok_pos = -1; - s.pos.line = 0; + s.tok_pos = -1 + s.pos.line = 0 redo: for { for ch < utf8.RUNE_SELF && (ch in s.whitespace) { - ch = advance(s); + ch = advance(s) } - s.tok_pos = s.src_pos - s.prev_char_len; - s.pos.offset = s.tok_pos; + s.tok_pos = s.src_pos - s.prev_char_len + s.pos.offset = s.tok_pos if s.column > 0 { - s.pos.line = s.line; - s.pos.column = s.column; + s.pos.line = s.line + s.pos.column = s.column } else { // previous character was newline - s.pos.line = s.line - 1; - s.pos.column = s.prev_line_len; + s.pos.line = s.line - 1 + s.pos.column = s.prev_line_len } - tok = ch; + tok = ch if is_ident_rune(s, ch, 0) { if .Scan_Idents in s.flags { - tok = Ident; - ch = scan_identifier(s); + tok = Ident + ch = scan_identifier(s) } else { - ch = advance(s); + ch = advance(s) } } else if is_decimal(ch) { if .Scan_Ints in s.flags || .Scan_Floats in s.flags { - tok, ch = scan_number(s, ch, false); + tok, ch = scan_number(s, ch, false) } else { - ch = advance(s); + ch = advance(s) } } else { switch ch { case EOF: - break; + break case '"': if .Scan_Strings in s.flags { - scan_string(s, '"'); - tok = String; + scan_string(s, '"') + tok = String } - ch = advance(s); + ch = advance(s) case '\'': if .Scan_Chars in s.flags { - scan_string(s, '\''); - tok = Char; + scan_string(s, '\'') + tok = Char } - ch = advance(s); + ch = advance(s) case '`': if .Scan_Raw_Strings in s.flags { - scan_raw_string(s); - tok = Raw_String; + scan_raw_string(s) + tok = Raw_String } - ch = advance(s); + ch = advance(s) case '.': - ch = advance(s); + ch = advance(s) if is_decimal(ch) && .Scan_Floats in s.flags { - tok, ch = scan_number(s, ch, true); + tok, ch = scan_number(s, ch, true) } case '/': - ch = advance(s); + ch = advance(s) if (ch == '/' || ch == '*') && .Scan_Comments in s.flags { if .Skip_Comments in s.flags { - s.tok_pos = -1; - ch = scan_comment(s, ch); - continue redo; + s.tok_pos = -1 + ch = scan_comment(s, ch) + continue redo } - ch = scan_comment(s, ch); - tok = Comment; + ch = scan_comment(s, ch) + tok = Comment } case: - ch = advance(s); + ch = advance(s) } } - break redo; + break redo } - s.tok_end = s.src_pos - s.prev_char_len; + s.tok_end = s.src_pos - s.prev_char_len - s.ch = ch; - return tok; + s.ch = ch + return tok } // position returns the position of the character immediately after the character or token returns by the previous call to next or scan // Use the Scanner's position field for the most recently scanned token position position :: proc(s: ^Scanner) -> Position { - pos: Position; - pos.filename = s.pos.filename; - pos.offset = s.src_pos - s.prev_char_len; + pos: Position + pos.filename = s.pos.filename + pos.offset = s.src_pos - s.prev_char_len switch { case s.column > 0: - pos.line = s.line; - pos.column = s.column; + pos.line = s.line + pos.column = s.column case s.prev_line_len > 0: - pos.line = s.line-1; - pos.column = s.prev_line_len; + pos.line = s.line-1 + pos.column = s.prev_line_len case: - pos.line = 1; - pos.column = 1; + pos.line = 1 + pos.column = 1 } - return pos; + return pos } // token_text returns the string of the most recently scanned token token_text :: proc(s: ^Scanner) -> string { if s.tok_pos < 0 { - return ""; + return "" } - return string(s.src[s.tok_pos:s.tok_end]); + return string(s.src[s.tok_pos:s.tok_end]) } // token_string returns a printable string for a token or Unicode character // By default, it uses the context.temp_allocator to produce the string token_string :: proc(tok: rune, allocator := context.temp_allocator) -> string { - context.allocator = allocator; + context.allocator = allocator switch tok { - case EOF: return strings.clone("EOF"); - case Ident: return strings.clone("Ident"); - case Int: return strings.clone("Int"); - case Float: return strings.clone("Float"); - case Char: return strings.clone("Char"); - case String: return strings.clone("String"); - case Raw_String: return strings.clone("Raw_String"); - case Comment: return strings.clone("Comment"); - } - return fmt.aprintf("%q", tok); + case EOF: return strings.clone("EOF") + case Ident: return strings.clone("Ident") + case Int: return strings.clone("Int") + case Float: return strings.clone("Float") + case Char: return strings.clone("Char") + case String: return strings.clone("String") + case Raw_String: return strings.clone("Raw_String") + case Comment: return strings.clone("Comment") + } + return fmt.aprintf("%q", tok) } diff --git a/core/thread/thread.odin b/core/thread/thread.odin index 5450aa860..fe3e2ffb7 100644 --- a/core/thread/thread.odin +++ b/core/thread/thread.odin @@ -4,11 +4,11 @@ import "core:runtime" import "core:mem" import "core:intrinsics" -_ :: intrinsics; +_ :: intrinsics -Thread_Proc :: #type proc(^Thread); +Thread_Proc :: #type proc(^Thread) -MAX_USER_ARGUMENTS :: 8; +MAX_USER_ARGUMENTS :: 8 Thread :: struct { using specific: Thread_Os_Specific, @@ -32,105 +32,105 @@ Thread_Priority :: enum { } create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^Thread { - return _create(procedure, priority); + return _create(procedure, priority) } destroy :: proc(thread: ^Thread) { - _destroy(thread); + _destroy(thread) } start :: proc(thread: ^Thread) { - _start(thread); + _start(thread) } is_done :: proc(thread: ^Thread) -> bool { - return _is_done(thread); + return _is_done(thread) } join :: proc(thread: ^Thread) { - _join(thread); + _join(thread) } join_mulitple :: proc(threads: ..^Thread) { - _join_multiple(..threads); + _join_multiple(..threads) } terminate :: proc(thread: ^Thread, exit_code: int) { - _terminate(thread, exit_code); + _terminate(thread, exit_code) } yield :: proc() { - _yield(); + _yield() } run :: proc(fn: proc(), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) { thread_proc :: proc(t: ^Thread) { - fn := cast(proc())t.data; - fn(); - destroy(t); + fn := cast(proc())t.data + fn() + destroy(t) } - t := create(thread_proc, priority); - t.data = rawptr(fn); - t.init_context = init_context; - start(t); + t := create(thread_proc, priority) + t.data = rawptr(fn) + t.init_context = init_context + start(t) } run_with_data :: proc(data: rawptr, fn: proc(data: rawptr), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) { thread_proc :: proc(t: ^Thread) { - fn := cast(proc(rawptr))t.data; - assert(t.user_index >= 1); - data := t.user_args[0]; - fn(data); - destroy(t); + fn := cast(proc(rawptr))t.data + assert(t.user_index >= 1) + data := t.user_args[0] + fn(data) + destroy(t) } - t := create(thread_proc, priority); - t.data = rawptr(fn); - t.user_index = 1; - t.user_args = data; - t.init_context = init_context; - start(t); + t := create(thread_proc, priority) + t.data = rawptr(fn) + t.user_index = 1 + t.user_args = data + t.init_context = init_context + start(t) } run_with_poly_data :: proc(data: $T, fn: proc(data: T), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) where size_of(T) <= size_of(rawptr) { thread_proc :: proc(t: ^Thread) { - fn := cast(proc(T))t.data; - assert(t.user_index >= 1); - data := (^T)(&t.user_args[0])^; - fn(data); - destroy(t); + fn := cast(proc(T))t.data + assert(t.user_index >= 1) + data := (^T)(&t.user_args[0])^ + fn(data) + destroy(t) } - t := create(thread_proc, priority); - t.data = rawptr(fn); - t.user_index = 1; - data := data; - mem.copy(&t.user_args[0], &data, size_of(data)); - t.init_context = init_context; - start(t); + t := create(thread_proc, priority) + t.data = rawptr(fn) + t.user_index = 1 + data := data + mem.copy(&t.user_args[0], &data, size_of(data)) + t.init_context = init_context + start(t) } run_with_poly_data2 :: proc(arg1: $T1, arg2: $T2, fn: proc(T1, T2), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) where size_of(T1) <= size_of(rawptr), size_of(T2) <= size_of(rawptr) { thread_proc :: proc(t: ^Thread) { - fn := cast(proc(T1, T2))t.data; - assert(t.user_index >= 2); - arg1 := (^T1)(&t.user_args[0])^; - arg2 := (^T2)(&t.user_args[1])^; - fn(arg1, arg2); - destroy(t); + fn := cast(proc(T1, T2))t.data + assert(t.user_index >= 2) + arg1 := (^T1)(&t.user_args[0])^ + arg2 := (^T2)(&t.user_args[1])^ + fn(arg1, arg2) + destroy(t) } - t := create(thread_proc, priority); - t.data = rawptr(fn); - t.user_index = 2; - arg1, arg2 := arg1, arg2; - mem.copy(&t.user_args[0], &arg1, size_of(arg1)); - mem.copy(&t.user_args[1], &arg2, size_of(arg2)); - t.init_context = init_context; - start(t); + t := create(thread_proc, priority) + t.data = rawptr(fn) + t.user_index = 2 + arg1, arg2 := arg1, arg2 + mem.copy(&t.user_args[0], &arg1, size_of(arg1)) + mem.copy(&t.user_args[1], &arg2, size_of(arg2)) + t.init_context = init_context + start(t) } run_with_poly_data3 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, fn: proc(arg1: T1, arg2: T2, arg3: T3), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) @@ -138,55 +138,55 @@ run_with_poly_data3 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, fn: proc(arg1: T1, size_of(T2) <= size_of(rawptr), size_of(T3) <= size_of(rawptr) { thread_proc :: proc(t: ^Thread) { - fn := cast(proc(T1, T2, T3))t.data; - assert(t.user_index >= 3); - arg1 := (^T1)(&t.user_args[0])^; - arg2 := (^T2)(&t.user_args[1])^; - arg3 := (^T3)(&t.user_args[2])^; - fn(arg1, arg2, arg3); - destroy(t); + fn := cast(proc(T1, T2, T3))t.data + assert(t.user_index >= 3) + arg1 := (^T1)(&t.user_args[0])^ + arg2 := (^T2)(&t.user_args[1])^ + arg3 := (^T3)(&t.user_args[2])^ + fn(arg1, arg2, arg3) + destroy(t) } - t := create(thread_proc, priority); - t.data = rawptr(fn); - t.user_index = 3; - arg1, arg2, arg3 := arg1, arg2, arg3; - mem.copy(&t.user_args[0], &arg1, size_of(arg1)); - mem.copy(&t.user_args[1], &arg2, size_of(arg2)); - mem.copy(&t.user_args[2], &arg3, size_of(arg3)); - t.init_context = init_context; - start(t); + t := create(thread_proc, priority) + t.data = rawptr(fn) + t.user_index = 3 + arg1, arg2, arg3 := arg1, arg2, arg3 + mem.copy(&t.user_args[0], &arg1, size_of(arg1)) + mem.copy(&t.user_args[1], &arg2, size_of(arg2)) + mem.copy(&t.user_args[2], &arg3, size_of(arg3)) + t.init_context = init_context + start(t) } run_with_poly_data4 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, arg4: $T4, fn: proc(arg1: T1, arg2: T2, arg3: T3, arg4: T4), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) where size_of(T1) <= size_of(rawptr), size_of(T2) <= size_of(rawptr), size_of(T3) <= size_of(rawptr) { thread_proc :: proc(t: ^Thread) { - fn := cast(proc(T1, T2, T3, T4))t.data; - assert(t.user_index >= 4); - arg1 := (^T1)(&t.user_args[0])^; - arg2 := (^T2)(&t.user_args[1])^; - arg3 := (^T3)(&t.user_args[2])^; - arg4 := (^T4)(&t.user_args[3])^; - fn(arg1, arg2, arg3, arg4); - destroy(t); + fn := cast(proc(T1, T2, T3, T4))t.data + assert(t.user_index >= 4) + arg1 := (^T1)(&t.user_args[0])^ + arg2 := (^T2)(&t.user_args[1])^ + arg3 := (^T3)(&t.user_args[2])^ + arg4 := (^T4)(&t.user_args[3])^ + fn(arg1, arg2, arg3, arg4) + destroy(t) } - t := create(thread_proc, priority); - t.data = rawptr(fn); - t.user_index = 4; - arg1, arg2, arg3, arg4 := arg1, arg2, arg3, arg4; - mem.copy(&t.user_args[0], &arg1, size_of(arg1)); - mem.copy(&t.user_args[1], &arg2, size_of(arg2)); - mem.copy(&t.user_args[2], &arg3, size_of(arg3)); - mem.copy(&t.user_args[3], &arg4, size_of(arg4)); - t.init_context = init_context; - start(t); + t := create(thread_proc, priority) + t.data = rawptr(fn) + t.user_index = 4 + arg1, arg2, arg3, arg4 := arg1, arg2, arg3, arg4 + mem.copy(&t.user_args[0], &arg1, size_of(arg1)) + mem.copy(&t.user_args[1], &arg2, size_of(arg2)) + mem.copy(&t.user_args[2], &arg3, size_of(arg3)) + mem.copy(&t.user_args[3], &arg4, size_of(arg4)) + t.init_context = init_context + start(t) } create_and_start :: proc(fn: Thread_Proc, init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) -> ^Thread { - t := create(fn, priority); - t.init_context = init_context; - start(t); - return t; + t := create(fn, priority) + t.init_context = init_context + start(t) + return t } diff --git a/core/thread/thread_pool.odin b/core/thread/thread_pool.odin index e7cd6d45b..37ee4fa98 100644 --- a/core/thread/thread_pool.odin +++ b/core/thread/thread_pool.odin @@ -11,7 +11,7 @@ Task_Status :: enum i32 { Term, } -Task_Proc :: #type proc(task: ^Task); +Task_Proc :: #type proc(task: ^Task) Task :: struct { procedure: Task_Proc, @@ -19,8 +19,8 @@ Task :: struct { user_index: int, } -Task_Id :: distinct i32; -INVALID_TASK_ID :: Task_Id(-1); +Task_Id :: distinct i32 +INVALID_TASK_ID :: Task_Id(-1) Pool :: struct { @@ -37,115 +37,115 @@ Pool :: struct { pool_init :: proc(pool: ^Pool, thread_count: int, allocator := context.allocator) { worker_thread_internal :: proc(t: ^Thread) { - pool := (^Pool)(t.data); + pool := (^Pool)(t.data) for pool.is_running { - sync.semaphore_wait_for(&pool.sem_available); + sync.semaphore_wait_for(&pool.sem_available) if task, ok := pool_try_and_pop_task(pool); ok { - pool_do_work(pool, &task); + pool_do_work(pool, &task) } } - sync.semaphore_post(&pool.sem_available, 1); + sync.semaphore_post(&pool.sem_available, 1) } - context.allocator = allocator; - pool.allocator = allocator; - pool.tasks = make([dynamic]Task); - pool.threads = make([]^Thread, thread_count); + context.allocator = allocator + pool.allocator = allocator + pool.tasks = make([dynamic]Task) + pool.threads = make([]^Thread, thread_count) - sync.mutex_init(&pool.mutex); - sync.semaphore_init(&pool.sem_available); - pool.is_running = true; + sync.mutex_init(&pool.mutex) + sync.semaphore_init(&pool.sem_available) + pool.is_running = true for _, i in pool.threads { - t := create(worker_thread_internal); - t.user_index = i; - t.data = pool; - pool.threads[i] = t; + t := create(worker_thread_internal) + t.user_index = i + t.data = pool + pool.threads[i] = t } } pool_destroy :: proc(pool: ^Pool) { - delete(pool.tasks); + delete(pool.tasks) for thread in &pool.threads { - destroy(thread); + destroy(thread) } - delete(pool.threads, pool.allocator); + delete(pool.threads, pool.allocator) - sync.mutex_destroy(&pool.mutex); - sync.semaphore_destroy(&pool.sem_available); + sync.mutex_destroy(&pool.mutex) + sync.semaphore_destroy(&pool.sem_available) } pool_start :: proc(pool: ^Pool) { for t in pool.threads { - start(t); + start(t) } } pool_join :: proc(pool: ^Pool) { - pool.is_running = false; + pool.is_running = false - sync.semaphore_post(&pool.sem_available, len(pool.threads)); + sync.semaphore_post(&pool.sem_available, len(pool.threads)) - yield(); + yield() for t in pool.threads { - join(t); + join(t) } } pool_add_task :: proc(pool: ^Pool, procedure: Task_Proc, data: rawptr, user_index: int = 0) { - sync.mutex_lock(&pool.mutex); - defer sync.mutex_unlock(&pool.mutex); + sync.mutex_lock(&pool.mutex) + defer sync.mutex_unlock(&pool.mutex) - task: Task; - task.procedure = procedure; - task.data = data; - task.user_index = user_index; + task: Task + task.procedure = procedure + task.data = data + task.user_index = user_index - append(&pool.tasks, task); - sync.semaphore_post(&pool.sem_available, 1); + append(&pool.tasks, task) + sync.semaphore_post(&pool.sem_available, 1) } pool_try_and_pop_task :: proc(pool: ^Pool) -> (task: Task, got_task: bool = false) { if sync.mutex_try_lock(&pool.mutex) { if len(pool.tasks) != 0 { - intrinsics.atomic_add(&pool.processing_task_count, 1); - task = pop_front(&pool.tasks); - got_task = true; + intrinsics.atomic_add(&pool.processing_task_count, 1) + task = pop_front(&pool.tasks) + got_task = true } - sync.mutex_unlock(&pool.mutex); + sync.mutex_unlock(&pool.mutex) } - return; + return } pool_do_work :: proc(pool: ^Pool, task: ^Task) { - task.procedure(task); - intrinsics.atomic_sub(&pool.processing_task_count, 1); + task.procedure(task) + intrinsics.atomic_sub(&pool.processing_task_count, 1) } pool_wait_and_process :: proc(pool: ^Pool) { for len(pool.tasks) != 0 || intrinsics.atomic_load(&pool.processing_task_count) != 0 { if task, ok := pool_try_and_pop_task(pool); ok { - pool_do_work(pool, &task); + pool_do_work(pool, &task) } // Safety kick if len(pool.tasks) != 0 && intrinsics.atomic_load(&pool.processing_task_count) == 0 { - sync.mutex_lock(&pool.mutex); - sync.semaphore_post(&pool.sem_available, len(pool.tasks)); - sync.mutex_unlock(&pool.mutex); + sync.mutex_lock(&pool.mutex) + sync.semaphore_post(&pool.sem_available, len(pool.tasks)) + sync.mutex_unlock(&pool.mutex) } - yield(); + yield() } - pool_join(pool); + pool_join(pool) } diff --git a/core/thread/thread_windows.odin b/core/thread/thread_windows.odin index 1dfa0c0b6..580ba9543 100644 --- a/core/thread/thread_windows.odin +++ b/core/thread/thread_windows.odin @@ -16,103 +16,103 @@ _thread_priority_map := [Thread_Priority]i32{ .Normal = 0, .Low = -2, .High = +2, -}; +} _create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^Thread { - win32_thread_id: win32.DWORD; + win32_thread_id: win32.DWORD __windows_thread_entry_proc :: proc "stdcall" (t_: rawptr) -> win32.DWORD { - t := (^Thread)(t_); - context = t.init_context.? or_else runtime.default_context(); + t := (^Thread)(t_) + context = t.init_context.? or_else runtime.default_context() - t.procedure(t); + t.procedure(t) if t.init_context == nil { if context.temp_allocator.data == &runtime.global_default_temp_allocator_data { - runtime.default_temp_allocator_destroy(auto_cast context.temp_allocator.data); + runtime.default_temp_allocator_destroy(auto_cast context.temp_allocator.data) } } - sync.atomic_store(&t.done, true); - return 0; + sync.atomic_store(&t.done, true) + return 0 } - thread := new(Thread); + thread := new(Thread) if thread == nil { - return nil; + return nil } - thread.creation_allocator = context.allocator; + thread.creation_allocator = context.allocator - win32_thread := win32.CreateThread(nil, 0, __windows_thread_entry_proc, thread, win32.CREATE_SUSPENDED, &win32_thread_id); + win32_thread := win32.CreateThread(nil, 0, __windows_thread_entry_proc, thread, win32.CREATE_SUSPENDED, &win32_thread_id) if win32_thread == nil { - free(thread, thread.creation_allocator); - return nil; + free(thread, thread.creation_allocator) + return nil } - thread.procedure = procedure; - thread.win32_thread = win32_thread; - thread.win32_thread_id = win32_thread_id; - thread.init_context = context; + thread.procedure = procedure + thread.win32_thread = win32_thread + thread.win32_thread_id = win32_thread_id + thread.init_context = context - ok := win32.SetThreadPriority(win32_thread, _thread_priority_map[priority]); - assert(ok == true); + ok := win32.SetThreadPriority(win32_thread, _thread_priority_map[priority]) + assert(ok == true) - return thread; + return thread } _start :: proc(thread: ^Thread) { - win32.ResumeThread(thread.win32_thread); + win32.ResumeThread(thread.win32_thread) } _is_done :: proc(using thread: ^Thread) -> bool { // NOTE(tetra, 2019-10-31): Apparently using wait_for_single_object and // checking if it didn't time out immediately, is not good enough, // so we do it this way instead. - return sync.atomic_load(&done); + return sync.atomic_load(&done) } _join :: proc(using thread: ^Thread) { if win32_thread != win32.INVALID_HANDLE { - win32.WaitForSingleObject(win32_thread, win32.INFINITE); - win32.CloseHandle(win32_thread); - win32_thread = win32.INVALID_HANDLE; + win32.WaitForSingleObject(win32_thread, win32.INFINITE) + win32.CloseHandle(win32_thread) + win32_thread = win32.INVALID_HANDLE } } _join_multiple :: proc(threads: ..^Thread) { - MAXIMUM_WAIT_OBJECTS :: 64; + MAXIMUM_WAIT_OBJECTS :: 64 - handles: [MAXIMUM_WAIT_OBJECTS]win32.HANDLE; + handles: [MAXIMUM_WAIT_OBJECTS]win32.HANDLE for k := 0; k < len(threads); k += MAXIMUM_WAIT_OBJECTS { - count := min(len(threads) - k, MAXIMUM_WAIT_OBJECTS); - j := 0; + count := min(len(threads) - k, MAXIMUM_WAIT_OBJECTS) + j := 0 for i in 0..<count { - handle := threads[i+k].win32_thread; + handle := threads[i+k].win32_thread if handle != win32.INVALID_HANDLE { - handles[j] = handle; - j += 1; + handles[j] = handle + j += 1 } } - win32.WaitForMultipleObjects(u32(j), &handles[0], true, win32.INFINITE); + win32.WaitForMultipleObjects(u32(j), &handles[0], true, win32.INFINITE) } for t in threads { - win32.CloseHandle(t.win32_thread); - t.win32_thread = win32.INVALID_HANDLE; + win32.CloseHandle(t.win32_thread) + t.win32_thread = win32.INVALID_HANDLE } } _destroy :: proc(thread: ^Thread) { - _join(thread); - free(thread, thread.creation_allocator); + _join(thread) + free(thread, thread.creation_allocator) } _terminate :: proc(using thread : ^Thread, exit_code: int) { - win32.TerminateThread(win32_thread, u32(exit_code)); + win32.TerminateThread(win32_thread, u32(exit_code)) } _yield :: proc() { - win32.SwitchToThread(); + win32.SwitchToThread() } diff --git a/core/time/perf.odin b/core/time/perf.odin index f370bedbf..5146ad543 100644 --- a/core/time/perf.odin +++ b/core/time/perf.odin @@ -5,35 +5,35 @@ Tick :: struct { } tick_now :: proc() -> Tick { - return _tick_now(); + return _tick_now() } tick_diff :: proc(start, end: Tick) -> Duration { - d := end._nsec - start._nsec; - return Duration(d); + d := end._nsec - start._nsec + return Duration(d) } tick_lap_time :: proc(prev: ^Tick) -> Duration { - d: Duration; - t := tick_now(); + d: Duration + t := tick_now() if prev._nsec != 0 { - d = tick_diff(prev^, t); + d = tick_diff(prev^, t) } - prev^ = t; - return d; + prev^ = t + return d } tick_since :: proc(start: Tick) -> Duration { - return tick_diff(start, tick_now()); + return tick_diff(start, tick_now()) } @(deferred_in_out=_tick_duration_end) SCOPED_TICK_DURATION :: proc(d: ^Duration) -> Tick { - return tick_now(); + return tick_now() } _tick_duration_end :: proc(d: ^Duration, t: Tick) { - d^ = tick_since(t); + d^ = tick_since(t) } diff --git a/core/time/time.odin b/core/time/time.odin index 620a08c31..1fcb20cf8 100644 --- a/core/time/time.odin +++ b/core/time/time.odin @@ -2,17 +2,17 @@ package time import "core:intrinsics" -Duration :: distinct i64; +Duration :: distinct i64 -Nanosecond :: Duration(1); -Microsecond :: 1000 * Nanosecond; -Millisecond :: 1000 * Microsecond; -Second :: 1000 * Millisecond; -Minute :: 60 * Second; -Hour :: 60 * Minute; +Nanosecond :: Duration(1) +Microsecond :: 1000 * Nanosecond +Millisecond :: 1000 * Microsecond +Second :: 1000 * Millisecond +Minute :: 60 * Second +Hour :: 60 * Minute -MIN_DURATION :: Duration(-1 << 63); -MAX_DURATION :: Duration(1<<63 - 1); +MIN_DURATION :: Duration(-1 << 63) +MAX_DURATION :: Duration(1<<63 - 1) Time :: struct { _nsec: i64, // zero is 1970-01-01 00:00:00 @@ -44,257 +44,257 @@ Weekday :: enum int { } diff :: proc(start, end: Time) -> Duration { - d := end._nsec - start._nsec; - return Duration(d); + d := end._nsec - start._nsec + return Duration(d) } since :: proc(start: Time) -> Duration { - return diff(start, now()); + return diff(start, now()) } duration_nanoseconds :: proc(d: Duration) -> i64 { - return i64(d); + return i64(d) } duration_microseconds :: proc(d: Duration) -> f64 { - return duration_seconds(d) * 1e6; + return duration_seconds(d) * 1e6 } duration_milliseconds :: proc(d: Duration) -> f64 { - return duration_seconds(d) * 1e3; + return duration_seconds(d) * 1e3 } duration_seconds :: proc(d: Duration) -> f64 { - sec := d / Second; - nsec := d % Second; - return f64(sec) + f64(nsec)/1e9; + sec := d / Second + nsec := d % Second + return f64(sec) + f64(nsec)/1e9 } duration_minutes :: proc(d: Duration) -> f64 { - min := d / Minute; - nsec := d % Minute; - return f64(min) + f64(nsec)/(60*1e9); + min := d / Minute + nsec := d % Minute + return f64(min) + f64(nsec)/(60*1e9) } duration_hours :: proc(d: Duration) -> f64 { - hour := d / Hour; - nsec := d % Hour; - return f64(hour) + f64(nsec)/(60*60*1e9); + hour := d / Hour + nsec := d % Hour + return f64(hour) + f64(nsec)/(60*60*1e9) } _less_than_half :: #force_inline proc(x, y: Duration) -> bool { - return u64(x)+u64(x) < u64(y); + return u64(x)+u64(x) < u64(y) } duration_round :: proc(d, m: Duration) -> Duration { if m <= 0 { - return d; + return d } - r := d % m; + r := d % m if d < 0 { - r = -r; + r = -r if _less_than_half(r, m) { - return d + r; + return d + r } if d1 := d-m+r; d1 < d { - return d1; + return d1 } - return MIN_DURATION; + return MIN_DURATION } if _less_than_half(r, m) { - return d - r; + return d - r } if d1 := d+m-r; d1 > d { - return d1; + return d1 } - return MAX_DURATION; + return MAX_DURATION } duration_truncate :: proc(d, m: Duration) -> Duration { - return d if m <= 0 else d - d%m; + return d if m <= 0 else d - d%m } date :: proc(t: Time) -> (year: int, month: Month, day: int) { - year, month, day, _ = _abs_date(_time_abs(t), true); - return; + year, month, day, _ = _abs_date(_time_abs(t), true) + return } year :: proc(t: Time) -> (year: int) { - year, _, _, _ = _date(t, true); - return; + year, _, _, _ = _date(t, true) + return } month :: proc(t: Time) -> (month: Month) { - _, month, _, _ = _date(t, true); - return; + _, month, _, _ = _date(t, true) + return } day :: proc(t: Time) -> (day: int) { - _, _, day, _ = _date(t, true); - return; + _, _, day, _ = _date(t, true) + return } clock :: proc(t: Time) -> (hour, min, sec: int) { - sec = int(_time_abs(t) % SECONDS_PER_DAY); - hour = sec / SECONDS_PER_HOUR; - sec -= hour * SECONDS_PER_HOUR; - min = sec / SECONDS_PER_MINUTE; - sec -= min * SECONDS_PER_MINUTE; - return; + sec = int(_time_abs(t) % SECONDS_PER_DAY) + hour = sec / SECONDS_PER_HOUR + sec -= hour * SECONDS_PER_HOUR + min = sec / SECONDS_PER_MINUTE + sec -= min * SECONDS_PER_MINUTE + return } read_cycle_counter :: proc() -> u64 { - return u64(intrinsics.read_cycle_counter()); + return u64(intrinsics.read_cycle_counter()) } unix :: proc(sec: i64, nsec: i64) -> Time { - sec, nsec := sec, nsec; + sec, nsec := sec, nsec if nsec < 0 || nsec >= 1e9 { - n := nsec / 1e9; - sec += n; - nsec -= n * 1e9; + n := nsec / 1e9 + sec += n + nsec -= n * 1e9 if nsec < 0 { - nsec += 1e9; - sec -= 1; + nsec += 1e9 + sec -= 1 } } - return Time{(sec*1e9 + nsec) + UNIX_TO_INTERNAL}; + return Time{(sec*1e9 + nsec) + UNIX_TO_INTERNAL} } time_to_unix :: proc(t: Time) -> i64 { - return t._nsec/1e9; + return t._nsec/1e9 } time_to_unix_nano :: proc(t: Time) -> i64 { - return t._nsec; + return t._nsec } time_add :: proc(t: Time, d: Duration) -> Time { - return Time{t._nsec + i64(d)}; + return Time{t._nsec + i64(d)} } -ABSOLUTE_ZERO_YEAR :: i64(-292277022399); // Day is chosen so that 2001-01-01 is Monday in the calculations -ABSOLUTE_TO_INTERNAL :: i64(-9223371966579724800); // i64((ABSOLUTE_ZERO_YEAR - 1) * 365.2425 * SECONDS_PER_DAY); -INTERNAL_TO_ABSOLUTE :: -ABSOLUTE_TO_INTERNAL; +ABSOLUTE_ZERO_YEAR :: i64(-292277022399) // Day is chosen so that 2001-01-01 is Monday in the calculations +ABSOLUTE_TO_INTERNAL :: i64(-9223371966579724800) // i64((ABSOLUTE_ZERO_YEAR - 1) * 365.2425 * SECONDS_PER_DAY); +INTERNAL_TO_ABSOLUTE :: -ABSOLUTE_TO_INTERNAL -UNIX_TO_INTERNAL :: i64((1969*365 + 1969/4 - 1969/100 + 1969/400) * SECONDS_PER_DAY); -INTERNAL_TO_UNIX :: -UNIX_TO_INTERNAL; +UNIX_TO_INTERNAL :: i64((1969*365 + 1969/4 - 1969/100 + 1969/400) * SECONDS_PER_DAY) +INTERNAL_TO_UNIX :: -UNIX_TO_INTERNAL -WALL_TO_INTERNAL :: i64((1884*365 + 1884/4 - 1884/100 + 1884/400) * SECONDS_PER_DAY); -INTERNAL_TO_WALL :: -WALL_TO_INTERNAL; +WALL_TO_INTERNAL :: i64((1884*365 + 1884/4 - 1884/100 + 1884/400) * SECONDS_PER_DAY) +INTERNAL_TO_WALL :: -WALL_TO_INTERNAL -UNIX_TO_ABSOLUTE :: UNIX_TO_INTERNAL + INTERNAL_TO_ABSOLUTE; -ABSOLUTE_TO_UNIX :: -UNIX_TO_ABSOLUTE; +UNIX_TO_ABSOLUTE :: UNIX_TO_INTERNAL + INTERNAL_TO_ABSOLUTE +ABSOLUTE_TO_UNIX :: -UNIX_TO_ABSOLUTE _is_leap_year :: proc(year: int) -> bool { - return year%4 == 0 && (year%100 != 0 || year%400 == 0); + return year%4 == 0 && (year%100 != 0 || year%400 == 0) } _date :: proc(t: Time, full: bool) -> (year: int, month: Month, day: int, yday: int) { - year, month, day, yday = _abs_date(_time_abs(t), full); - return; + year, month, day, yday = _abs_date(_time_abs(t), full) + return } _time_abs :: proc(t: Time) -> u64 { - return u64(t._nsec/1e9 + UNIX_TO_ABSOLUTE); + return u64(t._nsec/1e9 + UNIX_TO_ABSOLUTE) } _abs_date :: proc(abs: u64, full: bool) -> (year: int, month: Month, day: int, yday: int) { - d := abs / SECONDS_PER_DAY; + d := abs / SECONDS_PER_DAY // 400 year cycles - n := d / DAYS_PER_400_YEARS; - y := 400 * n; - d -= DAYS_PER_400_YEARS * n; + n := d / DAYS_PER_400_YEARS + y := 400 * n + d -= DAYS_PER_400_YEARS * n // Cut-off 100 year cycles - n = d / DAYS_PER_100_YEARS; - n -= n >> 2; - y += 100 * n; - d -= DAYS_PER_100_YEARS * n; + n = d / DAYS_PER_100_YEARS + n -= n >> 2 + y += 100 * n + d -= DAYS_PER_100_YEARS * n // Cut-off 4 year cycles - n = d / DAYS_PER_4_YEARS; - y += 4 * n; - d -= DAYS_PER_4_YEARS * n; + n = d / DAYS_PER_4_YEARS + y += 4 * n + d -= DAYS_PER_4_YEARS * n - n = d / 365; - n -= n >> 2; - y += n; - d -= 365 * n; + n = d / 365 + n -= n >> 2 + y += n + d -= 365 * n - year = int(i64(y) + ABSOLUTE_ZERO_YEAR); - yday = int(d); + year = int(i64(y) + ABSOLUTE_ZERO_YEAR) + yday = int(d) if !full { - return; + return } - day = yday; + day = yday if _is_leap_year(year) { switch { case day > 31+29-1: - day -= 1; + day -= 1 case day == 31+29-1: - month = .February; - day = 29; - return; + month = .February + day = 29 + return } } - month = Month(day / 31); - end := int(days_before[int(month)+1]); - begin: int; + month = Month(day / 31) + end := int(days_before[int(month)+1]) + begin: int if day >= end { - (^int)(&month)^ += 1; - begin = end; + (^int)(&month)^ += 1 + begin = end } else { - begin = int(days_before[month]); + begin = int(days_before[month]) } - (^int)(&month)^ += 1; // January is 1 - day = day - begin + 1; - return; + (^int)(&month)^ += 1 // January is 1 + day = day - begin + 1 + return } datetime_to_time :: proc(year, month, day, hour, minute, second: int, nsec := int(0)) -> (t: Time, ok: bool) { divmod :: proc(year: int, divisor: int) -> (div: int, mod: int) { - assert(divisor > 0); - div = int(year / divisor); - mod = year % divisor; - return; + assert(divisor > 0) + div = int(year / divisor) + mod = year % divisor + return } - ok = true; + ok = true - _y := year - 1970; - _m := month - 1; - _d := day - 1; + _y := year - 1970 + _m := month - 1 + _d := day - 1 if month < 1 || month > 12 { - _m %= 12; ok = false; + _m %= 12; ok = false } if day < 1 || day > 31 { - _d %= 31; ok = false; + _d %= 31; ok = false } - s := i64(0); - div, mod := divmod(_y, 400); - days := div * DAYS_PER_400_YEARS; + s := i64(0) + div, mod := divmod(_y, 400) + days := div * DAYS_PER_400_YEARS - div, mod = divmod(mod, 100); - days += div * DAYS_PER_100_YEARS; + div, mod = divmod(mod, 100) + days += div * DAYS_PER_100_YEARS - div, mod = divmod(mod, 4); - days += (div * DAYS_PER_4_YEARS) + (mod * 365); + div, mod = divmod(mod, 4) + days += (div * DAYS_PER_4_YEARS) + (mod * 365) - days += int(days_before[_m]) + _d; + days += int(days_before[_m]) + _d - s += i64(days) * SECONDS_PER_DAY; - s += i64(hour) * SECONDS_PER_HOUR; - s += i64(minute) * SECONDS_PER_MINUTE; - s += i64(second); + s += i64(days) * SECONDS_PER_DAY + s += i64(hour) * SECONDS_PER_HOUR + s += i64(minute) * SECONDS_PER_MINUTE + s += i64(second) - t._nsec = (s * 1e9) + i64(nsec); + t._nsec = (s * 1e9) + i64(nsec) - return; + return } days_before := [?]i32{ @@ -311,13 +311,13 @@ days_before := [?]i32{ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31, 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30, 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31, -}; +} -SECONDS_PER_MINUTE :: 60; -SECONDS_PER_HOUR :: 60 * SECONDS_PER_MINUTE; -SECONDS_PER_DAY :: 24 * SECONDS_PER_HOUR; -SECONDS_PER_WEEK :: 7 * SECONDS_PER_DAY; -DAYS_PER_400_YEARS :: 365*400 + 97; -DAYS_PER_100_YEARS :: 365*100 + 24; -DAYS_PER_4_YEARS :: 365*4 + 1; +SECONDS_PER_MINUTE :: 60 +SECONDS_PER_HOUR :: 60 * SECONDS_PER_MINUTE +SECONDS_PER_DAY :: 24 * SECONDS_PER_HOUR +SECONDS_PER_WEEK :: 7 * SECONDS_PER_DAY +DAYS_PER_400_YEARS :: 365*400 + 97 +DAYS_PER_100_YEARS :: 365*100 + 24 +DAYS_PER_4_YEARS :: 365*4 + 1 diff --git a/core/time/time_windows.odin b/core/time/time_windows.odin index 2a9a84178..18a8c4046 100644 --- a/core/time/time_windows.odin +++ b/core/time/time_windows.odin @@ -2,36 +2,36 @@ package time import win32 "core:sys/windows" -IS_SUPPORTED :: true; +IS_SUPPORTED :: true now :: proc() -> Time { - file_time: win32.FILETIME; - win32.GetSystemTimeAsFileTime(&file_time); - ns := win32.FILETIME_as_unix_nanoseconds(file_time); - return Time{_nsec=ns}; + file_time: win32.FILETIME + win32.GetSystemTimeAsFileTime(&file_time) + ns := win32.FILETIME_as_unix_nanoseconds(file_time) + return Time{_nsec=ns} } sleep :: proc(d: Duration) { - win32.Sleep(win32.DWORD(d/Millisecond)); + win32.Sleep(win32.DWORD(d/Millisecond)) } _tick_now :: proc() -> Tick { mul_div_u64 :: proc(val, num, den: i64) -> i64 { - q := val / den; - r := val % den; - return q * num + r * num / den; + q := val / den + r := val % den + return q * num + r * num / den } - @thread_local qpc_frequency: win32.LARGE_INTEGER; + @thread_local qpc_frequency: win32.LARGE_INTEGER if qpc_frequency == 0 { - win32.QueryPerformanceFrequency(&qpc_frequency); + win32.QueryPerformanceFrequency(&qpc_frequency) } - now: win32.LARGE_INTEGER; - win32.QueryPerformanceCounter(&now); + now: win32.LARGE_INTEGER + win32.QueryPerformanceCounter(&now) - _nsec := mul_div_u64(i64(now), 1e9, i64(qpc_frequency)); - return Tick{_nsec = _nsec}; + _nsec := mul_div_u64(i64(now), 1e9, i64(qpc_frequency)) + return Tick{_nsec = _nsec} } diff --git a/core/unicode/letter.odin b/core/unicode/letter.odin index b498e4272..891c90bf3 100644 --- a/core/unicode/letter.odin +++ b/core/unicode/letter.odin @@ -1,195 +1,195 @@ package unicode -MAX_RUNE :: '\U00010fff'; // Maximum valid unicode code point -REPLACEMENT_CHAR :: '\ufffd'; // Represented an invalid code point -MAX_ASCII :: '\u007f'; // Maximum ASCII value -MAX_LATIN1 :: '\u00ff'; // Maximum Latin-1 value +MAX_RUNE :: '\U00010fff' // Maximum valid unicode code point +REPLACEMENT_CHAR :: '\ufffd' // Represented an invalid code point +MAX_ASCII :: '\u007f' // Maximum ASCII value +MAX_LATIN1 :: '\u00ff' // Maximum Latin-1 value binary_search :: proc(c: i32, table: []i32, length, stride: int) -> int { - n := length; - t := 0; + n := length + t := 0 for n > 1 { - m := n / 2; - p := t + m*stride; + m := n / 2 + p := t + m*stride if c >= table[p] { - t = p; - n = n-m; + t = p + n = n-m } else { - n = m; + n = m } } if n != 0 && c >= table[t] { - return t; + return t } - return -1; + return -1 } to_lower :: proc(r: rune) -> rune { - c := i32(r); - p := binary_search(c, to_lower_ranges[:], len(to_lower_ranges)/3, 3); + c := i32(r) + p := binary_search(c, to_lower_ranges[:], len(to_lower_ranges)/3, 3) if p >= 0 && to_lower_ranges[p] <= c && c <= to_lower_ranges[p+1] { - return rune(c + to_lower_ranges[p+2] - 500); + return rune(c + to_lower_ranges[p+2] - 500) } - p = binary_search(c, to_lower_singlets[:], len(to_lower_singlets)/2, 2); + p = binary_search(c, to_lower_singlets[:], len(to_lower_singlets)/2, 2) if p >= 0 && c == to_lower_singlets[p] { - return rune(c + to_lower_singlets[p+1] - 500); + return rune(c + to_lower_singlets[p+1] - 500) } - return rune(c); + return rune(c) } to_upper :: proc(r: rune) -> rune { - c := i32(r); - p := binary_search(c, to_upper_ranges[:], len(to_upper_ranges)/3, 3); + c := i32(r) + p := binary_search(c, to_upper_ranges[:], len(to_upper_ranges)/3, 3) if p >= 0 && to_upper_ranges[p] <= c && c <= to_upper_ranges[p+1] { - return rune(c + to_upper_ranges[p+2] - 500); + return rune(c + to_upper_ranges[p+2] - 500) } - p = binary_search(c, to_upper_singlets[:], len(to_upper_singlets)/2, 2); + p = binary_search(c, to_upper_singlets[:], len(to_upper_singlets)/2, 2) if p >= 0 && c == to_upper_singlets[p] { - return rune(c + to_upper_singlets[p+1] - 500); + return rune(c + to_upper_singlets[p+1] - 500) } - return rune(c); + return rune(c) } to_title :: proc(r: rune) -> rune { - c := i32(r); - p := binary_search(c, to_upper_singlets[:], len(to_title_singlets)/2, 2); + c := i32(r) + p := binary_search(c, to_upper_singlets[:], len(to_title_singlets)/2, 2) if p >= 0 && c == to_upper_singlets[p] { - return rune(c + to_title_singlets[p+1] - 500); + return rune(c + to_title_singlets[p+1] - 500) } - return rune(c); + return rune(c) } is_lower :: proc(r: rune) -> bool { if r <= MAX_ASCII { - return u32(r)-'a' < 26; + return u32(r)-'a' < 26 } - c := i32(r); - p := binary_search(c, to_upper_ranges[:], len(to_upper_ranges)/3, 3); + c := i32(r) + p := binary_search(c, to_upper_ranges[:], len(to_upper_ranges)/3, 3) if p >= 0 && to_upper_ranges[p] <= c && c <= to_upper_ranges[p+1] { - return true; + return true } - p = binary_search(c, to_upper_singlets[:], len(to_upper_singlets)/2, 2); + p = binary_search(c, to_upper_singlets[:], len(to_upper_singlets)/2, 2) if p >= 0 && c == to_upper_singlets[p] { - return true; + return true } - return false; + return false } is_upper :: proc(r: rune) -> bool { if r <= MAX_ASCII { - return u32(r)-'A' < 26; + return u32(r)-'A' < 26 } - c := i32(r); - p := binary_search(c, to_lower_ranges[:], len(to_lower_ranges)/3, 3); + c := i32(r) + p := binary_search(c, to_lower_ranges[:], len(to_lower_ranges)/3, 3) if p >= 0 && to_lower_ranges[p] <= c && c <= to_lower_ranges[p+1] { - return true; + return true } - p = binary_search(c, to_lower_singlets[:], len(to_lower_singlets)/2, 2); + p = binary_search(c, to_lower_singlets[:], len(to_lower_singlets)/2, 2) if p >= 0 && c == to_lower_singlets[p] { - return true; + return true } - return false; + return false } -is_alpha :: is_letter; +is_alpha :: is_letter is_letter :: proc(r: rune) -> bool { if u32(r) <= MAX_LATIN1 { - return char_properties[u8(r)]&pLmask != 0; + return char_properties[u8(r)]&pLmask != 0 } if is_upper(r) || is_lower(r) { - return true; + return true } - c := i32(r); - p := binary_search(c, alpha_ranges[:], len(alpha_ranges)/2, 2); + c := i32(r) + p := binary_search(c, alpha_ranges[:], len(alpha_ranges)/2, 2) if p >= 0 && alpha_ranges[p] <= c && c <= alpha_ranges[p+1] { - return true; + return true } - p = binary_search(c, alpha_singlets[:], len(alpha_singlets), 1); + p = binary_search(c, alpha_singlets[:], len(alpha_singlets), 1) if p >= 0 && c == alpha_singlets[p] { - return true; + return true } - return false; + return false } is_title :: proc(r: rune) -> bool { - return is_upper(r) && is_lower(r); + return is_upper(r) && is_lower(r) } is_digit :: proc(r: rune) -> bool { if r <= MAX_LATIN1 { - return '0' <= r && r <= '9'; + return '0' <= r && r <= '9' } - return false; + return false } -is_white_space :: is_space; +is_white_space :: is_space is_space :: proc(r: rune) -> bool { if u32(r) <= MAX_LATIN1 { switch r { case '\t', '\n', '\v', '\f', '\r', ' ', 0x85, 0xa0: - return true; + return true } - return false; + return false } - c := i32(r); - p := binary_search(c, space_ranges[:], len(space_ranges)/2, 2); + c := i32(r) + p := binary_search(c, space_ranges[:], len(space_ranges)/2, 2) if p >= 0 && space_ranges[p] <= c && c <= space_ranges[p+1] { - return true; + return true } - return false; + return false } is_combining :: proc(r: rune) -> bool { - c := i32(r); + c := i32(r) return c >= 0x0300 && (c <= 0x036f || (c >= 0x1ab0 && c <= 0x1aff) || (c >= 0x1dc0 && c <= 0x1dff) || (c >= 0x20d0 && c <= 0x20ff) || - (c >= 0xfe20 && c <= 0xfe2f)); + (c >= 0xfe20 && c <= 0xfe2f)) } is_graphic :: proc(r: rune) -> bool { if u32(r) <= MAX_LATIN1 { - return char_properties[u8(r)]&pg != 0; + return char_properties[u8(r)]&pg != 0 } - return false; + return false } is_print :: proc(r: rune) -> bool { if u32(r) <= MAX_LATIN1 { - return char_properties[u8(r)]&pp != 0; + return char_properties[u8(r)]&pp != 0 } - return false; + return false } is_control :: proc(r: rune) -> bool { if u32(r) <= MAX_LATIN1 { - return char_properties[u8(r)]&pC != 0; + return char_properties[u8(r)]&pC != 0 } - return false; + return false } is_number :: proc(r: rune) -> bool { if u32(r) <= MAX_LATIN1 { - return char_properties[u8(r)]&pN != 0; + return char_properties[u8(r)]&pN != 0 } - return false; + return false } is_punct :: proc(r: rune) -> bool { if u32(r) <= MAX_LATIN1 { - return char_properties[u8(r)]&pP != 0; + return char_properties[u8(r)]&pP != 0 } - return false; + return false } is_symbol :: proc(r: rune) -> bool { if u32(r) <= MAX_LATIN1 { - return char_properties[u8(r)]&pS != 0; + return char_properties[u8(r)]&pS != 0 } - return false; + return false } diff --git a/core/unicode/tables.odin b/core/unicode/tables.odin index ff4793402..f43827413 100644 --- a/core/unicode/tables.odin +++ b/core/unicode/tables.odin @@ -1,16 +1,16 @@ package unicode -@(private) pC :: 1<<0; // a control character. -@(private) pP :: 1<<1; // a punctuation character. -@(private) pN :: 1<<2; // a numeral. -@(private) pS :: 1<<3; // a symbolic character. -@(private) pZ :: 1<<4; // a spacing character. -@(private) pLu :: 1<<5; // an upper-case letter. -@(private) pLl :: 1<<6; // a lower-case letter. -@(private) pp :: 1<<7; // a printable character according to Go's definition. -@(private) pg :: pp | pZ; // a graphical character according to the Unicode definition. -@(private) pLo :: pLl | pLu; // a letter that is neither upper nor lower case. -@(private) pLmask :: pLo; +@(private) pC :: 1<<0 // a control character. +@(private) pP :: 1<<1 // a punctuation character. +@(private) pN :: 1<<2 // a numeral. +@(private) pS :: 1<<3 // a symbolic character. +@(private) pZ :: 1<<4 // a spacing character. +@(private) pLu :: 1<<5 // an upper-case letter. +@(private) pLl :: 1<<6 // a lower-case letter. +@(private) pp :: 1<<7 // a printable character according to Go's definition. +@(private) pg :: pp | pZ // a graphical character according to the Unicode definition. +@(private) pLo :: pLl | pLu // a letter that is neither upper nor lower case. +@(private) pLmask :: pLo char_properties := [MAX_LATIN1+1]u8{ 0x00 = pC, // '\x00' @@ -269,7 +269,7 @@ char_properties := [MAX_LATIN1+1]u8{ 0xFD = pLl | pp, // 'ý' 0xFE = pLl | pp, // 'þ' 0xFF = pLl | pp, // 'ÿ' -}; +} alpha_ranges := [?]i32{ @@ -425,7 +425,7 @@ alpha_ranges := [?]i32{ 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, -}; +} alpha_singlets := [?]i32{ 0x00aa, @@ -460,7 +460,7 @@ alpha_singlets := [?]i32{ 0x2128, 0xfb3e, 0xfe74, -}; +} space_ranges := [?]i32{ 0x0009, 0x000d, // tab and newline @@ -475,7 +475,7 @@ space_ranges := [?]i32{ 0x205f, 0x205f, // medium mathematical space 0x3000, 0x3000, // ideographic space 0xfeff, 0xfeff, -}; +} unicode_spaces := [?]i32{ 0x0009, // tab @@ -492,7 +492,7 @@ unicode_spaces := [?]i32{ 0x205f, // medium mathematical space 0x3000, // ideographic space 0xfeff, // unknown -}; +} to_upper_ranges := [?]i32{ 0x0061, 0x007a, 468, // a-z A-Z @@ -530,7 +530,7 @@ to_upper_ranges := [?]i32{ 0x2170, 0x217f, 484, 0x24d0, 0x24e9, 474, 0xff41, 0xff5a, 468, -}; +} to_upper_singlets := [?]i32{ 0x00ff, 621, @@ -873,7 +873,7 @@ to_upper_singlets := [?]i32{ 0x1fc3, 509, 0x1fe5, 507, 0x1ff3, 509, -}; +} to_lower_ranges := [?]i32{ 0x0041, 0x005a, 532, // A-Z a-z @@ -912,7 +912,7 @@ to_lower_ranges := [?]i32{ 0x2160, 0x216f, 516, // - - 0x24b6, 0x24cf, 526, // - - 0xff21, 0xff3a, 532, // - - -}; +} to_lower_singlets := [?]i32{ 0x0100, 501, @@ -1248,7 +1248,7 @@ to_lower_singlets := [?]i32{ 0x1fcc, 491, 0x1fec, 493, 0x1ffc, 491, -}; +} to_title_singlets := [?]i32{ 0x01c4, 501, @@ -1259,4 +1259,4 @@ to_title_singlets := [?]i32{ 0x01cc, 499, 0x01f1, 501, 0x01f3, 499, -}; +} diff --git a/core/unicode/utf16/utf16.odin b/core/unicode/utf16/utf16.odin index 4c76956cc..27edf088d 100644 --- a/core/unicode/utf16/utf16.odin +++ b/core/unicode/utf16/utf16.odin @@ -1,82 +1,82 @@ package utf16 -REPLACEMENT_CHAR :: '\ufffd'; -MAX_RUNE :: '\U0010ffff'; +REPLACEMENT_CHAR :: '\ufffd' +MAX_RUNE :: '\U0010ffff' -_surr1 :: 0xd800; -_surr2 :: 0xdc00; -_surr3 :: 0xe000; -_surr_self :: 0x10000; +_surr1 :: 0xd800 +_surr2 :: 0xdc00 +_surr3 :: 0xe000 +_surr_self :: 0x10000 is_surrogate :: proc(r: rune) -> bool { - return _surr1 <= r && r < _surr3; + return _surr1 <= r && r < _surr3 } decode_surrogate_pair :: proc(r1, r2: rune) -> rune { if _surr1 <= r1 && r1 < _surr2 && _surr2 <= r2 && r2 < _surr3 { - return (r1-_surr1)<<10 | (r2 - _surr2) + _surr_self; + return (r1-_surr1)<<10 | (r2 - _surr2) + _surr_self } - return REPLACEMENT_CHAR; + return REPLACEMENT_CHAR } encode_surrogate_pair :: proc(c: rune) -> (r1, r2: rune) { - r := c; + r := c if r < _surr_self || r > MAX_RUNE { - return REPLACEMENT_CHAR, REPLACEMENT_CHAR; + return REPLACEMENT_CHAR, REPLACEMENT_CHAR } - r -= _surr_self; - return _surr1 + (r>>10)&0x3ff, _surr2 + r&0x3ff; + r -= _surr_self + return _surr1 + (r>>10)&0x3ff, _surr2 + r&0x3ff } encode :: proc(d: []u16, s: []rune) -> int { - n, m := 0, len(d); + n, m := 0, len(d) loop: for r in s { switch r { case 0..<_surr1, _surr3 ..< _surr_self: if m+1 < n { break loop; } - d[n] = u16(r); - n += 1; + d[n] = u16(r) + n += 1 case _surr_self ..= MAX_RUNE: if m+2 < n { break loop; } - r1, r2 := encode_surrogate_pair(r); - d[n] = u16(r1); - d[n+1] = u16(r2); - n += 2; + r1, r2 := encode_surrogate_pair(r) + d[n] = u16(r1) + d[n+1] = u16(r2) + n += 2 case: if m+1 < n { break loop; } - d[n] = u16(REPLACEMENT_CHAR); - n += 1; + d[n] = u16(REPLACEMENT_CHAR) + n += 1 } } - return n; + return n } encode_string :: proc(d: []u16, s: string) -> int { - n, m := 0, len(d); + n, m := 0, len(d) loop: for r in s { switch r { case 0..<_surr1, _surr3 ..< _surr_self: if m+1 < n { break loop; } - d[n] = u16(r); - n += 1; + d[n] = u16(r) + n += 1 case _surr_self ..= MAX_RUNE: if m+2 < n { break loop; } - r1, r2 := encode_surrogate_pair(r); - d[n] = u16(r1); - d[n+1] = u16(r2); - n += 2; + r1, r2 := encode_surrogate_pair(r) + d[n] = u16(r1) + d[n+1] = u16(r2) + n += 2 case: if m+1 < n { break loop; } - d[n] = u16(REPLACEMENT_CHAR); - n += 1; + d[n] = u16(REPLACEMENT_CHAR) + n += 1 } } - return n; + return n } diff --git a/core/unicode/utf8/utf8.odin b/core/unicode/utf8/utf8.odin index 61f54e07f..ba9bb6de0 100644 --- a/core/unicode/utf8/utf8.odin +++ b/core/unicode/utf8/utf8.odin @@ -1,36 +1,36 @@ package utf8 -RUNE_ERROR :: '\ufffd'; -RUNE_SELF :: 0x80; -RUNE_BOM :: 0xfeff; -RUNE_EOF :: ~rune(0); -MAX_RUNE :: '\U0010ffff'; -UTF_MAX :: 4; - -SURROGATE_MIN :: 0xd800; -SURROGATE_MAX :: 0xdfff; - -T1 :: 0b0000_0000; -TX :: 0b1000_0000; -T2 :: 0b1100_0000; -T3 :: 0b1110_0000; -T4 :: 0b1111_0000; -T5 :: 0b1111_1000; - -MASKX :: 0b0011_1111; -MASK2 :: 0b0001_1111; -MASK3 :: 0b0000_1111; -MASK4 :: 0b0000_0111; - -RUNE1_MAX :: 1<<7 - 1; -RUNE2_MAX :: 1<<11 - 1; -RUNE3_MAX :: 1<<16 - 1; +RUNE_ERROR :: '\ufffd' +RUNE_SELF :: 0x80 +RUNE_BOM :: 0xfeff +RUNE_EOF :: ~rune(0) +MAX_RUNE :: '\U0010ffff' +UTF_MAX :: 4 + +SURROGATE_MIN :: 0xd800 +SURROGATE_MAX :: 0xdfff + +T1 :: 0b0000_0000 +TX :: 0b1000_0000 +T2 :: 0b1100_0000 +T3 :: 0b1110_0000 +T4 :: 0b1111_0000 +T5 :: 0b1111_1000 + +MASKX :: 0b0011_1111 +MASK2 :: 0b0001_1111 +MASK3 :: 0b0000_1111 +MASK4 :: 0b0000_0111 + +RUNE1_MAX :: 1<<7 - 1 +RUNE2_MAX :: 1<<11 - 1 +RUNE3_MAX :: 1<<16 - 1 // The default lowest and highest continuation byte. -LOCB :: 0b1000_0000; -HICB :: 0b1011_1111; +LOCB :: 0b1000_0000 +HICB :: 0b1011_1111 -Accept_Range :: struct {lo, hi: u8}; +Accept_Range :: struct {lo, hi: u8} accept_ranges := [5]Accept_Range{ {0x80, 0xbf}, @@ -38,7 +38,7 @@ accept_ranges := [5]Accept_Range{ {0x80, 0x9f}, {0x90, 0xbf}, {0x80, 0x8f}, -}; +} accept_sizes := [256]u8{ 0x00..0x7f = 0xf0, @@ -52,329 +52,329 @@ accept_sizes := [256]u8{ 0xf1..0xf3 = 0x04, 0xf4 = 0x44, 0xf5..0xff = 0xf1, -}; +} encode_rune :: proc(c: rune) -> ([4]u8, int) { - r := c; + r := c - buf: [4]u8; - i := u32(r); - mask :: u8(0x3f); + buf: [4]u8 + i := u32(r) + mask :: u8(0x3f) if i <= 1<<7-1 { - buf[0] = u8(r); - return buf, 1; + buf[0] = u8(r) + return buf, 1 } if i <= 1<<11-1 { - buf[0] = 0xc0 | u8(r>>6); - buf[1] = 0x80 | u8(r) & mask; - return buf, 2; + buf[0] = 0xc0 | u8(r>>6) + buf[1] = 0x80 | u8(r) & mask + return buf, 2 } // Invalid or Surrogate range if i > 0x0010ffff || (0xd800 <= i && i <= 0xdfff) { - r = 0xfffd; + r = 0xfffd } if i <= 1<<16-1 { - buf[0] = 0xe0 | u8(r>>12); - buf[1] = 0x80 | u8(r>>6) & mask; - buf[2] = 0x80 | u8(r) & mask; - return buf, 3; + buf[0] = 0xe0 | u8(r>>12) + buf[1] = 0x80 | u8(r>>6) & mask + buf[2] = 0x80 | u8(r) & mask + return buf, 3 } - buf[0] = 0xf0 | u8(r>>18); - buf[1] = 0x80 | u8(r>>12) & mask; - buf[2] = 0x80 | u8(r>>6) & mask; - buf[3] = 0x80 | u8(r) & mask; - return buf, 4; + buf[0] = 0xf0 | u8(r>>18) + buf[1] = 0x80 | u8(r>>12) & mask + buf[2] = 0x80 | u8(r>>6) & mask + buf[3] = 0x80 | u8(r) & mask + return buf, 4 } decode_rune_in_string :: #force_inline proc(s: string) -> (rune, int) { - return decode_rune(transmute([]u8)s); + return decode_rune(transmute([]u8)s) } decode_rune :: proc(s: []u8) -> (rune, int) { - n := len(s); + n := len(s) if n < 1 { - return RUNE_ERROR, 0; + return RUNE_ERROR, 0 } - s0 := s[0]; - x := accept_sizes[s0]; + s0 := s[0] + x := accept_sizes[s0] if x >= 0xF0 { - mask := rune(x) << 31 >> 31; // NOTE(bill): Create 0x0000 or 0xffff. - return rune(s[0])&~mask | RUNE_ERROR&mask, 1; + mask := rune(x) << 31 >> 31 // NOTE(bill): Create 0x0000 or 0xffff. + return rune(s[0])&~mask | RUNE_ERROR&mask, 1 } - sz := x & 7; - accept := accept_ranges[x>>4]; + sz := x & 7 + accept := accept_ranges[x>>4] if n < int(sz) { - return RUNE_ERROR, 1; + return RUNE_ERROR, 1 } - b1 := s[1]; + b1 := s[1] if b1 < accept.lo || accept.hi < b1 { - return RUNE_ERROR, 1; + return RUNE_ERROR, 1 } if sz == 2 { - return rune(s0&MASK2)<<6 | rune(b1&MASKX), 2; + return rune(s0&MASK2)<<6 | rune(b1&MASKX), 2 } - b2 := s[2]; + b2 := s[2] if b2 < LOCB || HICB < b2 { - return RUNE_ERROR, 1; + return RUNE_ERROR, 1 } if sz == 3 { - return rune(s0&MASK3)<<12 | rune(b1&MASKX)<<6 | rune(b2&MASKX), 3; + return rune(s0&MASK3)<<12 | rune(b1&MASKX)<<6 | rune(b2&MASKX), 3 } - b3 := s[3]; + b3 := s[3] if b3 < LOCB || HICB < b3 { - return RUNE_ERROR, 1; + return RUNE_ERROR, 1 } - return rune(s0&MASK4)<<18 | rune(b1&MASKX)<<12 | rune(b2&MASKX)<<6 | rune(b3&MASKX), 4; + return rune(s0&MASK4)<<18 | rune(b1&MASKX)<<12 | rune(b2&MASKX)<<6 | rune(b3&MASKX), 4 } string_to_runes :: proc(s: string, allocator := context.allocator) -> (runes: []rune) { - n := rune_count_in_string(s); + n := rune_count_in_string(s) - runes = make([]rune, n, allocator); - i := 0; + runes = make([]rune, n, allocator) + i := 0 for r in s { - runes[i] = r; - i += 1; + runes[i] = r + i += 1 } - return; + return } runes_to_string :: proc(runes: []rune, allocator := context.allocator) -> string { - byte_count := 0; + byte_count := 0 for r in runes { - _, w := encode_rune(r); - byte_count += w; + _, w := encode_rune(r) + byte_count += w } - bytes := make([]byte, byte_count, allocator); - offset := 0; + bytes := make([]byte, byte_count, allocator) + offset := 0 for r in runes { - b, w := encode_rune(r); - copy(bytes[offset:], b[:w]); - offset += w; + b, w := encode_rune(r) + copy(bytes[offset:], b[:w]) + offset += w } - return string(bytes); + return string(bytes) } decode_last_rune_in_string :: #force_inline proc(s: string) -> (rune, int) { - return decode_last_rune(transmute([]u8)s); + return decode_last_rune(transmute([]u8)s) } decode_last_rune :: proc(s: []u8) -> (rune, int) { - r: rune; - size: int; - start, end, limit: int; + r: rune + size: int + start, end, limit: int - end = len(s); + end = len(s) if end == 0 { - return RUNE_ERROR, 0; + return RUNE_ERROR, 0 } - start = end-1; - r = rune(s[start]); + start = end-1 + r = rune(s[start]) if r < RUNE_SELF { - return r, 1; + return r, 1 } - limit = max(end - UTF_MAX, 0); + limit = max(end - UTF_MAX, 0) for start-=1; start >= limit; start-=1 { if rune_start(s[start]) { - break; + break } } - start = max(start, 0); - r, size = decode_rune(s[start:end]); + start = max(start, 0) + r, size = decode_rune(s[start:end]) if start+size != end { - return RUNE_ERROR, 1; + return RUNE_ERROR, 1 } - return r, size; + return r, size } rune_at_pos :: proc(s: string, pos: int) -> rune { if pos < 0 { - return RUNE_ERROR; + return RUNE_ERROR } - i := 0; + i := 0 for r in s { if i == pos { - return r; + return r } - i += 1; + i += 1 } - return RUNE_ERROR; + return RUNE_ERROR } rune_string_at_pos :: proc(s: string, pos: int) -> string { if pos < 0 { - return ""; + return "" } - i := 0; + i := 0 for c, offset in s { if i == pos { - w := rune_size(c); - return s[offset:][:w]; + w := rune_size(c) + return s[offset:][:w] } - i += 1; + i += 1 } - return ""; + return "" } rune_at :: proc(s: string, byte_index: int) -> rune { - r, _ := decode_rune_in_string(s[byte_index:]); - return r; + r, _ := decode_rune_in_string(s[byte_index:]) + return r } // Returns the byte position of rune at position pos in s with an optional start byte position. // Returns -1 if it runs out of the string. rune_offset :: proc(s: string, pos: int, start: int = 0) -> int { if pos < 0 { - return -1; + return -1 } - i := 0; + i := 0 for _, offset in s[start:] { if i == pos { - return offset+start; + return offset+start } - i += 1; + i += 1 } - return -1; + return -1 } valid_rune :: proc(r: rune) -> bool { if r < 0 { - return false; + return false } else if SURROGATE_MIN <= r && r <= SURROGATE_MAX { - return false; + return false } else if r > MAX_RUNE { - return false; + return false } - return true; + return true } valid_string :: proc(s: string) -> bool { - n := len(s); + n := len(s) for i := 0; i < n; { - si := s[i]; + si := s[i] if si < RUNE_SELF { // ascii - i += 1; - continue; + i += 1 + continue } - x := accept_sizes[si]; + x := accept_sizes[si] if x == 0xf1 { - return false; + return false } - size := int(x & 7); + size := int(x & 7) if i+size > n { - return false; + return false } - ar := accept_ranges[x>>4]; + ar := accept_ranges[x>>4] if b := s[i+1]; b < ar.lo || ar.hi < b { - return false; + return false } else if size == 2 { // Okay } else if c := s[i+2]; c < 0x80 || 0xbf < c { - return false; + return false } else if size == 3 { // Okay } else if d := s[i+3]; b < 0x80 || 0xbf < d { - return false; + return false } - i += size; + i += size } - return true; + return true } rune_start :: #force_inline proc(b: u8) -> bool { - return b&0xc0 != 0x80; + return b&0xc0 != 0x80 } rune_count_in_string :: #force_inline proc(s: string) -> int { - return rune_count(transmute([]u8)s); + return rune_count(transmute([]u8)s) } rune_count :: proc(s: []u8) -> int { - count := 0; - n := len(s); + count := 0 + n := len(s) for i := 0; i < n; { - defer count += 1; - si := s[i]; + defer count += 1 + si := s[i] if si < RUNE_SELF { // ascii - i += 1; - continue; + i += 1 + continue } - x := accept_sizes[si]; + x := accept_sizes[si] if x == 0xf1 { - i += 1; - continue; + i += 1 + continue } - size := int(x & 7); + size := int(x & 7) if i+size > n { - i += 1; - continue; + i += 1 + continue } - ar := accept_ranges[x>>4]; + ar := accept_ranges[x>>4] if b := s[i+1]; b < ar.lo || ar.hi < b { - size = 1; + size = 1 } else if size == 2 { // Okay } else if c := s[i+2]; c < 0x80 || 0xbf < c { - size = 1; + size = 1 } else if size == 3 { // Okay } else if d := s[i+3]; d < 0x80 || 0xbf < d { - size = 1; + size = 1 } - i += size; + i += size } - return count; + return count } rune_size :: proc(r: rune) -> int { switch { - case r < 0: return -1; - case r <= 1<<7 - 1: return 1; - case r <= 1<<11 - 1: return 2; - case SURROGATE_MIN <= r && r <= SURROGATE_MAX: return -1; - case r <= 1<<16 - 1: return 3; - case r <= MAX_RUNE: return 4; - } - return -1; + case r < 0: return -1 + case r <= 1<<7 - 1: return 1 + case r <= 1<<11 - 1: return 2 + case SURROGATE_MIN <= r && r <= SURROGATE_MAX: return -1 + case r <= 1<<16 - 1: return 3 + case r <= MAX_RUNE: return 4 + } + return -1 } // full_rune reports if the bytes in b begin with a full utf-8 encoding of a rune or not // An invalid encoding is considered a full rune since it will convert as an error rune of width 1 (RUNE_ERROR) full_rune :: proc(b: []byte) -> bool { - n := len(b); + n := len(b) if n == 0 { - return false; + return false } - x := _first[b[0]]; + x := _first[b[0]] if n >= int(x & 7) { - return true; + return true } - accept := accept_ranges[x>>4]; + accept := accept_ranges[x>>4] if n > 1 && (b[1] < accept.lo || accept.hi < b[1]) { - return true; + return true } else if n > 2 && (b[2] < LOCB || HICB < b[2]) { - return true; + return true } - return false; + return false } // full_rune_in_string reports if the bytes in s begin with a full utf-8 encoding of a rune or not // An invalid encoding is considered a full rune since it will convert as an error rune of width 1 (RUNE_ERROR) full_rune_in_string :: proc(s: string) -> bool { - return full_rune(transmute([]byte)s); + return full_rune(transmute([]byte)s) } @@ -390,4 +390,4 @@ _first := [256]u8{ 0xf1..0xf3 = 0x04, // accept 0, size 4 0xf4 = 0x44, // accept 4, size 4 0xf5..0xff = 0xf1, // ascii, size 1 -}; +} |