mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-13 01:21:38 -07:00
Merge branch 'master' into odin-global-constants-as-enums
This commit is contained in:
+22
-10
@@ -17,13 +17,16 @@ jobs:
|
||||
run: ./odin report
|
||||
timeout-minutes: 1
|
||||
- name: Odin check
|
||||
run: ./odin check examples/demo/demo.odin -vet
|
||||
run: ./odin check examples/demo -vet
|
||||
timeout-minutes: 10
|
||||
- name: Odin run
|
||||
run: ./odin run examples/demo/demo.odin
|
||||
run: ./odin run examples/demo
|
||||
timeout-minutes: 10
|
||||
- name: Odin run -debug
|
||||
run: ./odin run examples/demo/demo.odin -debug
|
||||
run: ./odin run examples/demo -debug
|
||||
timeout-minutes: 10
|
||||
- name: Odin check examples/all
|
||||
run: ./odin check examples/all -strict-style
|
||||
timeout-minutes: 10
|
||||
- name: Core library tests
|
||||
run: |
|
||||
@@ -54,13 +57,16 @@ jobs:
|
||||
run: ./odin report
|
||||
timeout-minutes: 1
|
||||
- name: Odin check
|
||||
run: ./odin check examples/demo/demo.odin -vet
|
||||
run: ./odin check examples/demo -vet
|
||||
timeout-minutes: 10
|
||||
- name: Odin run
|
||||
run: ./odin run examples/demo/demo.odin
|
||||
run: ./odin run examples/demo
|
||||
timeout-minutes: 10
|
||||
- name: Odin run -debug
|
||||
run: ./odin run examples/demo/demo.odin -debug
|
||||
run: ./odin run examples/demo -debug
|
||||
timeout-minutes: 10
|
||||
- name: Odin check examples/all
|
||||
run: ./odin check examples/all -strict-style
|
||||
timeout-minutes: 10
|
||||
- name: Core library tests
|
||||
run: |
|
||||
@@ -73,7 +79,7 @@ jobs:
|
||||
make
|
||||
timeout-minutes: 10
|
||||
build_windows:
|
||||
runs-on: windows-latest
|
||||
runs-on: windows-2019
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: build Odin
|
||||
@@ -91,19 +97,25 @@ jobs:
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
||||
odin check examples/demo/demo.odin -vet
|
||||
odin check examples/demo -vet
|
||||
timeout-minutes: 10
|
||||
- name: Odin run
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
||||
odin run examples/demo/demo.odin
|
||||
odin run examples/demo
|
||||
timeout-minutes: 10
|
||||
- name: Odin run -debug
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
||||
odin run examples/demo/demo.odin -debug
|
||||
odin run examples/demo -debug
|
||||
timeout-minutes: 10
|
||||
- name: Odin check examples/all
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
||||
odin check examples/all -strict-style
|
||||
timeout-minutes: 10
|
||||
- name: Core library tests
|
||||
shell: cmd
|
||||
|
||||
@@ -7,7 +7,7 @@ on:
|
||||
|
||||
jobs:
|
||||
build_windows:
|
||||
runs-on: windows-latest
|
||||
runs-on: windows-2019
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: build Odin
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# For macOS
|
||||
.DS_Store
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
|
||||
@@ -8,22 +8,34 @@ CC=clang
|
||||
OS=$(shell uname)
|
||||
|
||||
ifeq ($(OS), Darwin)
|
||||
|
||||
ARCH=$(shell uname -m)
|
||||
LLVM_CONFIG=llvm-config
|
||||
LLVM_CONFIG=
|
||||
|
||||
# LLVM Version Setting
|
||||
LLVM_VERSION_PATTERN="^11\."
|
||||
LLVM_VERSION="11"
|
||||
# allow for arm only llvm's with version 13
|
||||
ifeq ($(ARCH), arm64)
|
||||
LLVM_VERSION="13"
|
||||
LLVM_VERSION_PATTERN="^13"
|
||||
endif
|
||||
LLVM_VERSIONS = "13.%.%"
|
||||
else
|
||||
# allow for x86 / amd64 all llvm versions begining from 11
|
||||
LLVM_VERSIONS = "13.%.%" "12.0.1" "11.1.0"
|
||||
endif
|
||||
|
||||
ifneq ($(shell llvm-config --version | grep $(LLVM_VERSION_PATTERN)),)
|
||||
LLVM_VERSION_PATTERN_SEPERATOR = )|(
|
||||
LLVM_VERSION_PATTERNS_ESCAPED_DOT = $(subst .,\.,$(LLVM_VERSIONS))
|
||||
LLVM_VERSION_PATTERNS_REPLACE_PERCENT = $(subst %,.*,$(LLVM_VERSION_PATTERNS_ESCAPED_DOT))
|
||||
LLVM_VERSION_PATTERN_REMOVE_ELEMENTS = $(subst " ",$(LLVM_VERSION_PATTERN_SEPERATOR),$(LLVM_VERSION_PATTERNS_REPLACE_PERCENT))
|
||||
LLMV_VERSION_PATTERN_REMOVE_SINGLE_STR = $(subst ",,$(LLVM_VERSION_PATTERN_REMOVE_ELEMENTS))
|
||||
LLVM_VERSION_PATTERN = "^(($(LLMV_VERSION_PATTERN_REMOVE_SINGLE_STR)))"
|
||||
|
||||
ifneq ($(shell llvm-config --version | grep -E $(LLVM_VERSION_PATTERN)),)
|
||||
LLVM_CONFIG=llvm-config
|
||||
else
|
||||
$(error "Requirement: llvm-config must be version $(LLVM_VERSION)")
|
||||
endif
|
||||
ifeq ($(ARCH), arm64)
|
||||
$(error "Requirement: llvm-config must be base version 13 for arm64")
|
||||
else
|
||||
$(error "Requirement: llvm-config must be base version greater than 11 for amd64/x86")
|
||||
endif
|
||||
endif
|
||||
|
||||
LDFLAGS:=$(LDFLAGS) -liconv
|
||||
CFLAGS:=$(CFLAGS) $(shell $(LLVM_CONFIG) --cxxflags --ldflags)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
package builtin
|
||||
|
||||
nil :: nil;
|
||||
false :: 0!==0;
|
||||
false :: 0!=0;
|
||||
true :: 0==0;
|
||||
|
||||
ODIN_OS :: ODIN_OS;
|
||||
|
||||
+11
-35
@@ -218,61 +218,37 @@ split_after_n :: proc(s, sep: []byte, n: int, allocator := context.allocator) ->
|
||||
|
||||
|
||||
@private
|
||||
_split_iterator :: proc(s: ^[]byte, sep: []byte, sep_save, n: int) -> (res: []byte, ok: bool) {
|
||||
s, n := s, n
|
||||
|
||||
if n == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if sep == nil {
|
||||
_split_iterator :: proc(s: ^[]byte, sep: []byte, sep_save: int) -> (res: []byte, ok: bool) {
|
||||
if len(sep) == 0 {
|
||||
res = s[:]
|
||||
ok = true
|
||||
s^ = s[len(s):]
|
||||
return
|
||||
}
|
||||
|
||||
if n < 0 {
|
||||
n = count(s^, sep) + 1
|
||||
}
|
||||
|
||||
n -= 1
|
||||
|
||||
i := 0
|
||||
for ; i < n; i += 1 {
|
||||
m := index(s^, sep)
|
||||
if m < 0 {
|
||||
break
|
||||
}
|
||||
m := index(s^, sep)
|
||||
if m < 0 {
|
||||
// not found
|
||||
res = s[:]
|
||||
ok = len(res) != 0
|
||||
s^ = s[len(s):]
|
||||
} else {
|
||||
res = s[:m+sep_save]
|
||||
ok = true
|
||||
s^ = s[m+len(sep):]
|
||||
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)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
split_after_n_iterator :: proc(s: ^[]byte, sep: []byte, n: int) -> ([]byte, bool) {
|
||||
return _split_iterator(s, sep, len(sep), n)
|
||||
}
|
||||
|
||||
|
||||
|
||||
index_byte :: proc(s: []byte, c: byte) -> int {
|
||||
for i := 0; i < len(s); i += 1 {
|
||||
|
||||
@@ -149,7 +149,7 @@ foreign libc {
|
||||
putchar :: proc() -> int ---
|
||||
puts :: proc(s: cstring) -> int ---
|
||||
ungetc :: proc(c: int, stream: ^FILE) -> int ---
|
||||
fread :: proc(ptr: rawptr, size: size_t, stream: ^FILE) -> size_t ---
|
||||
fread :: proc(ptr: rawptr, size: size_t, nmemb: size_t, stream: ^FILE) -> size_t ---
|
||||
fwrite :: proc(ptr: rawptr, size: size_t, nmemb: size_t, stream: ^FILE) -> size_t ---
|
||||
|
||||
// 7.21.9 File positioning functions
|
||||
|
||||
@@ -66,7 +66,8 @@ OS :: enum u8 {
|
||||
_Unknown = 14,
|
||||
Unknown = 255,
|
||||
}
|
||||
OS_Name :: #partial [OS]string{
|
||||
OS_Name :: #sparse[OS]string{
|
||||
._Unknown = "",
|
||||
.FAT = "FAT",
|
||||
.Amiga = "Amiga",
|
||||
.VMS = "VMS/OpenVMS",
|
||||
|
||||
@@ -111,9 +111,9 @@ ZFAST_MASK :: ((1 << ZFAST_BITS) - 1)
|
||||
*/
|
||||
Huffman_Table :: struct {
|
||||
fast: [1 << ZFAST_BITS]u16,
|
||||
firstcode: [16]u16,
|
||||
firstcode: [17]u16,
|
||||
maxcode: [17]int,
|
||||
firstsymbol: [16]u16,
|
||||
firstsymbol: [17]u16,
|
||||
size: [288]u8,
|
||||
value: [288]u16,
|
||||
}
|
||||
@@ -244,7 +244,7 @@ allocate_huffman_table :: proc(allocator := context.allocator) -> (z: ^Huffman_T
|
||||
@(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
|
||||
next_code: [HUFFMAN_MAX_BITS+1]int
|
||||
|
||||
k := int(0)
|
||||
|
||||
@@ -256,14 +256,14 @@ build_huffman :: proc(z: ^Huffman_Table, code_lengths: []u8) -> (err: Error) {
|
||||
}
|
||||
sizes[0] = 0
|
||||
|
||||
for i in 1..<(HUFFMAN_MAX_BITS+1) {
|
||||
for i in 1 ..< HUFFMAN_MAX_BITS {
|
||||
if sizes[i] > (1 << uint(i)) {
|
||||
return E_Deflate.Huffman_Bad_Sizes
|
||||
}
|
||||
}
|
||||
code := int(0)
|
||||
|
||||
for i in 1..<HUFFMAN_MAX_BITS {
|
||||
for i in 1 ..= HUFFMAN_MAX_BITS {
|
||||
next_code[i] = code
|
||||
z.firstcode[i] = u16(code)
|
||||
z.firstsymbol[i] = u16(k)
|
||||
@@ -538,19 +538,20 @@ inflate_raw :: proc(z: ^$C, expected_output_size := -1, allocator := context.all
|
||||
final = compress.read_bits_lsb(z, 1)
|
||||
type = compress.read_bits_lsb(z, 2)
|
||||
|
||||
// fmt.printf("Final: %v | Type: %v\n", final, type);
|
||||
// fmt.printf("Final: %v | Type: %v\n", final, type)
|
||||
|
||||
switch type {
|
||||
case 0:
|
||||
// fmt.printf("Method 0: STORED\n")
|
||||
// Uncompressed block
|
||||
|
||||
// Discard bits until next byte boundary
|
||||
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 := u16(compress.read_bits_lsb(z, 16))
|
||||
length_check := u16(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);
|
||||
// fmt.printf("LEN: %v, ~LEN: %v, NLEN: %v, ~NLEN: %v\n", uncompressed_len, ~uncompressed_len, length_check, ~length_check)
|
||||
|
||||
|
||||
if ~uncompressed_len != length_check {
|
||||
@@ -567,10 +568,12 @@ inflate_raw :: proc(z: ^$C, expected_output_size := -1, allocator := context.all
|
||||
write_byte(z, u8(lit))
|
||||
uncompressed_len -= 1
|
||||
}
|
||||
assert(uncompressed_len == 0)
|
||||
|
||||
case 3:
|
||||
return E_Deflate.BType_3
|
||||
case:
|
||||
// log.debugf("Err: %v | Final: %v | Type: %v\n", err, final, type);
|
||||
// fmt.printf("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
|
||||
|
||||
@@ -11,11 +11,119 @@ INDEX_SHIFT :: 6
|
||||
@(private="file")
|
||||
INDEX_MASK :: 63
|
||||
|
||||
@(private="file")
|
||||
NUM_BITS :: 64
|
||||
|
||||
Bit_Array :: struct {
|
||||
bits: [dynamic]u64,
|
||||
bias: int,
|
||||
max_index: int,
|
||||
}
|
||||
|
||||
Bit_Array_Iterator :: struct {
|
||||
array: ^Bit_Array,
|
||||
word_idx: int,
|
||||
bit_idx: uint,
|
||||
}
|
||||
|
||||
/*
|
||||
In:
|
||||
- ba: ^Bit_Array - the array to iterate over
|
||||
|
||||
Out:
|
||||
- it: ^Bit_Array_Iterator - the iterator that holds iteration state
|
||||
*/
|
||||
make_iterator :: proc (ba: ^Bit_Array) -> (it: Bit_Array_Iterator) {
|
||||
return Bit_Array_Iterator { array = ba }
|
||||
}
|
||||
|
||||
/*
|
||||
In:
|
||||
- it: ^Bit_Array_Iterator - the iterator struct that holds the state.
|
||||
|
||||
Out:
|
||||
- set: bool - the state of the bit at `index`
|
||||
- index: int - the next bit of the Bit_Array referenced by `it`.
|
||||
- ok: bool - `true` if the iterator returned a valid index,
|
||||
`false` if there were no more bits
|
||||
*/
|
||||
iterate_by_all :: proc (it: ^Bit_Array_Iterator) -> (set: bool, index: int, ok: bool) {
|
||||
index = it.word_idx * NUM_BITS + int(it.bit_idx) + it.array.bias
|
||||
if index > it.array.max_index { return false, 0, false }
|
||||
|
||||
word := it.array.bits[it.word_idx] if len(it.array.bits) > it.word_idx else 0
|
||||
set = (word >> it.bit_idx & 1) == 1
|
||||
|
||||
it.bit_idx += 1
|
||||
if it.bit_idx >= NUM_BITS {
|
||||
it.bit_idx = 0
|
||||
it.word_idx += 1
|
||||
}
|
||||
|
||||
return set, index, true
|
||||
}
|
||||
|
||||
/*
|
||||
In:
|
||||
- it: ^Bit_Array_Iterator - the iterator struct that holds the state.
|
||||
|
||||
Out:
|
||||
- index: int - the next set bit of the Bit_Array referenced by `it`.
|
||||
- ok: bool - `true` if the iterator returned a valid index,
|
||||
`false` if there were no more bits set
|
||||
*/
|
||||
iterate_by_set :: proc (it: ^Bit_Array_Iterator) -> (index: int, ok: bool) {
|
||||
return iterate_internal_(it, true)
|
||||
}
|
||||
|
||||
/*
|
||||
In:
|
||||
- it: ^Bit_Array_Iterator - the iterator struct that holds the state.
|
||||
|
||||
Out:
|
||||
- index: int - the next unset bit of the Bit_Array referenced by `it`.
|
||||
- ok: bool - `true` if the iterator returned a valid index,
|
||||
`false` if there were no more unset bits
|
||||
*/
|
||||
iterate_by_unset:: proc (it: ^Bit_Array_Iterator) -> (index: int, ok: bool) {
|
||||
return iterate_internal_(it, false)
|
||||
}
|
||||
|
||||
@(private="file")
|
||||
iterate_internal_ :: proc (it: ^Bit_Array_Iterator, $ITERATE_SET_BITS: bool) -> (index: int, ok: bool) {
|
||||
word := it.array.bits[it.word_idx] if len(it.array.bits) > it.word_idx else 0
|
||||
when ! ITERATE_SET_BITS { word = ~word }
|
||||
|
||||
// if the word is empty or we have already gone over all the bits in it,
|
||||
// b.bit_idx is greater than the index of any set bit in the word,
|
||||
// meaning that word >> b.bit_idx == 0.
|
||||
for it.word_idx < len(it.array.bits) && word >> it.bit_idx == 0 {
|
||||
it.word_idx += 1
|
||||
it.bit_idx = 0
|
||||
word = it.array.bits[it.word_idx] if len(it.array.bits) > it.word_idx else 0
|
||||
when ! ITERATE_SET_BITS { word = ~word }
|
||||
}
|
||||
|
||||
// if we are iterating the set bits, reaching the end of the array means we have no more bits to check
|
||||
when ITERATE_SET_BITS {
|
||||
if it.word_idx >= len(it.array.bits) {
|
||||
return 0, false
|
||||
}
|
||||
}
|
||||
|
||||
// reaching here means that the word has some set bits
|
||||
it.bit_idx += uint(intrinsics.count_trailing_zeros(word >> it.bit_idx))
|
||||
index = it.word_idx * NUM_BITS + int(it.bit_idx) + it.array.bias
|
||||
|
||||
it.bit_idx += 1
|
||||
if it.bit_idx >= NUM_BITS {
|
||||
it.bit_idx = 0
|
||||
it.word_idx += 1
|
||||
}
|
||||
return index, index <= it.array.max_index
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
In:
|
||||
- ba: ^Bit_Array - a pointer to the Bit Array
|
||||
@@ -70,6 +178,7 @@ set :: proc(ba: ^Bit_Array, #any_int index: uint, allocator := context.allocator
|
||||
|
||||
resize_if_needed(ba, leg_index) or_return
|
||||
|
||||
ba.max_index = max(idx, ba.max_index)
|
||||
ba.bits[leg_index] |= 1 << uint(bit_index)
|
||||
return true
|
||||
}
|
||||
@@ -87,8 +196,9 @@ create :: proc(max_index: int, min_index := 0, allocator := context.allocator) -
|
||||
|
||||
res = Bit_Array{
|
||||
bias = min_index,
|
||||
max_index = max_index,
|
||||
}
|
||||
return res, resize_if_needed(&res, size_in_bits)
|
||||
return res, resize_if_needed(&res, legs)
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -121,4 +231,4 @@ resize_if_needed :: proc(ba: ^Bit_Array, legs: int, allocator := context.allocat
|
||||
resize(&ba.bits, legs + 1)
|
||||
}
|
||||
return len(ba.bits) > legs
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
package container_lru
|
||||
|
||||
import "core:runtime"
|
||||
import "core:intrinsics"
|
||||
_ :: runtime
|
||||
_ :: intrinsics
|
||||
|
||||
Node :: struct($Key, $Value: typeid) where intrinsics.type_is_valid_map_key(Key) {
|
||||
prev, next: ^Node(Key, Value),
|
||||
key: Key,
|
||||
value: Value,
|
||||
}
|
||||
|
||||
// Cache is an LRU cache. It automatically removes entries as new entries are
|
||||
// added if the capacity is reached. Entries are removed based on how recently
|
||||
// they were used where the oldest entries are removed first.
|
||||
Cache :: struct($Key, $Value: typeid) where intrinsics.type_is_valid_map_key(Key) {
|
||||
head: ^Node(Key, Value),
|
||||
tail: ^Node(Key, Value),
|
||||
|
||||
entries: map[Key]^Node(Key, Value),
|
||||
|
||||
count: int,
|
||||
capacity: int,
|
||||
|
||||
node_allocator: runtime.Allocator,
|
||||
|
||||
on_remove: proc(key: Key, value: Value, user_data: rawptr),
|
||||
on_remove_user_data: rawptr,
|
||||
}
|
||||
|
||||
// init initializes a Cache
|
||||
init :: proc(c: ^$C/Cache($Key, $Value), capacity: int, entries_allocator := context.allocator, node_allocator := context.allocator) {
|
||||
c.entries.allocator = entries_allocator
|
||||
c.node_allocator = node_allocator
|
||||
c.capacity = capacity
|
||||
}
|
||||
|
||||
// destroy deinitializes a Cachem
|
||||
destroy :: proc(c: ^$C/Cache($Key, $Value), call_on_remove: bool) {
|
||||
clear(c, call_on_remove)
|
||||
delete(c.entries)
|
||||
}
|
||||
|
||||
// clear the contents of a Cache
|
||||
clear :: proc(c: ^$C/Cache($Key, $Value), call_on_remove: bool) {
|
||||
for _, node in c.entries {
|
||||
if call_on_remove {
|
||||
_call_on_remove(c, node)
|
||||
}
|
||||
free(node, c.node_allocator)
|
||||
}
|
||||
runtime.clear(&c.entries)
|
||||
c.head = nil
|
||||
c.tail = nil
|
||||
c.count = 0
|
||||
}
|
||||
|
||||
// set the given key value pair. This operation updates the recent usage of the item.
|
||||
set :: proc(c: ^$C/Cache($Key, $Value), key: Key, value: Value) -> runtime.Allocator_Error {
|
||||
if e, ok := c.entries[key]; ok {
|
||||
e.value = value
|
||||
return nil
|
||||
}
|
||||
|
||||
e := new(Node(Key, Value), c.node_allocator) or_return
|
||||
e.key = key
|
||||
e.value = value
|
||||
|
||||
_push_front_node(c, e)
|
||||
if c.count > c.capacity {
|
||||
_remove_node(c, c.tail)
|
||||
}
|
||||
|
||||
c.entries[key] = e
|
||||
return nil
|
||||
}
|
||||
|
||||
// get a value from the cache from a given key. This operation updates the usage of the item.
|
||||
get :: proc(c: ^$C/Cache($Key, $Value), key: Key) -> (value: Value, ok: bool) #optional_ok {
|
||||
e: ^Node(Key, Value)
|
||||
e, ok = c.entries[key]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
_pop_node(c, e)
|
||||
_push_front_node(c, e)
|
||||
return e.value, true
|
||||
}
|
||||
|
||||
// get_ptr gets the pointer to a value the cache from a given key. This operation updates the usage of the item.
|
||||
get_ptr :: proc(c: ^$C/Cache($Key, $Value), key: Key) -> (value: ^Value, ok: bool) #optional_ok {
|
||||
e: ^Node(Key, Value)
|
||||
e, ok = c.entries[key]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
_pop_node(c, e)
|
||||
_push_front_node(c, e)
|
||||
return &e.value, true
|
||||
}
|
||||
|
||||
// peek gets the value from the cache from a given key without updating the recent usage.
|
||||
peek :: proc(c: ^$C/Cache($Key, $Value), key: Key) -> (value: Value, ok: bool) #optional_ok {
|
||||
e: ^Node(Key, Value)
|
||||
e, ok = c.entries[key]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
return e.value, true
|
||||
}
|
||||
|
||||
// exists checks for the existence of a value from a given key without updating the recent usage.
|
||||
exists :: proc(c: ^$C/Cache($Key, $Value), key: Key) -> bool {
|
||||
return key in c.entries
|
||||
}
|
||||
|
||||
// remove removes an item from the cache.
|
||||
remove :: proc(c: ^$C/Cache($Key, $Value), key: Key) -> bool {
|
||||
e, ok := c.entries[key]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
_remove_node(c, e)
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@(private)
|
||||
_remove_node :: proc(c: ^$C/Cache($Key, $Value), node: ^Node(Key, Value)) {
|
||||
if c.head == node {
|
||||
c.head = node.next
|
||||
}
|
||||
if c.tail == node {
|
||||
c.tail = node.prev
|
||||
}
|
||||
if node.prev != nil {
|
||||
node.prev.next = node.next
|
||||
}
|
||||
if node.next != nil {
|
||||
node.next.prev = node.prev
|
||||
}
|
||||
node.prev = nil
|
||||
node.next = nil
|
||||
|
||||
c.count -= 1
|
||||
|
||||
delete_key(&c.entries, node.key)
|
||||
|
||||
_call_on_remove(c, node)
|
||||
|
||||
free(node, c.node_allocator)
|
||||
|
||||
}
|
||||
|
||||
@(private)
|
||||
_call_on_remove :: proc(c: ^$C/Cache($Key, $Value), node: ^Node(Key, Value)) {
|
||||
if c.on_remove != nil {
|
||||
c.on_remove(node.key, node.value, c.on_remove_user_data)
|
||||
}
|
||||
}
|
||||
|
||||
@(private)
|
||||
_push_front_node :: proc(c: ^$C/Cache($Key, $Value), e: ^Node(Key, Value)) {
|
||||
if c.head != nil {
|
||||
e.next = c.head
|
||||
e.next.prev = e
|
||||
}
|
||||
c.head = e
|
||||
if c.tail == nil {
|
||||
c.tail = e
|
||||
}
|
||||
e.prev = nil
|
||||
|
||||
c.count += 1
|
||||
}
|
||||
|
||||
@(private)
|
||||
_pop_node :: proc(c: ^$C/Cache($Key, $Value), e: ^Node(Key, Value)) {
|
||||
if e == nil {
|
||||
return
|
||||
}
|
||||
if e.prev != nil {
|
||||
e.prev.next = e.next
|
||||
}
|
||||
|
||||
if e.next != nil {
|
||||
e.next.prev = e.prev
|
||||
}
|
||||
e.prev = nil
|
||||
e.next = nil
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package container_queue
|
||||
|
||||
import "core:builtin"
|
||||
import "core:runtime"
|
||||
_ :: runtime
|
||||
|
||||
// Dynamically resizable double-ended queue/ring-buffer
|
||||
Queue :: struct($T: typeid) {
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
// The following is a generic O(V+E) topological sorter implementation.
|
||||
// This is the fastest known method for topological sorting and Odin's
|
||||
// map type is being used to accelerate lookups.
|
||||
package container_topological_sort
|
||||
|
||||
import "core:intrinsics"
|
||||
import "core:runtime"
|
||||
_ :: intrinsics
|
||||
_ :: runtime
|
||||
|
||||
|
||||
Relations :: struct($K: typeid) where intrinsics.type_is_valid_map_key(K) {
|
||||
dependents: map[K]bool,
|
||||
dependencies: int,
|
||||
}
|
||||
|
||||
Sorter :: struct(K: typeid) where intrinsics.type_is_valid_map_key(K) {
|
||||
relations: map[K]Relations(K),
|
||||
dependents_allocator: runtime.Allocator,
|
||||
}
|
||||
|
||||
@(private="file")
|
||||
make_relations :: proc(sorter: ^$S/Sorter($K)) -> (r: Relations(K)) {
|
||||
r.dependents.allocator = sorter.dependents_allocator
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
init :: proc(sorter: ^$S/Sorter($K)) {
|
||||
sorter.relations = make(map[K]Relations(K))
|
||||
sorter.dependents_allocator = context.allocator
|
||||
}
|
||||
|
||||
destroy :: proc(sorter: ^$S/Sorter($K)) {
|
||||
for _, v in &sorter.relations {
|
||||
delete(v.dependents)
|
||||
}
|
||||
delete(sorter.relations)
|
||||
}
|
||||
|
||||
add_key :: proc(sorter: ^$S/Sorter($K), key: K) -> bool {
|
||||
if key in sorter.relations {
|
||||
return false
|
||||
}
|
||||
sorter.relations[key] = make_relations(sorter)
|
||||
return true
|
||||
}
|
||||
|
||||
add_dependency :: proc(sorter: ^$S/Sorter($K), key, dependency: K) -> bool {
|
||||
if key == dependency {
|
||||
return false
|
||||
}
|
||||
|
||||
find := &sorter.relations[dependency]
|
||||
if find == nil {
|
||||
find = map_insert(&sorter.relations, dependency, make_relations(sorter))
|
||||
}
|
||||
|
||||
if find.dependents[key] {
|
||||
return true
|
||||
}
|
||||
find.dependents[key] = true
|
||||
|
||||
find = &sorter.relations[key]
|
||||
if find == nil {
|
||||
find = map_insert(&sorter.relations, key, make_relations(sorter))
|
||||
}
|
||||
|
||||
find.dependencies += 1
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
sort :: proc(sorter: ^$S/Sorter($K)) -> (sorted, cycled: [dynamic]K) {
|
||||
relations := &sorter.relations
|
||||
|
||||
for k, v in relations {
|
||||
if v.dependencies == 0 {
|
||||
append(&sorted, k)
|
||||
}
|
||||
}
|
||||
|
||||
for root in &sorted do for k, _ in relations[root].dependents {
|
||||
relation := &relations[k]
|
||||
relation.dependencies -= 1
|
||||
if relation.dependencies == 0 {
|
||||
append(&sorted, k)
|
||||
}
|
||||
}
|
||||
|
||||
for k, v in relations {
|
||||
if v.dependencies != 0 {
|
||||
append(&cycled, k)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -44,7 +44,7 @@ hash_bytes_224 :: proc "contextless" (data: []byte) -> [DIGEST_SIZE_224]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_224(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_224(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_224 will hash the given input and write the
|
||||
@@ -123,7 +123,7 @@ hash_bytes_256 :: proc "contextless" (data: []byte) -> [DIGEST_SIZE_256]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_256 will hash the given input and write the
|
||||
@@ -202,7 +202,7 @@ hash_bytes_384 :: proc "contextless" (data: []byte) -> [DIGEST_SIZE_384]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_384(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_384(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_384 will hash the given input and write the
|
||||
@@ -281,7 +281,7 @@ hash_bytes_512 :: proc "contextless" (data: []byte) -> [DIGEST_SIZE_512]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_512(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_512(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_512 will hash the given input and write the
|
||||
|
||||
@@ -46,7 +46,7 @@ hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer will hash the given input and write the
|
||||
|
||||
@@ -47,7 +47,7 @@ hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer will hash the given input and write the
|
||||
|
||||
@@ -41,7 +41,7 @@ hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer will hash the given input and write the
|
||||
|
||||
@@ -44,7 +44,7 @@ hash_bytes_224 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_224(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_224(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_224 will hash the given input and write the
|
||||
@@ -123,7 +123,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_256 will hash the given input and write the
|
||||
@@ -202,7 +202,7 @@ hash_bytes_384 :: proc(data: []byte) -> [DIGEST_SIZE_384]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_384(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_384(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_384 will hash the given input and write the
|
||||
@@ -281,7 +281,7 @@ hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_512(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_512(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_512 will hash the given input and write the
|
||||
|
||||
@@ -50,7 +50,7 @@ hash_bytes_128_3 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_128_3 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_128_3(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_128_3(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_128_3 will hash the given input and write the
|
||||
@@ -135,7 +135,7 @@ hash_bytes_128_4 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_128_4 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_128_4(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_128_4(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_128_4 will hash the given input and write the
|
||||
@@ -220,7 +220,7 @@ hash_bytes_128_5 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_128_5 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_128_5(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_128_5(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_128_5 will hash the given input and write the
|
||||
@@ -305,7 +305,7 @@ hash_bytes_160_3 :: proc(data: []byte) -> [DIGEST_SIZE_160]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_160_3 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_160_3(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_160_3(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_160_3 will hash the given input and write the
|
||||
@@ -390,7 +390,7 @@ hash_bytes_160_4 :: proc(data: []byte) -> [DIGEST_SIZE_160]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_160_4 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_160_4(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_160_4(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_160_4 will hash the given input and write the
|
||||
@@ -475,7 +475,7 @@ hash_bytes_160_5 :: proc(data: []byte) -> [DIGEST_SIZE_160]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_160_5 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_160_5(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_160_5(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_160_5 will hash the given input and write the
|
||||
@@ -560,7 +560,7 @@ hash_bytes_192_3 :: proc(data: []byte) -> [DIGEST_SIZE_192]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_192_3 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_192_3(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_192_3(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_192_3 will hash the given input and write the
|
||||
@@ -645,7 +645,7 @@ hash_bytes_192_4 :: proc(data: []byte) -> [DIGEST_SIZE_192]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_192_4 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_192_4(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_192_4(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_192_4 will hash the given input and write the
|
||||
@@ -730,7 +730,7 @@ hash_bytes_192_5 :: proc(data: []byte) -> [DIGEST_SIZE_192]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_192_5 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_192_5(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_192_5(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_192_5 will hash the given input and write the
|
||||
@@ -815,7 +815,7 @@ hash_bytes_224_3 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_224_3 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_224_3(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_224_3(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_224_3 will hash the given input and write the
|
||||
@@ -900,7 +900,7 @@ hash_bytes_224_4 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_224_4 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_224_4(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_224_4(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_224_4 will hash the given input and write the
|
||||
@@ -985,7 +985,7 @@ hash_bytes_224_5 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_224_5 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_224_5(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_224_5(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_224_5 will hash the given input and write the
|
||||
@@ -1070,7 +1070,7 @@ hash_bytes_256_3 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_256_3 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_256_3(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_256_3(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_256_3 will hash the given input and write the
|
||||
@@ -1155,7 +1155,7 @@ hash_bytes_256_4 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_256_4 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_256_4(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_256_4(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_256_4 will hash the given input and write the
|
||||
@@ -1240,7 +1240,7 @@ hash_bytes_256_5 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_256_5 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_256_5(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_256_5(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_256_5 will hash the given input and write the
|
||||
|
||||
@@ -44,7 +44,7 @@ hash_bytes_224 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_224(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_224(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_224 will hash the given input and write the
|
||||
@@ -123,7 +123,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_256 will hash the given input and write the
|
||||
@@ -202,7 +202,7 @@ hash_bytes_384 :: proc(data: []byte) -> [DIGEST_SIZE_384]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_384(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_384(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_384 will hash the given input and write the
|
||||
@@ -281,7 +281,7 @@ hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_512(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_512(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_512 will hash the given input and write the
|
||||
|
||||
@@ -49,7 +49,7 @@ hash_bytes_224 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_224(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_224(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_224 will hash the given input and write the
|
||||
@@ -131,7 +131,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_256 will hash the given input and write the
|
||||
@@ -213,7 +213,7 @@ hash_bytes_384 :: proc(data: []byte) -> [DIGEST_SIZE_384]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_384(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_384(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_384 will hash the given input and write the
|
||||
@@ -295,7 +295,7 @@ hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_512(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_512(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_512 will hash the given input and write the
|
||||
|
||||
@@ -40,7 +40,7 @@ hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer will hash the given input and write the
|
||||
|
||||
@@ -44,7 +44,7 @@ hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer will hash the given input and write the
|
||||
|
||||
@@ -43,7 +43,7 @@ hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer will hash the given input and write the
|
||||
|
||||
@@ -45,7 +45,7 @@ hash_bytes_128 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_128 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_128(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_128(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_128 will hash the given input and write the
|
||||
@@ -121,7 +121,7 @@ hash_bytes_160 :: proc(data: []byte) -> [DIGEST_SIZE_160]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_160 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_160(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_160(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_160 will hash the given input and write the
|
||||
@@ -197,7 +197,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_256 will hash the given input and write the
|
||||
@@ -273,7 +273,7 @@ hash_bytes_320 :: proc(data: []byte) -> [DIGEST_SIZE_320]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_320 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_320(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_320(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_320 will hash the given input and write the
|
||||
|
||||
@@ -43,7 +43,7 @@ hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer will hash the given input and write the
|
||||
|
||||
@@ -48,7 +48,7 @@ hash_bytes_224 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_224(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_224(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_224 will hash the given input and write the
|
||||
@@ -127,7 +127,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_256 will hash the given input and write the
|
||||
@@ -206,7 +206,7 @@ hash_bytes_384 :: proc(data: []byte) -> [DIGEST_SIZE_384]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_384(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_384(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_384 will hash the given input and write the
|
||||
@@ -285,7 +285,7 @@ hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_512(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_512(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_512 will hash the given input and write the
|
||||
|
||||
@@ -47,7 +47,7 @@ hash_bytes_224 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_224(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_224(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_224 will hash the given input and write the
|
||||
@@ -126,7 +126,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_256 will hash the given input and write the
|
||||
@@ -205,7 +205,7 @@ hash_bytes_384 :: proc(data: []byte) -> [DIGEST_SIZE_384]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_384(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_384(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_384 will hash the given input and write the
|
||||
@@ -284,7 +284,7 @@ hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_512(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_512(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_512 will hash the given input and write the
|
||||
|
||||
@@ -46,7 +46,7 @@ hash_bytes_128 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_128 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_128(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_128(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_128 will hash the given input and write the
|
||||
@@ -128,7 +128,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_256 will hash the given input and write the
|
||||
|
||||
@@ -42,7 +42,7 @@ hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer will hash the given input and write the
|
||||
|
||||
@@ -44,7 +44,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_256 will hash the given input and write the
|
||||
@@ -122,7 +122,7 @@ hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_512(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_512(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_512 will hash the given input and write the
|
||||
|
||||
@@ -45,7 +45,7 @@ hash_bytes_128 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_128 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_128(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_128(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_128 will hash the given input and write the
|
||||
@@ -124,7 +124,7 @@ hash_bytes_160 :: proc(data: []byte) -> [DIGEST_SIZE_160]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_160 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_160(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_160(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_160 will hash the given input and write the
|
||||
@@ -203,7 +203,7 @@ hash_bytes_192 :: proc(data: []byte) -> [DIGEST_SIZE_192]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_192 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_192(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_192(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_192 will hash the given input and write the
|
||||
|
||||
@@ -45,7 +45,7 @@ hash_bytes_128 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_128 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_128(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_128(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_128 will hash the given input and write the
|
||||
@@ -124,7 +124,7 @@ hash_bytes_160 :: proc(data: []byte) -> [DIGEST_SIZE_160]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_160 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_160(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_160(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_160 will hash the given input and write the
|
||||
@@ -203,7 +203,7 @@ hash_bytes_192 :: proc(data: []byte) -> [DIGEST_SIZE_192]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer_192 :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer_192(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer_192(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer_192 will hash the given input and write the
|
||||
|
||||
@@ -42,7 +42,7 @@ hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte {
|
||||
// computed hash to the second parameter.
|
||||
// It requires that the destination buffer is at least as big as the digest size
|
||||
hash_string_to_buffer :: proc(data: string, hash: []byte) {
|
||||
hash_bytes_to_buffer(transmute([]byte)(data), hash);
|
||||
hash_bytes_to_buffer(transmute([]byte)(data), hash)
|
||||
}
|
||||
|
||||
// hash_bytes_to_buffer will hash the given input and write the
|
||||
|
||||
+27
-6
@@ -11,6 +11,7 @@ import "core:time"
|
||||
import "core:unicode/utf8"
|
||||
import "core:intrinsics"
|
||||
|
||||
// Internal data structure that stores the required information for formatted printing
|
||||
Info :: struct {
|
||||
minus: bool,
|
||||
plus: bool,
|
||||
@@ -46,9 +47,13 @@ Register_User_Formatter_Error :: enum {
|
||||
// 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
|
||||
|
||||
// set_user_formatters assigns m to a global value allowing the user have custom print formatting for specific
|
||||
// types
|
||||
set_user_formatters :: proc(m: ^map[typeid]User_Formatter) {
|
||||
_user_formatters = m
|
||||
}
|
||||
// register_user_formatter assigns a formatter to a specific typeid. set_user_formatters must be called
|
||||
// before any use of this procedure.
|
||||
register_user_formatter :: proc(id: typeid, formatter: User_Formatter) -> Register_User_Formatter_Error {
|
||||
if _user_formatters == nil {
|
||||
return .No_User_Formatter
|
||||
@@ -61,7 +66,7 @@ register_user_formatter :: proc(id: typeid, formatter: User_Formatter) -> Regist
|
||||
}
|
||||
|
||||
|
||||
// aprint* procedures return a string that was allocated with the current context
|
||||
// aprint procedure return a string that was allocated with the current context
|
||||
// They must be freed accordingly
|
||||
aprint :: proc(args: ..any, sep := " ") -> string {
|
||||
str: strings.Builder
|
||||
@@ -69,12 +74,16 @@ aprint :: proc(args: ..any, sep := " ") -> string {
|
||||
sbprint(buf=&str, args=args, sep=sep)
|
||||
return strings.to_string(str)
|
||||
}
|
||||
// aprintln procedure return a string that was allocated with the current context
|
||||
// They must be freed accordingly
|
||||
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)
|
||||
}
|
||||
// aprintf procedure return a string that was allocated with the current context
|
||||
// They must be freed accordingly
|
||||
aprintf :: proc(fmt: string, args: ..any) -> string {
|
||||
str: strings.Builder
|
||||
strings.init_builder(&str)
|
||||
@@ -83,19 +92,21 @@ aprintf :: proc(fmt: string, args: ..any) -> string {
|
||||
}
|
||||
|
||||
|
||||
// tprint* procedures return a string that was allocated with the current context's temporary allocator
|
||||
// tprint procedure 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)
|
||||
}
|
||||
// tprintln procedure return a string that was allocated with the current context's temporary allocator
|
||||
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)
|
||||
}
|
||||
// tprintf procedure return a string that was allocated with the current context's temporary allocator
|
||||
tprintf :: proc(fmt: string, args: ..any) -> string {
|
||||
str: strings.Builder
|
||||
strings.init_builder(&str, context.temp_allocator)
|
||||
@@ -104,21 +115,24 @@ tprintf :: proc(fmt: string, args: ..any) -> string {
|
||||
}
|
||||
|
||||
|
||||
// bprint* procedures return a string using a buffer from an array
|
||||
// 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)
|
||||
}
|
||||
// bprintln procedures return a string using a buffer from an array
|
||||
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)
|
||||
}
|
||||
// bprintf procedures return a string using a buffer from an array
|
||||
bprintf :: proc(buf: []byte, fmt: string, args: ..any) -> string {
|
||||
sb := strings.builder_from_slice(buf[0:len(buf)])
|
||||
return sbprintf(&sb, fmt, ..args)
|
||||
}
|
||||
|
||||
|
||||
// formatted assert
|
||||
assertf :: proc(condition: bool, fmt: string, args: ..any, loc := #caller_location) -> bool {
|
||||
if !condition {
|
||||
p := context.assertion_failure_proc
|
||||
@@ -131,6 +145,7 @@ assertf :: proc(condition: bool, fmt: string, args: ..any, loc := #caller_locati
|
||||
return condition
|
||||
}
|
||||
|
||||
// formatted panic
|
||||
panicf :: proc(fmt: string, args: ..any, loc := #caller_location) -> ! {
|
||||
p := context.assertion_failure_proc
|
||||
if p == nil {
|
||||
@@ -142,24 +157,26 @@ panicf :: proc(fmt: string, args: ..any, loc := #caller_location) -> ! {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// sbprint formats using the default print settings and writes to buf
|
||||
sbprint :: proc(buf: ^strings.Builder, args: ..any, sep := " ") -> string {
|
||||
wprint(w=strings.to_writer(buf), args=args, sep=sep)
|
||||
return strings.to_string(buf^)
|
||||
}
|
||||
|
||||
// sbprintln formats using the default print settings and writes to 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^)
|
||||
}
|
||||
|
||||
// sbprintf formats according to the specififed format string and writes to 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^)
|
||||
}
|
||||
|
||||
|
||||
// wprint formats using the default print settings and writes to w
|
||||
wprint :: proc(w: io.Writer, args: ..any, sep := " ") -> int {
|
||||
fi: Info
|
||||
fi.writer = w
|
||||
@@ -194,6 +211,7 @@ wprint :: proc(w: io.Writer, args: ..any, sep := " ") -> int {
|
||||
return int(size1 - size0)
|
||||
}
|
||||
|
||||
// wprintln formats using the default print settings and writes to w
|
||||
wprintln :: proc(w: io.Writer, args: ..any, sep := " ") -> int {
|
||||
fi: Info
|
||||
fi.writer = w
|
||||
@@ -214,6 +232,7 @@ wprintln :: proc(w: io.Writer, args: ..any, sep := " ") -> int {
|
||||
return int(size1 - size0)
|
||||
}
|
||||
|
||||
// wprintf formats according to the specififed format string and writes to w
|
||||
wprintf :: proc(w: io.Writer, fmt: string, args: ..any) -> int {
|
||||
fi: Info
|
||||
arg_index: int = 0
|
||||
@@ -493,11 +512,13 @@ wprintf :: proc(w: io.Writer, fmt: string, args: ..any) -> int {
|
||||
return int(size1 - size0)
|
||||
}
|
||||
|
||||
// wprint_type is a utility procedure to write a ^runtime.Type_Info value to w
|
||||
wprint_type :: proc(w: io.Writer, info: ^runtime.Type_Info) -> (int, io.Error) {
|
||||
n, err := reflect.write_type(w, info)
|
||||
io.flush(auto_cast w)
|
||||
return n, err
|
||||
}
|
||||
// wprint_typeid is a utility procedure to write a typeid value to w
|
||||
wprint_typeid :: proc(w: io.Writer, id: typeid) -> (int, io.Error) {
|
||||
n, err := reflect.write_type(w, type_info_of(id))
|
||||
io.flush(auto_cast w)
|
||||
@@ -829,7 +850,7 @@ _pad :: proc(fi: ^Info, s: string) {
|
||||
|
||||
fmt_float :: proc(fi: ^Info, v: f64, bit_size: int, verb: rune) {
|
||||
switch verb {
|
||||
case 'f', 'F', 'v':
|
||||
case 'f', 'F', 'g', 'G', 'v':
|
||||
prec: int = 3
|
||||
if fi.prec_set {
|
||||
prec = fi.prec
|
||||
|
||||
@@ -34,11 +34,16 @@ stderr := io.Writer{
|
||||
},
|
||||
}
|
||||
|
||||
// print* procedures return the number of bytes written
|
||||
// print formats using the default print settings and writes to stdout
|
||||
print :: proc(args: ..any, sep := " ") -> int { return wprint(w=stdout, args=args, sep=sep) }
|
||||
// println formats using the default print settings and writes to stdout
|
||||
println :: proc(args: ..any, sep := " ") -> int { return wprintln(w=stdout, args=args, sep=sep) }
|
||||
// printf formats according to the specififed format string and writes to stdout
|
||||
printf :: proc(fmt: string, args: ..any) -> int { return wprintf(stdout, fmt, ..args) }
|
||||
|
||||
// eprint formats using the default print settings and writes to stderr
|
||||
eprint :: proc(args: ..any, sep := " ") -> int { return wprint(w=stderr, args=args, sep=sep) }
|
||||
// eprintln formats using the default print settings and writes to stderr
|
||||
eprintln :: proc(args: ..any, sep := " ") -> int { return wprintln(w=stderr, args=args, sep=sep) }
|
||||
// eprintf formats according to the specififed format string and writes to stderr
|
||||
eprintf :: proc(fmt: string, args: ..any) -> int { return wprintf(stderr, fmt, ..args) }
|
||||
|
||||
@@ -5,15 +5,18 @@ import "core:runtime"
|
||||
import "core:os"
|
||||
import "core:io"
|
||||
|
||||
// fprint formats using the default print settings and writes to fd
|
||||
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)
|
||||
}
|
||||
|
||||
// fprintln formats using the default print settings and writes to fd
|
||||
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)
|
||||
}
|
||||
// fprintf formats according to the specififed format string and writes to fd
|
||||
fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int {
|
||||
w := io.to_writer(os.stream_from_handle(fd))
|
||||
return wprintf(w, fmt, ..args)
|
||||
@@ -27,11 +30,16 @@ fprint_typeid :: proc(fd: os.Handle, id: typeid) -> (n: int, err: io.Error) {
|
||||
return wprint_typeid(w, id)
|
||||
}
|
||||
|
||||
// print* procedures return the number of bytes written
|
||||
// print formats using the default print settings and writes to os.stdout
|
||||
print :: proc(args: ..any, sep := " ") -> int { return fprint(fd=os.stdout, args=args, sep=sep) }
|
||||
// println formats using the default print settings and writes to os.stdout
|
||||
println :: proc(args: ..any, sep := " ") -> int { return fprintln(fd=os.stdout, args=args, sep=sep) }
|
||||
// printf formats according to the specififed format string and writes to os.stdout
|
||||
printf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stdout, fmt, ..args) }
|
||||
|
||||
// eprint formats using the default print settings and writes to os.stderr
|
||||
eprint :: proc(args: ..any, sep := " ") -> int { return fprint(fd=os.stderr, args=args, sep=sep) }
|
||||
// eprintln formats using the default print settings and writes to os.stderr
|
||||
eprintln :: proc(args: ..any, sep := " ") -> int { return fprintln(fd=os.stderr, args=args, sep=sep) }
|
||||
// eprintf formats according to the specififed format string and writes to os.stderr
|
||||
eprintf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stderr, fmt, ..args) }
|
||||
|
||||
+39
-2
@@ -1,9 +1,13 @@
|
||||
// package io provides basic interfaces for generic data stream primitives.
|
||||
// The purpose of this package is wrap existing data structures and their
|
||||
// operations into an abstracted stream interface.
|
||||
package io
|
||||
|
||||
import "core:intrinsics"
|
||||
import "core:runtime"
|
||||
import "core:unicode/utf8"
|
||||
|
||||
// Seek whence values
|
||||
Seek_From :: enum {
|
||||
Start = 0, // seek relative to the origin of the file
|
||||
Current = 1, // seek relative to the current offset
|
||||
@@ -139,6 +143,10 @@ destroy :: proc(s: Stream) -> Error {
|
||||
return .Empty
|
||||
}
|
||||
|
||||
// read reads up to len(p) bytes into s. It returns the number of bytes read and any error if occurred.
|
||||
//
|
||||
// When read encounters an .EOF or error after successfully reading n > 0 bytes, it returns the number of
|
||||
// bytes read along with the error.
|
||||
read :: proc(s: Reader, p: []byte, n_read: ^int = nil) -> (n: int, err: Error) {
|
||||
if s.stream_vtable != nil && s.impl_read != nil {
|
||||
n, err = s->impl_read(p)
|
||||
@@ -150,6 +158,7 @@ read :: proc(s: Reader, p: []byte, n_read: ^int = nil) -> (n: int, err: Error) {
|
||||
return 0, .Empty
|
||||
}
|
||||
|
||||
// write writes up to len(p) bytes into s. It returns the number of bytes written and any error if occurred.
|
||||
write :: proc(s: Writer, p: []byte, n_written: ^int = nil) -> (n: int, err: Error) {
|
||||
if s.stream_vtable != nil && s.impl_write != nil {
|
||||
n, err = s->impl_write(p)
|
||||
@@ -161,6 +170,13 @@ write :: proc(s: Writer, p: []byte, n_written: ^int = nil) -> (n: int, err: Erro
|
||||
return 0, .Empty
|
||||
}
|
||||
|
||||
// seek sets the offset of the next read or write to offset.
|
||||
//
|
||||
// .Start means seek relative to the origin of the file.
|
||||
// .Current means seek relative to the current offset.
|
||||
// .End means seek relative to the end.
|
||||
//
|
||||
// seek returns the new offset to the start of the file/stream, and any error if occurred.
|
||||
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)
|
||||
@@ -168,6 +184,8 @@ seek :: proc(s: Seeker, offset: i64, whence: Seek_From) -> (n: i64, err: Error)
|
||||
return 0, .Empty
|
||||
}
|
||||
|
||||
// The behaviour of close after the first call is stream implementation defined.
|
||||
// Different streams may document their own behaviour.
|
||||
close :: proc(s: Closer) -> Error {
|
||||
if s.stream_vtable != nil && s.impl_close != nil {
|
||||
return s->impl_close()
|
||||
@@ -184,6 +202,7 @@ flush :: proc(s: Flusher) -> Error {
|
||||
return .None
|
||||
}
|
||||
|
||||
// size returns the size of the stream. If the stream does not support querying its size, 0 will be returned.
|
||||
size :: proc(s: Stream) -> i64 {
|
||||
if s.stream_vtable == nil {
|
||||
return 0
|
||||
@@ -214,7 +233,12 @@ size :: proc(s: Stream) -> i64 {
|
||||
|
||||
|
||||
|
||||
|
||||
// read_at reads len(p) bytes into p starting with the provided offset in the underlying Reader_At stream r.
|
||||
// It returns the number of bytes read and any error if occurred.
|
||||
//
|
||||
// When read_at returns n < len(p), it returns a non-nil Error explaining why.
|
||||
//
|
||||
// If n == len(p), err may be either nil or .EOF
|
||||
read_at :: proc(r: Reader_At, p: []byte, offset: i64, n_read: ^int = nil) -> (n: int, err: Error) {
|
||||
defer if n_read != nil {
|
||||
n_read^ += n
|
||||
@@ -245,6 +269,11 @@ read_at :: proc(r: Reader_At, p: []byte, offset: i64, n_read: ^int = nil) -> (n:
|
||||
|
||||
}
|
||||
|
||||
// write_at writes len(p) bytes into p starting with the provided offset in the underlying Writer_At stream w.
|
||||
// It returns the number of bytes written and any error if occurred.
|
||||
//
|
||||
// If write_at is writing to a Writer_At which has a seek offset, then write_at should not affect the underlying
|
||||
// seek offset.
|
||||
write_at :: proc(w: Writer_At, p: []byte, offset: i64, n_written: ^int = nil) -> (n: int, err: Error) {
|
||||
defer if n_written != nil {
|
||||
n_written^ += n
|
||||
@@ -294,6 +323,7 @@ read_from :: proc(w: Reader_From, r: Reader) -> (n: i64, err: Error) {
|
||||
}
|
||||
|
||||
|
||||
// read_byte reads and returns the next byte from r.
|
||||
read_byte :: proc(r: Byte_Reader, n_read: ^int = nil) -> (b: byte, err: Error) {
|
||||
defer if err == nil && n_read != nil {
|
||||
n_read^ += 1
|
||||
@@ -347,6 +377,7 @@ _write_byte :: proc(w: Byte_Writer, c: byte, n_written: ^int = nil) -> (err: Err
|
||||
return err
|
||||
}
|
||||
|
||||
// read_rune reads a single UTF-8 encoded Unicode codepoint and returns the rune and its size in bytes.
|
||||
read_rune :: proc(br: Rune_Reader, n_read: ^int = nil) -> (ch: rune, size: int, err: Error) {
|
||||
defer if err == nil && n_read != nil {
|
||||
n_read^ += size
|
||||
@@ -405,10 +436,12 @@ unread_rune :: proc(s: Rune_Scanner) -> Error {
|
||||
}
|
||||
|
||||
|
||||
// write_string writes the contents of the string s to w.
|
||||
write_string :: proc(s: Writer, str: string, n_written: ^int = nil) -> (n: int, err: Error) {
|
||||
return write(s, transmute([]byte)str, n_written)
|
||||
}
|
||||
|
||||
// write_rune writes a UTF-8 encoded rune to w.
|
||||
write_rune :: proc(s: Writer, r: rune, n_written: ^int = nil) -> (size: int, err: Error) {
|
||||
defer if err == nil && n_written != nil {
|
||||
n_written^ += size
|
||||
@@ -430,12 +463,16 @@ write_rune :: proc(s: Writer, r: rune, n_written: ^int = nil) -> (size: int, err
|
||||
}
|
||||
|
||||
|
||||
|
||||
// read_full expected exactly len(buf) bytes from r into buf.
|
||||
read_full :: proc(r: Reader, buf: []byte) -> (n: int, err: Error) {
|
||||
return read_at_least(r, buf, len(buf))
|
||||
}
|
||||
|
||||
|
||||
// read_at_least reads from r into buf until it has read at least min bytes. It returns the number
|
||||
// of bytes copied and an error if fewer bytes were read. `.EOF` is only returned if no bytes were read.
|
||||
// `.Unexpected_EOF` is returned when an `.EOF ` is returned by the passed Reader after reading
|
||||
// fewer than min bytes. If len(buf) is less than min, `.Short_Buffer` is returned.
|
||||
read_at_least :: proc(r: Reader, buf: []byte, min: int) -> (n: int, err: Error) {
|
||||
if len(buf) < min {
|
||||
return 0, .Short_Buffer
|
||||
|
||||
@@ -172,7 +172,7 @@ Error :: enum int {
|
||||
Unimplemented = 127,
|
||||
}
|
||||
|
||||
Error_String :: #partial [Error]string{
|
||||
Error_String :: #sparse[Error]string{
|
||||
.Okay = "Okay",
|
||||
.Out_Of_Memory = "Out of memory",
|
||||
.Invalid_Pointer = "Invalid pointer",
|
||||
@@ -182,6 +182,7 @@ Error_String :: #partial [Error]string{
|
||||
.Max_Iterations_Reached = "Max iterations reached",
|
||||
.Buffer_Overflow = "Buffer overflow",
|
||||
.Integer_Overflow = "Integer overflow",
|
||||
.Integer_Underflow = "Integer underflow",
|
||||
|
||||
.Division_by_Zero = "Division by zero",
|
||||
.Math_Domain_Error = "Math domain error",
|
||||
|
||||
@@ -473,6 +473,25 @@ floor_dvec3 :: proc "c" (x: dvec3) -> dvec3 { return {floor(x.x), floor(x.y), fl
|
||||
floor_dvec4 :: proc "c" (x: dvec4) -> dvec4 { return {floor(x.x), floor(x.y), floor(x.z), floor(x.w)} }
|
||||
|
||||
|
||||
|
||||
round :: proc{
|
||||
round_f32,
|
||||
round_f64,
|
||||
round_vec2,
|
||||
round_vec3,
|
||||
round_vec4,
|
||||
round_dvec2,
|
||||
round_dvec3,
|
||||
round_dvec4,
|
||||
}
|
||||
round_vec2 :: proc "c" (x: vec2) -> vec2 { return {round(x.x), round(x.y)} }
|
||||
round_vec3 :: proc "c" (x: vec3) -> vec3 { return {round(x.x), round(x.y), round(x.z)} }
|
||||
round_vec4 :: proc "c" (x: vec4) -> vec4 { return {round(x.x), round(x.y), round(x.z), round(x.w)} }
|
||||
round_dvec2 :: proc "c" (x: dvec2) -> dvec2 { return {round(x.x), round(x.y)} }
|
||||
round_dvec3 :: proc "c" (x: dvec3) -> dvec3 { return {round(x.x), round(x.y), round(x.z)} }
|
||||
round_dvec4 :: proc "c" (x: dvec4) -> dvec4 { return {round(x.x), round(x.y), round(x.z), round(x.w)} }
|
||||
|
||||
|
||||
ceil :: proc{
|
||||
ceil_f32,
|
||||
ceil_f64,
|
||||
|
||||
@@ -23,6 +23,7 @@ log_f32 :: proc "c" (x: f32) -> f32 { return math.ln(x) }
|
||||
exp2_f32 :: proc "c" (x: f32) -> f32 { return math.pow(f32(2), x) }
|
||||
sign_f32 :: proc "c" (x: f32) -> f32 { return math.sign(x) }
|
||||
floor_f32 :: proc "c" (x: f32) -> f32 { return math.floor(x) }
|
||||
round_f32 :: proc "c" (x: f32) -> f32 { return math.round(x) }
|
||||
ceil_f32 :: proc "c" (x: f32) -> f32 { return math.ceil(x) }
|
||||
mod_f32 :: proc "c" (x, y: f32) -> f32 { return math.mod(x, y) }
|
||||
fract_f32 :: proc "c" (x: f32) -> f32 {
|
||||
@@ -53,6 +54,7 @@ log_f64 :: proc "c" (x: f64) -> f64 { return math.ln(x) }
|
||||
exp2_f64 :: proc "c" (x: f64) -> f64 { return math.pow(f64(2), x) }
|
||||
sign_f64 :: proc "c" (x: f64) -> f64 { return math.sign(x) }
|
||||
floor_f64 :: proc "c" (x: f64) -> f64 { return math.floor(x) }
|
||||
round_f64 :: proc "c" (x: f64) -> f64 { return math.round(x) }
|
||||
ceil_f64 :: proc "c" (x: f64) -> f64 { return math.ceil(x) }
|
||||
mod_f64 :: proc "c" (x, y: f64) -> f64 { return math.mod(x, y) }
|
||||
fract_f64 :: proc "c" (x: f64) -> f64 {
|
||||
|
||||
@@ -551,6 +551,23 @@ floor_double2 :: proc "c" (x: double2) -> double2 { return {floor(x.x), floor(x.
|
||||
floor_double3 :: proc "c" (x: double3) -> double3 { return {floor(x.x), floor(x.y), floor(x.z)} }
|
||||
floor_double4 :: proc "c" (x: double4) -> double4 { return {floor(x.x), floor(x.y), floor(x.z), floor(x.w)} }
|
||||
|
||||
round :: proc{
|
||||
round_float,
|
||||
round_double,
|
||||
round_float2,
|
||||
round_float3,
|
||||
round_float4,
|
||||
round_double2,
|
||||
round_double3,
|
||||
round_double4,
|
||||
}
|
||||
round_float2 :: proc "c" (x: float2) -> float2 { return {round(x.x), round(x.y)} }
|
||||
round_float3 :: proc "c" (x: float3) -> float3 { return {round(x.x), round(x.y), round(x.z)} }
|
||||
round_float4 :: proc "c" (x: float4) -> float4 { return {round(x.x), round(x.y), round(x.z), round(x.w)} }
|
||||
round_double2 :: proc "c" (x: double2) -> double2 { return {round(x.x), round(x.y)} }
|
||||
round_double3 :: proc "c" (x: double3) -> double3 { return {round(x.x), round(x.y), round(x.z)} }
|
||||
round_double4 :: proc "c" (x: double4) -> double4 { return {round(x.x), round(x.y), round(x.z), round(x.w)} }
|
||||
|
||||
|
||||
ceil :: proc{
|
||||
ceil_float,
|
||||
@@ -570,6 +587,69 @@ ceil_double3 :: proc "c" (x: double3) -> double3 { return {ceil(x.x), ceil(x.y),
|
||||
ceil_double4 :: proc "c" (x: double4) -> double4 { return {ceil(x.x), ceil(x.y), ceil(x.z), ceil(x.w)} }
|
||||
|
||||
|
||||
isfinite_float :: proc "c" (x: float) -> bool { return !isinf_float(x) }
|
||||
isfinite_float2 :: proc "c" (x: float2) -> bool2 { return {isfinite_float(x.x), isfinite_float(x.y)} }
|
||||
isfinite_float3 :: proc "c" (x: float3) -> bool3 { return {isfinite_float(x.x), isfinite_float(x.y), isfinite_float(x.z)} }
|
||||
isfinite_float4 :: proc "c" (x: float4) -> bool4 { return {isfinite_float(x.x), isfinite_float(x.y), isfinite_float(x.z), isfinite_float(x.w)} }
|
||||
isfinite_double :: proc "c" (x: double) -> bool { return !isinf_double(x) }
|
||||
isfinite_double2 :: proc "c" (x: double2) -> bool2 { return {isfinite_double(x.x), isfinite_double(x.y)} }
|
||||
isfinite_double3 :: proc "c" (x: double3) -> bool3 { return {isfinite_double(x.x), isfinite_double(x.y), isfinite_double(x.z)} }
|
||||
isfinite_double4 :: proc "c" (x: double4) -> bool4 { return {isfinite_double(x.x), isfinite_double(x.y), isfinite_double(x.z), isfinite_double(x.w)} }
|
||||
|
||||
// isfinite is the opposite of isinf and returns true if the number is neither positive-infinite or negative-infinite
|
||||
isfinite :: proc{
|
||||
isfinite_float,
|
||||
isfinite_float2,
|
||||
isfinite_float3,
|
||||
isfinite_float4,
|
||||
isfinite_double,
|
||||
isfinite_double2,
|
||||
isfinite_double3,
|
||||
isfinite_double4,
|
||||
}
|
||||
|
||||
|
||||
isinf_float :: proc "c" (x: float) -> bool { return x * 0.5 == x }
|
||||
isinf_float2 :: proc "c" (x: float2) -> bool2 { return {isinf_float(x.x), isinf_float(x.y)} }
|
||||
isinf_float3 :: proc "c" (x: float3) -> bool3 { return {isinf_float(x.x), isinf_float(x.y), isinf_float(x.z)} }
|
||||
isinf_float4 :: proc "c" (x: float4) -> bool4 { return {isinf_float(x.x), isinf_float(x.y), isinf_float(x.z), isinf_float(x.w)} }
|
||||
isinf_double :: proc "c" (x: double) -> bool { return x * 0.5 == x }
|
||||
isinf_double2 :: proc "c" (x: double2) -> bool2 { return {isinf_double(x.x), isinf_double(x.y)} }
|
||||
isinf_double3 :: proc "c" (x: double3) -> bool3 { return {isinf_double(x.x), isinf_double(x.y), isinf_double(x.z)} }
|
||||
isinf_double4 :: proc "c" (x: double4) -> bool4 { return {isinf_double(x.x), isinf_double(x.y), isinf_double(x.z), isinf_double(x.w)} }
|
||||
|
||||
// isinf is the opposite of isfinite and returns true if the number is either positive-infinite or negative-infinite
|
||||
isinf :: proc{
|
||||
isinf_float,
|
||||
isinf_float2,
|
||||
isinf_float3,
|
||||
isinf_float4,
|
||||
isinf_double,
|
||||
isinf_double2,
|
||||
isinf_double3,
|
||||
isinf_double4,
|
||||
}
|
||||
|
||||
|
||||
isnan_float2 :: proc "c" (x: float2) -> bool2 { return {isnan_float(x.x), isnan_float(x.y)} }
|
||||
isnan_float3 :: proc "c" (x: float3) -> bool3 { return {isnan_float(x.x), isnan_float(x.y), isnan_float(x.z)} }
|
||||
isnan_float4 :: proc "c" (x: float4) -> bool4 { return {isnan_float(x.x), isnan_float(x.y), isnan_float(x.z), isnan_float(x.w)} }
|
||||
isnan_double2 :: proc "c" (x: double2) -> bool2 { return {isnan_double(x.x), isnan_double(x.y)} }
|
||||
isnan_double3 :: proc "c" (x: double3) -> bool3 { return {isnan_double(x.x), isnan_double(x.y), isnan_double(x.z)} }
|
||||
isnan_double4 :: proc "c" (x: double4) -> bool4 { return {isnan_double(x.x), isnan_double(x.y), isnan_double(x.z), isnan_double(x.w)} }
|
||||
|
||||
// isnan returns true if the input value is the special case of Not-A-Number
|
||||
isnan :: proc{
|
||||
isnan_float,
|
||||
isnan_float2,
|
||||
isnan_float3,
|
||||
isnan_float4,
|
||||
isnan_double,
|
||||
isnan_double2,
|
||||
isnan_double3,
|
||||
isnan_double4,
|
||||
}
|
||||
|
||||
fmod :: proc{
|
||||
fmod_float,
|
||||
fmod_double,
|
||||
|
||||
@@ -26,7 +26,9 @@ log10_float :: proc "c" (x: float) -> float { return math.log(x, 10) }
|
||||
exp2_float :: proc "c" (x: float) -> float { return math.pow(float(2), x) }
|
||||
sign_float :: proc "c" (x: float) -> float { return math.sign(x) }
|
||||
floor_float :: proc "c" (x: float) -> float { return math.floor(x) }
|
||||
round_float :: proc "c" (x: float) -> float { return math.round(x) }
|
||||
ceil_float :: proc "c" (x: float) -> float { return math.ceil(x) }
|
||||
isnan_float :: proc "c" (x: float) -> bool { return math.classify(x) == .NaN}
|
||||
fmod_float :: proc "c" (x, y: float) -> float { return math.mod(x, y) }
|
||||
frac_float :: proc "c" (x: float) -> float {
|
||||
if x >= 0 {
|
||||
@@ -35,6 +37,7 @@ frac_float :: proc "c" (x: float) -> float {
|
||||
return math.trunc(-x) + x
|
||||
}
|
||||
|
||||
|
||||
cos_double :: proc "c" (x: double) -> double { return math.cos(x) }
|
||||
sin_double :: proc "c" (x: double) -> double { return math.sin(x) }
|
||||
tan_double :: proc "c" (x: double) -> double { return math.tan(x) }
|
||||
@@ -59,7 +62,9 @@ log10_double :: proc "c" (x: double) -> double { return math.log(x, 10)
|
||||
exp2_double :: proc "c" (x: double) -> double { return math.pow(double(2), x) }
|
||||
sign_double :: proc "c" (x: double) -> double { return math.sign(x) }
|
||||
floor_double :: proc "c" (x: double) -> double { return math.floor(x) }
|
||||
round_double :: proc "c" (x: double) -> double { return math.round(x) }
|
||||
ceil_double :: proc "c" (x: double) -> double { return math.ceil(x) }
|
||||
isnan_double :: proc "c" (x: double) -> bool { return math.classify(x) == .NaN}
|
||||
fmod_double :: proc "c" (x, y: double) -> double { return math.mod(x, y) }
|
||||
frac_double :: proc "c" (x: double) -> double {
|
||||
if x >= 0 {
|
||||
|
||||
@@ -0,0 +1,734 @@
|
||||
/*
|
||||
OpenSimplex2 noise implementation.
|
||||
|
||||
Ported from https://github.com/KdotJPG/OpenSimplex2.
|
||||
Copyright 2022 Yuki2 (https://github.com/NoahR02)
|
||||
*/
|
||||
//+private
|
||||
package math_noise
|
||||
|
||||
/*
|
||||
Private implementation details follow.
|
||||
*/
|
||||
|
||||
PRIME_X :: i64(0x5205402B9270C86F)
|
||||
PRIME_Y :: i64(0x598CD327003817B5)
|
||||
PRIME_Z :: i64(0x5BCC226E9FA0BACB)
|
||||
PRIME_W :: i64(0x56CC5227E58F554B)
|
||||
|
||||
HASH_MULTIPLIER :: i64(0x53A3F72DEEC546F5)
|
||||
SEED_FLIP_3D :: i64(-0x52D547B2E96ED629)
|
||||
SEED_OFFSET_4D :: i64(0xE83DC3E0DA7164D)
|
||||
|
||||
ROOT_2_OVER_2 :: f64(0.7071067811865476)
|
||||
SKEW_2D :: f64(0.366025403784439)
|
||||
UNSKEW_2D :: f64(-0.21132486540518713)
|
||||
ROOT_3_OVER_3 :: f64(0.577350269189626)
|
||||
|
||||
FALLBACK_ROTATE_3D :: f64(2.0) / f64(3.0)
|
||||
ROTATE_3D_ORTHOGONALIZER :: f64(UNSKEW_2D)
|
||||
|
||||
SKEW_4D :: f32(0hbe0d8369)
|
||||
UNSKEW_4D :: f32(0.309016994374947)
|
||||
LATTICE_STEP_4D :: f32(0.2)
|
||||
|
||||
N_GRADS_2D_EXPONENT :: 7
|
||||
N_GRADS_3D_EXPONENT :: 8
|
||||
N_GRADS_4D_EXPONENT :: 9
|
||||
N_GRADS_2D :: 1 << N_GRADS_2D_EXPONENT
|
||||
N_GRADS_3D :: 1 << N_GRADS_3D_EXPONENT
|
||||
N_GRADS_4D :: 1 << N_GRADS_4D_EXPONENT
|
||||
|
||||
NORMALIZER_2D :: f64(0.01001634121365712)
|
||||
NORMALIZER_3D :: f64(0.07969837668935331)
|
||||
NORMALIZER_4D :: f64(0.0220065933241897)
|
||||
RSQUARED_2D :: f32(0.5)
|
||||
RSQUARED_3D :: f32(0.6)
|
||||
RSQUARED_4D :: f32(0.6)
|
||||
|
||||
GRADIENTS_2D := [N_GRADS_2D * 2]f32{
|
||||
0h4218d2da, 0h42b87975, 0h42b87975, 0h4218d2da, 0h42b87975, 0hc218d2da, 0h4218d2da, 0hc2b87975,
|
||||
0hc218d2da, 0hc2b87975, 0hc2b87975, 0hc218d2da, 0hc2b87975, 0h4218d2da, 0hc218d2da, 0h42b87975,
|
||||
0h4150804d, 0h42c5f72a, 0h42731b78, 0h429e696c, 0h429e696c, 0h42731b78, 0h42c5f72a, 0h4150804d,
|
||||
0h42c5f72a, 0hc150804d, 0h429e696c, 0hc2731b78, 0h42731b78, 0hc29e696c, 0h4150804d, 0hc2c5f72a,
|
||||
0hc150804d, 0hc2c5f72a, 0hc2731b78, 0hc29e696c, 0hc29e696c, 0hc2731b78, 0hc2c5f72a, 0hc150804d,
|
||||
0hc2c5f72a, 0h4150804d, 0hc29e696c, 0h42731b78, 0hc2731b78, 0h429e696c, 0hc150804d, 0h42c5f72a,
|
||||
0h4218d2da, 0h42b87975, 0h42b87975, 0h4218d2da, 0h42b87975, 0hc218d2da, 0h4218d2da, 0hc2b87975,
|
||||
0hc218d2da, 0hc2b87975, 0hc2b87975, 0hc218d2da, 0hc2b87975, 0h4218d2da, 0hc218d2da, 0h42b87975,
|
||||
0h4150804d, 0h42c5f72a, 0h42731b78, 0h429e696c, 0h429e696c, 0h42731b78, 0h42c5f72a, 0h4150804d,
|
||||
0h42c5f72a, 0hc150804d, 0h429e696c, 0hc2731b78, 0h42731b78, 0hc29e696c, 0h4150804d, 0hc2c5f72a,
|
||||
0hc150804d, 0hc2c5f72a, 0hc2731b78, 0hc29e696c, 0hc29e696c, 0hc2731b78, 0hc2c5f72a, 0hc150804d,
|
||||
0hc2c5f72a, 0h4150804d, 0hc29e696c, 0h42731b78, 0hc2731b78, 0h429e696c, 0hc150804d, 0h42c5f72a,
|
||||
0h4218d2da, 0h42b87975, 0h42b87975, 0h4218d2da, 0h42b87975, 0hc218d2da, 0h4218d2da, 0hc2b87975,
|
||||
0hc218d2da, 0hc2b87975, 0hc2b87975, 0hc218d2da, 0hc2b87975, 0h4218d2da, 0hc218d2da, 0h42b87975,
|
||||
0h4150804d, 0h42c5f72a, 0h42731b78, 0h429e696c, 0h429e696c, 0h42731b78, 0h42c5f72a, 0h4150804d,
|
||||
0h42c5f72a, 0hc150804d, 0h429e696c, 0hc2731b78, 0h42731b78, 0hc29e696c, 0h4150804d, 0hc2c5f72a,
|
||||
0hc150804d, 0hc2c5f72a, 0hc2731b78, 0hc29e696c, 0hc29e696c, 0hc2731b78, 0hc2c5f72a, 0hc150804d,
|
||||
0hc2c5f72a, 0h4150804d, 0hc29e696c, 0h42731b78, 0hc2731b78, 0h429e696c, 0hc150804d, 0h42c5f72a,
|
||||
0h4218d2da, 0h42b87975, 0h42b87975, 0h4218d2da, 0h42b87975, 0hc218d2da, 0h4218d2da, 0hc2b87975,
|
||||
0hc218d2da, 0hc2b87975, 0hc2b87975, 0hc218d2da, 0hc2b87975, 0h4218d2da, 0hc218d2da, 0h42b87975,
|
||||
0h4150804d, 0h42c5f72a, 0h42731b78, 0h429e696c, 0h429e696c, 0h42731b78, 0h42c5f72a, 0h4150804d,
|
||||
0h42c5f72a, 0hc150804d, 0h429e696c, 0hc2731b78, 0h42731b78, 0hc29e696c, 0h4150804d, 0hc2c5f72a,
|
||||
0hc150804d, 0hc2c5f72a, 0hc2731b78, 0hc29e696c, 0hc29e696c, 0hc2731b78, 0hc2c5f72a, 0hc150804d,
|
||||
0hc2c5f72a, 0h4150804d, 0hc29e696c, 0h42731b78, 0hc2731b78, 0h429e696c, 0hc150804d, 0h42c5f72a,
|
||||
0h4218d2da, 0h42b87975, 0h42b87975, 0h4218d2da, 0h42b87975, 0hc218d2da, 0h4218d2da, 0hc2b87975,
|
||||
0hc218d2da, 0hc2b87975, 0hc2b87975, 0hc218d2da, 0hc2b87975, 0h4218d2da, 0hc218d2da, 0h42b87975,
|
||||
0h4150804d, 0h42c5f72a, 0h42731b78, 0h429e696c, 0h429e696c, 0h42731b78, 0h42c5f72a, 0h4150804d,
|
||||
0h42c5f72a, 0hc150804d, 0h429e696c, 0hc2731b78, 0h42731b78, 0hc29e696c, 0h4150804d, 0hc2c5f72a,
|
||||
0hc150804d, 0hc2c5f72a, 0hc2731b78, 0hc29e696c, 0hc29e696c, 0hc2731b78, 0hc2c5f72a, 0hc150804d,
|
||||
0hc2c5f72a, 0h4150804d, 0hc29e696c, 0h42731b78, 0hc2731b78, 0h429e696c, 0hc150804d, 0h42c5f72a,
|
||||
0h4218d2da, 0h42b87975, 0h42b87975, 0h4218d2da, 0h42b87975, 0hc218d2da, 0h4218d2da, 0hc2b87975,
|
||||
0hc218d2da, 0hc2b87975, 0hc2b87975, 0hc218d2da, 0hc2b87975, 0h4218d2da, 0hc218d2da, 0h42b87975,
|
||||
}
|
||||
|
||||
GRADIENTS_3D := [N_GRADS_3D * 4]f32{
|
||||
0h41df5103, 0h41df5103, 0hc148c1c5, 0h00000000, 0h41df5103, 0h41df5103, 0h4148c1c5, 0h00000000,
|
||||
0h421ae5b8, 0h416b5146, 0h00000000, 0h00000000, 0h416b5146, 0h421ae5b8, 0h00000000, 0h00000000,
|
||||
0hc1df5103, 0h41df5103, 0hc148c1c5, 0h00000000, 0hc1df5103, 0h41df5103, 0h4148c1c5, 0h00000000,
|
||||
0hc16b5146, 0h421ae5b8, 0h00000000, 0h00000000, 0hc21ae5b8, 0h416b5146, 0h00000000, 0h00000000,
|
||||
0hc148c1c5, 0hc1df5103, 0hc1df5103, 0h00000000, 0h4148c1c5, 0hc1df5103, 0hc1df5103, 0h00000000,
|
||||
0h00000000, 0hc21ae5b8, 0hc16b5146, 0h00000000, 0h00000000, 0hc16b5146, 0hc21ae5b8, 0h00000000,
|
||||
0hc148c1c5, 0hc1df5103, 0h41df5103, 0h00000000, 0h4148c1c5, 0hc1df5103, 0h41df5103, 0h00000000,
|
||||
0h00000000, 0hc16b5146, 0h421ae5b8, 0h00000000, 0h00000000, 0hc21ae5b8, 0h416b5146, 0h00000000,
|
||||
0hc1df5103, 0hc1df5103, 0hc148c1c5, 0h00000000, 0hc1df5103, 0hc1df5103, 0h4148c1c5, 0h00000000,
|
||||
0hc21ae5b8, 0hc16b5146, 0h00000000, 0h00000000, 0hc16b5146, 0hc21ae5b8, 0h00000000, 0h00000000,
|
||||
0hc1df5103, 0hc148c1c5, 0hc1df5103, 0h00000000, 0hc1df5103, 0h4148c1c5, 0hc1df5103, 0h00000000,
|
||||
0hc16b5146, 0h00000000, 0hc21ae5b8, 0h00000000, 0hc21ae5b8, 0h00000000, 0hc16b5146, 0h00000000,
|
||||
0hc1df5103, 0hc148c1c5, 0h41df5103, 0h00000000, 0hc1df5103, 0h4148c1c5, 0h41df5103, 0h00000000,
|
||||
0hc21ae5b8, 0h00000000, 0h416b5146, 0h00000000, 0hc16b5146, 0h00000000, 0h421ae5b8, 0h00000000,
|
||||
0hc148c1c5, 0h41df5103, 0hc1df5103, 0h00000000, 0h4148c1c5, 0h41df5103, 0hc1df5103, 0h00000000,
|
||||
0h00000000, 0h416b5146, 0hc21ae5b8, 0h00000000, 0h00000000, 0h421ae5b8, 0hc16b5146, 0h00000000,
|
||||
0hc148c1c5, 0h41df5103, 0h41df5103, 0h00000000, 0h4148c1c5, 0h41df5103, 0h41df5103, 0h00000000,
|
||||
0h00000000, 0h421ae5b8, 0h416b5146, 0h00000000, 0h00000000, 0h416b5146, 0h421ae5b8, 0h00000000,
|
||||
0h41df5103, 0hc1df5103, 0hc148c1c5, 0h00000000, 0h41df5103, 0hc1df5103, 0h4148c1c5, 0h00000000,
|
||||
0h416b5146, 0hc21ae5b8, 0h00000000, 0h00000000, 0h421ae5b8, 0hc16b5146, 0h00000000, 0h00000000,
|
||||
0h41df5103, 0hc148c1c5, 0hc1df5103, 0h00000000, 0h41df5103, 0h4148c1c5, 0hc1df5103, 0h00000000,
|
||||
0h421ae5b8, 0h00000000, 0hc16b5146, 0h00000000, 0h416b5146, 0h00000000, 0hc21ae5b8, 0h00000000,
|
||||
0h41df5103, 0hc148c1c5, 0h41df5103, 0h00000000, 0h41df5103, 0h4148c1c5, 0h41df5103, 0h00000000,
|
||||
0h416b5146, 0h00000000, 0h421ae5b8, 0h00000000, 0h421ae5b8, 0h00000000, 0h416b5146, 0h00000000,
|
||||
0h41df5103, 0h41df5103, 0hc148c1c5, 0h00000000, 0h41df5103, 0h41df5103, 0h4148c1c5, 0h00000000,
|
||||
0h421ae5b8, 0h416b5146, 0h00000000, 0h00000000, 0h416b5146, 0h421ae5b8, 0h00000000, 0h00000000,
|
||||
0hc1df5103, 0h41df5103, 0hc148c1c5, 0h00000000, 0hc1df5103, 0h41df5103, 0h4148c1c5, 0h00000000,
|
||||
0hc16b5146, 0h421ae5b8, 0h00000000, 0h00000000, 0hc21ae5b8, 0h416b5146, 0h00000000, 0h00000000,
|
||||
0hc148c1c5, 0hc1df5103, 0hc1df5103, 0h00000000, 0h4148c1c5, 0hc1df5103, 0hc1df5103, 0h00000000,
|
||||
0h00000000, 0hc21ae5b8, 0hc16b5146, 0h00000000, 0h00000000, 0hc16b5146, 0hc21ae5b8, 0h00000000,
|
||||
0hc148c1c5, 0hc1df5103, 0h41df5103, 0h00000000, 0h4148c1c5, 0hc1df5103, 0h41df5103, 0h00000000,
|
||||
0h00000000, 0hc16b5146, 0h421ae5b8, 0h00000000, 0h00000000, 0hc21ae5b8, 0h416b5146, 0h00000000,
|
||||
0hc1df5103, 0hc1df5103, 0hc148c1c5, 0h00000000, 0hc1df5103, 0hc1df5103, 0h4148c1c5, 0h00000000,
|
||||
0hc21ae5b8, 0hc16b5146, 0h00000000, 0h00000000, 0hc16b5146, 0hc21ae5b8, 0h00000000, 0h00000000,
|
||||
0hc1df5103, 0hc148c1c5, 0hc1df5103, 0h00000000, 0hc1df5103, 0h4148c1c5, 0hc1df5103, 0h00000000,
|
||||
0hc16b5146, 0h00000000, 0hc21ae5b8, 0h00000000, 0hc21ae5b8, 0h00000000, 0hc16b5146, 0h00000000,
|
||||
0hc1df5103, 0hc148c1c5, 0h41df5103, 0h00000000, 0hc1df5103, 0h4148c1c5, 0h41df5103, 0h00000000,
|
||||
0hc21ae5b8, 0h00000000, 0h416b5146, 0h00000000, 0hc16b5146, 0h00000000, 0h421ae5b8, 0h00000000,
|
||||
0hc148c1c5, 0h41df5103, 0hc1df5103, 0h00000000, 0h4148c1c5, 0h41df5103, 0hc1df5103, 0h00000000,
|
||||
0h00000000, 0h416b5146, 0hc21ae5b8, 0h00000000, 0h00000000, 0h421ae5b8, 0hc16b5146, 0h00000000,
|
||||
0hc148c1c5, 0h41df5103, 0h41df5103, 0h00000000, 0h4148c1c5, 0h41df5103, 0h41df5103, 0h00000000,
|
||||
0h00000000, 0h421ae5b8, 0h416b5146, 0h00000000, 0h00000000, 0h416b5146, 0h421ae5b8, 0h00000000,
|
||||
0h41df5103, 0hc1df5103, 0hc148c1c5, 0h00000000, 0h41df5103, 0hc1df5103, 0h4148c1c5, 0h00000000,
|
||||
0h416b5146, 0hc21ae5b8, 0h00000000, 0h00000000, 0h421ae5b8, 0hc16b5146, 0h00000000, 0h00000000,
|
||||
0h41df5103, 0hc148c1c5, 0hc1df5103, 0h00000000, 0h41df5103, 0h4148c1c5, 0hc1df5103, 0h00000000,
|
||||
0h421ae5b8, 0h00000000, 0hc16b5146, 0h00000000, 0h416b5146, 0h00000000, 0hc21ae5b8, 0h00000000,
|
||||
0h41df5103, 0hc148c1c5, 0h41df5103, 0h00000000, 0h41df5103, 0h4148c1c5, 0h41df5103, 0h00000000,
|
||||
0h416b5146, 0h00000000, 0h421ae5b8, 0h00000000, 0h421ae5b8, 0h00000000, 0h416b5146, 0h00000000,
|
||||
0h41df5103, 0h41df5103, 0hc148c1c5, 0h00000000, 0h41df5103, 0h41df5103, 0h4148c1c5, 0h00000000,
|
||||
0h421ae5b8, 0h416b5146, 0h00000000, 0h00000000, 0h416b5146, 0h421ae5b8, 0h00000000, 0h00000000,
|
||||
0hc1df5103, 0h41df5103, 0hc148c1c5, 0h00000000, 0hc1df5103, 0h41df5103, 0h4148c1c5, 0h00000000,
|
||||
0hc16b5146, 0h421ae5b8, 0h00000000, 0h00000000, 0hc21ae5b8, 0h416b5146, 0h00000000, 0h00000000,
|
||||
0hc148c1c5, 0hc1df5103, 0hc1df5103, 0h00000000, 0h4148c1c5, 0hc1df5103, 0hc1df5103, 0h00000000,
|
||||
0h00000000, 0hc21ae5b8, 0hc16b5146, 0h00000000, 0h00000000, 0hc16b5146, 0hc21ae5b8, 0h00000000,
|
||||
0hc148c1c5, 0hc1df5103, 0h41df5103, 0h00000000, 0h4148c1c5, 0hc1df5103, 0h41df5103, 0h00000000,
|
||||
0h00000000, 0hc16b5146, 0h421ae5b8, 0h00000000, 0h00000000, 0hc21ae5b8, 0h416b5146, 0h00000000,
|
||||
0hc1df5103, 0hc1df5103, 0hc148c1c5, 0h00000000, 0hc1df5103, 0hc1df5103, 0h4148c1c5, 0h00000000,
|
||||
0hc21ae5b8, 0hc16b5146, 0h00000000, 0h00000000, 0hc16b5146, 0hc21ae5b8, 0h00000000, 0h00000000,
|
||||
0hc1df5103, 0hc148c1c5, 0hc1df5103, 0h00000000, 0hc1df5103, 0h4148c1c5, 0hc1df5103, 0h00000000,
|
||||
0hc16b5146, 0h00000000, 0hc21ae5b8, 0h00000000, 0hc21ae5b8, 0h00000000, 0hc16b5146, 0h00000000,
|
||||
0hc1df5103, 0hc148c1c5, 0h41df5103, 0h00000000, 0hc1df5103, 0h4148c1c5, 0h41df5103, 0h00000000,
|
||||
0hc21ae5b8, 0h00000000, 0h416b5146, 0h00000000, 0hc16b5146, 0h00000000, 0h421ae5b8, 0h00000000,
|
||||
0hc148c1c5, 0h41df5103, 0hc1df5103, 0h00000000, 0h4148c1c5, 0h41df5103, 0hc1df5103, 0h00000000,
|
||||
0h00000000, 0h416b5146, 0hc21ae5b8, 0h00000000, 0h00000000, 0h421ae5b8, 0hc16b5146, 0h00000000,
|
||||
0hc148c1c5, 0h41df5103, 0h41df5103, 0h00000000, 0h4148c1c5, 0h41df5103, 0h41df5103, 0h00000000,
|
||||
0h00000000, 0h421ae5b8, 0h416b5146, 0h00000000, 0h00000000, 0h416b5146, 0h421ae5b8, 0h00000000,
|
||||
0h41df5103, 0hc1df5103, 0hc148c1c5, 0h00000000, 0h41df5103, 0hc1df5103, 0h4148c1c5, 0h00000000,
|
||||
0h416b5146, 0hc21ae5b8, 0h00000000, 0h00000000, 0h421ae5b8, 0hc16b5146, 0h00000000, 0h00000000,
|
||||
0h41df5103, 0hc148c1c5, 0hc1df5103, 0h00000000, 0h41df5103, 0h4148c1c5, 0hc1df5103, 0h00000000,
|
||||
0h421ae5b8, 0h00000000, 0hc16b5146, 0h00000000, 0h416b5146, 0h00000000, 0hc21ae5b8, 0h00000000,
|
||||
0h41df5103, 0hc148c1c5, 0h41df5103, 0h00000000, 0h41df5103, 0h4148c1c5, 0h41df5103, 0h00000000,
|
||||
0h416b5146, 0h00000000, 0h421ae5b8, 0h00000000, 0h421ae5b8, 0h00000000, 0h416b5146, 0h00000000,
|
||||
0h41df5103, 0h41df5103, 0hc148c1c5, 0h00000000, 0h41df5103, 0h41df5103, 0h4148c1c5, 0h00000000,
|
||||
0h421ae5b8, 0h416b5146, 0h00000000, 0h00000000, 0h416b5146, 0h421ae5b8, 0h00000000, 0h00000000,
|
||||
0hc1df5103, 0h41df5103, 0hc148c1c5, 0h00000000, 0hc1df5103, 0h41df5103, 0h4148c1c5, 0h00000000,
|
||||
0hc16b5146, 0h421ae5b8, 0h00000000, 0h00000000, 0hc21ae5b8, 0h416b5146, 0h00000000, 0h00000000,
|
||||
0hc148c1c5, 0hc1df5103, 0hc1df5103, 0h00000000, 0h4148c1c5, 0hc1df5103, 0hc1df5103, 0h00000000,
|
||||
0h00000000, 0hc21ae5b8, 0hc16b5146, 0h00000000, 0h00000000, 0hc16b5146, 0hc21ae5b8, 0h00000000,
|
||||
0hc148c1c5, 0hc1df5103, 0h41df5103, 0h00000000, 0h4148c1c5, 0hc1df5103, 0h41df5103, 0h00000000,
|
||||
0h00000000, 0hc16b5146, 0h421ae5b8, 0h00000000, 0h00000000, 0hc21ae5b8, 0h416b5146, 0h00000000,
|
||||
0hc1df5103, 0hc1df5103, 0hc148c1c5, 0h00000000, 0hc1df5103, 0hc1df5103, 0h4148c1c5, 0h00000000,
|
||||
0hc21ae5b8, 0hc16b5146, 0h00000000, 0h00000000, 0hc16b5146, 0hc21ae5b8, 0h00000000, 0h00000000,
|
||||
0hc1df5103, 0hc148c1c5, 0hc1df5103, 0h00000000, 0hc1df5103, 0h4148c1c5, 0hc1df5103, 0h00000000,
|
||||
0hc16b5146, 0h00000000, 0hc21ae5b8, 0h00000000, 0hc21ae5b8, 0h00000000, 0hc16b5146, 0h00000000,
|
||||
0hc1df5103, 0hc148c1c5, 0h41df5103, 0h00000000, 0hc1df5103, 0h4148c1c5, 0h41df5103, 0h00000000,
|
||||
0hc21ae5b8, 0h00000000, 0h416b5146, 0h00000000, 0hc16b5146, 0h00000000, 0h421ae5b8, 0h00000000,
|
||||
0hc148c1c5, 0h41df5103, 0hc1df5103, 0h00000000, 0h4148c1c5, 0h41df5103, 0hc1df5103, 0h00000000,
|
||||
0h00000000, 0h416b5146, 0hc21ae5b8, 0h00000000, 0h00000000, 0h421ae5b8, 0hc16b5146, 0h00000000,
|
||||
0hc148c1c5, 0h41df5103, 0h41df5103, 0h00000000, 0h4148c1c5, 0h41df5103, 0h41df5103, 0h00000000,
|
||||
0h00000000, 0h421ae5b8, 0h416b5146, 0h00000000, 0h00000000, 0h416b5146, 0h421ae5b8, 0h00000000,
|
||||
0h41df5103, 0hc1df5103, 0hc148c1c5, 0h00000000, 0h41df5103, 0hc1df5103, 0h4148c1c5, 0h00000000,
|
||||
0h416b5146, 0hc21ae5b8, 0h00000000, 0h00000000, 0h421ae5b8, 0hc16b5146, 0h00000000, 0h00000000,
|
||||
0h41df5103, 0hc148c1c5, 0hc1df5103, 0h00000000, 0h41df5103, 0h4148c1c5, 0hc1df5103, 0h00000000,
|
||||
0h421ae5b8, 0h00000000, 0hc16b5146, 0h00000000, 0h416b5146, 0h00000000, 0hc21ae5b8, 0h00000000,
|
||||
0h41df5103, 0hc148c1c5, 0h41df5103, 0h00000000, 0h41df5103, 0h4148c1c5, 0h41df5103, 0h00000000,
|
||||
0h416b5146, 0h00000000, 0h421ae5b8, 0h00000000, 0h421ae5b8, 0h00000000, 0h416b5146, 0h00000000,
|
||||
0h41df5103, 0h41df5103, 0hc148c1c5, 0h00000000, 0h41df5103, 0h41df5103, 0h4148c1c5, 0h00000000,
|
||||
0h421ae5b8, 0h416b5146, 0h00000000, 0h00000000, 0h416b5146, 0h421ae5b8, 0h00000000, 0h00000000,
|
||||
0hc1df5103, 0h41df5103, 0hc148c1c5, 0h00000000, 0hc1df5103, 0h41df5103, 0h4148c1c5, 0h00000000,
|
||||
0hc16b5146, 0h421ae5b8, 0h00000000, 0h00000000, 0hc21ae5b8, 0h416b5146, 0h00000000, 0h00000000,
|
||||
0hc148c1c5, 0hc1df5103, 0hc1df5103, 0h00000000, 0h4148c1c5, 0hc1df5103, 0hc1df5103, 0h00000000,
|
||||
0h00000000, 0hc21ae5b8, 0hc16b5146, 0h00000000, 0h00000000, 0hc16b5146, 0hc21ae5b8, 0h00000000,
|
||||
0hc148c1c5, 0hc1df5103, 0h41df5103, 0h00000000, 0h4148c1c5, 0hc1df5103, 0h41df5103, 0h00000000,
|
||||
0h00000000, 0hc16b5146, 0h421ae5b8, 0h00000000, 0h00000000, 0hc21ae5b8, 0h416b5146, 0h00000000,
|
||||
0hc1df5103, 0hc1df5103, 0hc148c1c5, 0h00000000, 0hc1df5103, 0hc1df5103, 0h4148c1c5, 0h00000000,
|
||||
0hc21ae5b8, 0hc16b5146, 0h00000000, 0h00000000, 0hc16b5146, 0hc21ae5b8, 0h00000000, 0h00000000,
|
||||
0hc1df5103, 0hc148c1c5, 0hc1df5103, 0h00000000, 0hc1df5103, 0h4148c1c5, 0hc1df5103, 0h00000000,
|
||||
0hc16b5146, 0h00000000, 0hc21ae5b8, 0h00000000, 0hc21ae5b8, 0h00000000, 0hc16b5146, 0h00000000,
|
||||
0hc1df5103, 0hc148c1c5, 0h41df5103, 0h00000000, 0hc1df5103, 0h4148c1c5, 0h41df5103, 0h00000000,
|
||||
0hc21ae5b8, 0h00000000, 0h416b5146, 0h00000000, 0hc16b5146, 0h00000000, 0h421ae5b8, 0h00000000,
|
||||
0hc148c1c5, 0h41df5103, 0hc1df5103, 0h00000000, 0h4148c1c5, 0h41df5103, 0hc1df5103, 0h00000000,
|
||||
0h00000000, 0h416b5146, 0hc21ae5b8, 0h00000000, 0h00000000, 0h421ae5b8, 0hc16b5146, 0h00000000,
|
||||
0hc148c1c5, 0h41df5103, 0h41df5103, 0h00000000, 0h4148c1c5, 0h41df5103, 0h41df5103, 0h00000000,
|
||||
0h00000000, 0h421ae5b8, 0h416b5146, 0h00000000, 0h00000000, 0h416b5146, 0h421ae5b8, 0h00000000,
|
||||
0h41df5103, 0hc1df5103, 0hc148c1c5, 0h00000000, 0h41df5103, 0hc1df5103, 0h4148c1c5, 0h00000000,
|
||||
0h416b5146, 0hc21ae5b8, 0h00000000, 0h00000000, 0h421ae5b8, 0hc16b5146, 0h00000000, 0h00000000,
|
||||
0h41df5103, 0hc148c1c5, 0hc1df5103, 0h00000000, 0h41df5103, 0h4148c1c5, 0hc1df5103, 0h00000000,
|
||||
0h421ae5b8, 0h00000000, 0hc16b5146, 0h00000000, 0h416b5146, 0h00000000, 0hc21ae5b8, 0h00000000,
|
||||
0h41df5103, 0hc148c1c5, 0h41df5103, 0h00000000, 0h41df5103, 0h4148c1c5, 0h41df5103, 0h00000000,
|
||||
0h416b5146, 0h00000000, 0h421ae5b8, 0h00000000, 0h421ae5b8, 0h00000000, 0h416b5146, 0h00000000,
|
||||
0h41df5103, 0h41df5103, 0hc148c1c5, 0h00000000, 0h41df5103, 0h41df5103, 0h4148c1c5, 0h00000000,
|
||||
0h421ae5b8, 0h416b5146, 0h00000000, 0h00000000, 0h416b5146, 0h421ae5b8, 0h00000000, 0h00000000,
|
||||
0hc1df5103, 0h41df5103, 0hc148c1c5, 0h00000000, 0hc1df5103, 0h41df5103, 0h4148c1c5, 0h00000000,
|
||||
0hc16b5146, 0h421ae5b8, 0h00000000, 0h00000000, 0hc21ae5b8, 0h416b5146, 0h00000000, 0h00000000,
|
||||
0hc148c1c5, 0hc1df5103, 0hc1df5103, 0h00000000, 0h4148c1c5, 0hc1df5103, 0hc1df5103, 0h00000000,
|
||||
0h00000000, 0hc21ae5b8, 0hc16b5146, 0h00000000, 0h00000000, 0hc16b5146, 0hc21ae5b8, 0h00000000,
|
||||
0hc148c1c5, 0hc1df5103, 0h41df5103, 0h00000000, 0h4148c1c5, 0hc1df5103, 0h41df5103, 0h00000000,
|
||||
0h00000000, 0hc16b5146, 0h421ae5b8, 0h00000000, 0h00000000, 0hc21ae5b8, 0h416b5146, 0h00000000,
|
||||
}
|
||||
|
||||
GRADIENTS_4D := [N_GRADS_4D * 4]f32{
|
||||
0hc1f50507, 0hc16b8e00, 0hc16b8e00, 0h41d2a716, 0hc208695c, 0hc19194b0, 0h40de6d7d, 0h41b6d966,
|
||||
0hc208695c, 0h40de6d7d, 0hc19194b0, 0h41b6d966, 0hc22076c5, 0h406d72bf, 0h406d72bf, 0h41a58418,
|
||||
0hc1a58418, 0hc06d72bf, 0hc06d72bf, 0h422076c5, 0hc1b6d966, 0hc0de6d7d, 0h419194b0, 0h4208695c,
|
||||
0hc1b6d966, 0h419194b0, 0hc0de6d7d, 0h4208695c, 0hc1d2a716, 0h416b8e00, 0h416b8e00, 0h41f50507,
|
||||
0hc1f50507, 0hc16b8e00, 0h41d2a716, 0hc16b8e00, 0hc208695c, 0hc19194b0, 0h41b6d966, 0h40de6d7d,
|
||||
0hc208695c, 0h40de6d7d, 0h41b6d966, 0hc19194b0, 0hc22076c5, 0h406d72bf, 0h41a58418, 0h406d72bf,
|
||||
0hc1a58418, 0hc06d72bf, 0h422076c5, 0hc06d72bf, 0hc1b6d966, 0hc0de6d7d, 0h4208695c, 0h419194b0,
|
||||
0hc1b6d966, 0h419194b0, 0h4208695c, 0hc0de6d7d, 0hc1d2a716, 0h416b8e00, 0h41f50507, 0h416b8e00,
|
||||
0hc1f50507, 0h41d2a716, 0hc16b8e00, 0hc16b8e00, 0hc208695c, 0h41b6d966, 0hc19194b0, 0h40de6d7d,
|
||||
0hc208695c, 0h41b6d966, 0h40de6d7d, 0hc19194b0, 0hc22076c5, 0h41a58418, 0h406d72bf, 0h406d72bf,
|
||||
0hc1a58418, 0h422076c5, 0hc06d72bf, 0hc06d72bf, 0hc1b6d966, 0h4208695c, 0hc0de6d7d, 0h419194b0,
|
||||
0hc1b6d966, 0h4208695c, 0h419194b0, 0hc0de6d7d, 0hc1d2a716, 0h41f50507, 0h416b8e00, 0h416b8e00,
|
||||
0h41d2a716, 0hc1f50507, 0hc16b8e00, 0hc16b8e00, 0h41b6d966, 0hc208695c, 0hc19194b0, 0h40de6d7d,
|
||||
0h41b6d966, 0hc208695c, 0h40de6d7d, 0hc19194b0, 0h41a58418, 0hc22076c5, 0h406d72bf, 0h406d72bf,
|
||||
0h422076c5, 0hc1a58418, 0hc06d72bf, 0hc06d72bf, 0h4208695c, 0hc1b6d966, 0hc0de6d7d, 0h419194b0,
|
||||
0h4208695c, 0hc1b6d966, 0h419194b0, 0hc0de6d7d, 0h41f50507, 0hc1d2a716, 0h416b8e00, 0h416b8e00,
|
||||
0hc208ee18, 0hc18a0670, 0hc18a0670, 0hc18a0670, 0hc20e2b7a, 0hc19d18ee, 0hc19d18ee, 0h40b05c85,
|
||||
0hc20e2b7a, 0hc19d18ee, 0h40b05c85, 0hc19d18ee, 0hc20e2b7a, 0h40b05c85, 0hc19d18ee, 0hc19d18ee,
|
||||
0hc21c1252, 0hc1b8e69d, 0h40024b8d, 0h40024b8d, 0hc21c1252, 0h40024b8d, 0hc1b8e69d, 0h40024b8d,
|
||||
0hc21c1252, 0h40024b8d, 0h40024b8d, 0hc1b8e69d, 0hc235739c, 0hbfc4b564, 0hbfc4b564, 0hbfc4b564,
|
||||
0hc18a0670, 0hc208ee18, 0hc18a0670, 0hc18a0670, 0hc19d18ee, 0hc20e2b7a, 0hc19d18ee, 0h40b05c85,
|
||||
0hc19d18ee, 0hc20e2b7a, 0h40b05c85, 0hc19d18ee, 0h40b05c85, 0hc20e2b7a, 0hc19d18ee, 0hc19d18ee,
|
||||
0hc1b8e69d, 0hc21c1252, 0h40024b8d, 0h40024b8d, 0h40024b8d, 0hc21c1252, 0hc1b8e69d, 0h40024b8d,
|
||||
0h40024b8d, 0hc21c1252, 0h40024b8d, 0hc1b8e69d, 0hbfc4b564, 0hc235739c, 0hbfc4b564, 0hbfc4b564,
|
||||
0hc18a0670, 0hc18a0670, 0hc208ee18, 0hc18a0670, 0hc19d18ee, 0hc19d18ee, 0hc20e2b7a, 0h40b05c85,
|
||||
0hc19d18ee, 0h40b05c85, 0hc20e2b7a, 0hc19d18ee, 0h40b05c85, 0hc19d18ee, 0hc20e2b7a, 0hc19d18ee,
|
||||
0hc1b8e69d, 0h40024b8d, 0hc21c1252, 0h40024b8d, 0h40024b8d, 0hc1b8e69d, 0hc21c1252, 0h40024b8d,
|
||||
0h40024b8d, 0h40024b8d, 0hc21c1252, 0hc1b8e69d, 0hbfc4b564, 0hbfc4b564, 0hc235739c, 0hbfc4b564,
|
||||
0hc18a0670, 0hc18a0670, 0hc18a0670, 0hc208ee18, 0hc19d18ee, 0hc19d18ee, 0h40b05c85, 0hc20e2b7a,
|
||||
0hc19d18ee, 0h40b05c85, 0hc19d18ee, 0hc20e2b7a, 0h40b05c85, 0hc19d18ee, 0hc19d18ee, 0hc20e2b7a,
|
||||
0hc1b8e69d, 0h40024b8d, 0h40024b8d, 0hc21c1252, 0h40024b8d, 0hc1b8e69d, 0h40024b8d, 0hc21c1252,
|
||||
0h40024b8d, 0h40024b8d, 0hc1b8e69d, 0hc21c1252, 0hbfc4b564, 0hbfc4b564, 0hbfc4b564, 0hc235739c,
|
||||
0hc16b8e00, 0hc1f50507, 0hc16b8e00, 0h41d2a716, 0hc19194b0, 0hc208695c, 0h40de6d7d, 0h41b6d966,
|
||||
0h40de6d7d, 0hc208695c, 0hc19194b0, 0h41b6d966, 0h406d72bf, 0hc22076c5, 0h406d72bf, 0h41a58418,
|
||||
0hc06d72bf, 0hc1a58418, 0hc06d72bf, 0h422076c5, 0hc0de6d7d, 0hc1b6d966, 0h419194b0, 0h4208695c,
|
||||
0h419194b0, 0hc1b6d966, 0hc0de6d7d, 0h4208695c, 0h416b8e00, 0hc1d2a716, 0h416b8e00, 0h41f50507,
|
||||
0hc16b8e00, 0hc16b8e00, 0hc1f50507, 0h41d2a716, 0hc19194b0, 0h40de6d7d, 0hc208695c, 0h41b6d966,
|
||||
0h40de6d7d, 0hc19194b0, 0hc208695c, 0h41b6d966, 0h406d72bf, 0h406d72bf, 0hc22076c5, 0h41a58418,
|
||||
0hc06d72bf, 0hc06d72bf, 0hc1a58418, 0h422076c5, 0hc0de6d7d, 0h419194b0, 0hc1b6d966, 0h4208695c,
|
||||
0h419194b0, 0hc0de6d7d, 0hc1b6d966, 0h4208695c, 0h416b8e00, 0h416b8e00, 0hc1d2a716, 0h41f50507,
|
||||
0hc16b8e00, 0hc1f50507, 0h41d2a716, 0hc16b8e00, 0hc19194b0, 0hc208695c, 0h41b6d966, 0h40de6d7d,
|
||||
0h40de6d7d, 0hc208695c, 0h41b6d966, 0hc19194b0, 0h406d72bf, 0hc22076c5, 0h41a58418, 0h406d72bf,
|
||||
0hc06d72bf, 0hc1a58418, 0h422076c5, 0hc06d72bf, 0hc0de6d7d, 0hc1b6d966, 0h4208695c, 0h419194b0,
|
||||
0h419194b0, 0hc1b6d966, 0h4208695c, 0hc0de6d7d, 0h416b8e00, 0hc1d2a716, 0h41f50507, 0h416b8e00,
|
||||
0hc16b8e00, 0hc16b8e00, 0h41d2a716, 0hc1f50507, 0hc19194b0, 0h40de6d7d, 0h41b6d966, 0hc208695c,
|
||||
0h40de6d7d, 0hc19194b0, 0h41b6d966, 0hc208695c, 0h406d72bf, 0h406d72bf, 0h41a58418, 0hc22076c5,
|
||||
0hc06d72bf, 0hc06d72bf, 0h422076c5, 0hc1a58418, 0hc0de6d7d, 0h419194b0, 0h4208695c, 0hc1b6d966,
|
||||
0h419194b0, 0hc0de6d7d, 0h4208695c, 0hc1b6d966, 0h416b8e00, 0h416b8e00, 0h41f50507, 0hc1d2a716,
|
||||
0hc16b8e00, 0h41d2a716, 0hc1f50507, 0hc16b8e00, 0hc19194b0, 0h41b6d966, 0hc208695c, 0h40de6d7d,
|
||||
0h40de6d7d, 0h41b6d966, 0hc208695c, 0hc19194b0, 0h406d72bf, 0h41a58418, 0hc22076c5, 0h406d72bf,
|
||||
0hc06d72bf, 0h422076c5, 0hc1a58418, 0hc06d72bf, 0hc0de6d7d, 0h4208695c, 0hc1b6d966, 0h419194b0,
|
||||
0h419194b0, 0h4208695c, 0hc1b6d966, 0hc0de6d7d, 0h416b8e00, 0h41f50507, 0hc1d2a716, 0h416b8e00,
|
||||
0hc16b8e00, 0h41d2a716, 0hc16b8e00, 0hc1f50507, 0hc19194b0, 0h41b6d966, 0h40de6d7d, 0hc208695c,
|
||||
0h40de6d7d, 0h41b6d966, 0hc19194b0, 0hc208695c, 0h406d72bf, 0h41a58418, 0h406d72bf, 0hc22076c5,
|
||||
0hc06d72bf, 0h422076c5, 0hc06d72bf, 0hc1a58418, 0hc0de6d7d, 0h4208695c, 0h419194b0, 0hc1b6d966,
|
||||
0h419194b0, 0h4208695c, 0hc0de6d7d, 0hc1b6d966, 0h416b8e00, 0h41f50507, 0h416b8e00, 0hc1d2a716,
|
||||
0h41d2a716, 0hc16b8e00, 0hc1f50507, 0hc16b8e00, 0h41b6d966, 0hc19194b0, 0hc208695c, 0h40de6d7d,
|
||||
0h41b6d966, 0h40de6d7d, 0hc208695c, 0hc19194b0, 0h41a58418, 0h406d72bf, 0hc22076c5, 0h406d72bf,
|
||||
0h422076c5, 0hc06d72bf, 0hc1a58418, 0hc06d72bf, 0h4208695c, 0hc0de6d7d, 0hc1b6d966, 0h419194b0,
|
||||
0h4208695c, 0h419194b0, 0hc1b6d966, 0hc0de6d7d, 0h41f50507, 0h416b8e00, 0hc1d2a716, 0h416b8e00,
|
||||
0h41d2a716, 0hc16b8e00, 0hc16b8e00, 0hc1f50507, 0h41b6d966, 0hc19194b0, 0h40de6d7d, 0hc208695c,
|
||||
0h41b6d966, 0h40de6d7d, 0hc19194b0, 0hc208695c, 0h41a58418, 0h406d72bf, 0h406d72bf, 0hc22076c5,
|
||||
0h422076c5, 0hc06d72bf, 0hc06d72bf, 0hc1a58418, 0h4208695c, 0hc0de6d7d, 0h419194b0, 0hc1b6d966,
|
||||
0h4208695c, 0h419194b0, 0hc0de6d7d, 0hc1b6d966, 0h41f50507, 0h416b8e00, 0h416b8e00, 0hc1d2a716,
|
||||
0h3fc4b564, 0h3fc4b564, 0h3fc4b564, 0h4235739c, 0hc0024b8d, 0hc0024b8d, 0h41b8e69d, 0h421c1252,
|
||||
0hc0024b8d, 0h41b8e69d, 0hc0024b8d, 0h421c1252, 0hc0b05c85, 0h419d18ee, 0h419d18ee, 0h420e2b7a,
|
||||
0h41b8e69d, 0hc0024b8d, 0hc0024b8d, 0h421c1252, 0h419d18ee, 0hc0b05c85, 0h419d18ee, 0h420e2b7a,
|
||||
0h419d18ee, 0h419d18ee, 0hc0b05c85, 0h420e2b7a, 0h418a0670, 0h418a0670, 0h418a0670, 0h4208ee18,
|
||||
0h3fc4b564, 0h3fc4b564, 0h4235739c, 0h3fc4b564, 0hc0024b8d, 0h40024b8d, 0h421c1252, 0h41b8e69d,
|
||||
0hc0024b8d, 0h41b8e69d, 0h421c1252, 0hc0024b8d, 0hc0b05c85, 0h419d18ee, 0h420e2b7a, 0h419d18ee,
|
||||
0h41b8e69d, 0hc0024b8d, 0h421c1252, 0hc0024b8d, 0h419d18ee, 0hc0b05c85, 0h420e2b7a, 0h419d18ee,
|
||||
0h419d18ee, 0h419d18ee, 0h420e2b7a, 0hc0b05c85, 0h418a0670, 0h418a0670, 0h4208ee18, 0h418a0670,
|
||||
0h3fc4b564, 0h4235739c, 0h3fc4b564, 0h3fc4b564, 0hc0024b8d, 0h421c1252, 0hc0024b8d, 0h41b8e69d,
|
||||
0hc0024b8d, 0h421c1252, 0h41b8e69d, 0hc0024b8d, 0hc0b05c85, 0h420e2b7a, 0h419d18ee, 0h419d18ee,
|
||||
0h41b8e69d, 0h421c1252, 0hc0024b8d, 0hc0024b8d, 0h419d18ee, 0h420e2b7a, 0hc0b05c85, 0h419d18ee,
|
||||
0h419d18ee, 0h420e2b7a, 0h419d18ee, 0hc0b05c85, 0h418a0670, 0h4208ee18, 0h418a0670, 0h418a0670,
|
||||
0h4235739c, 0h3fc4b564, 0h3fc4b564, 0h3fc4b564, 0h421c1252, 0hc0024b8d, 0hc0024b8d, 0h41b8e69d,
|
||||
0h421c1252, 0hc0024b8d, 0h41b8e69d, 0hc0024b8d, 0h420e2b7a, 0hc0b05c85, 0h419d18ee, 0h419d18ee,
|
||||
0h421c1252, 0h41b8e69d, 0hc0024b8d, 0hc0024b8d, 0h420e2b7a, 0h419d18ee, 0hc0b05c85, 0h419d18ee,
|
||||
0h420e2b7a, 0h419d18ee, 0h419d18ee, 0hc0b05c85, 0h4208ee18, 0h418a0670, 0h418a0670, 0h418a0670,
|
||||
0hc1f50507, 0hc16b8e00, 0hc16b8e00, 0h41d2a716, 0hc208695c, 0hc19194b0, 0h40de6d7d, 0h41b6d966,
|
||||
0hc208695c, 0h40de6d7d, 0hc19194b0, 0h41b6d966, 0hc22076c5, 0h406d72bf, 0h406d72bf, 0h41a58418,
|
||||
0hc1a58418, 0hc06d72bf, 0hc06d72bf, 0h422076c5, 0hc1b6d966, 0hc0de6d7d, 0h419194b0, 0h4208695c,
|
||||
0hc1b6d966, 0h419194b0, 0hc0de6d7d, 0h4208695c, 0hc1d2a716, 0h416b8e00, 0h416b8e00, 0h41f50507,
|
||||
0hc1f50507, 0hc16b8e00, 0h41d2a716, 0hc16b8e00, 0hc208695c, 0hc19194b0, 0h41b6d966, 0h40de6d7d,
|
||||
0hc208695c, 0h40de6d7d, 0h41b6d966, 0hc19194b0, 0hc22076c5, 0h406d72bf, 0h41a58418, 0h406d72bf,
|
||||
0hc1a58418, 0hc06d72bf, 0h422076c5, 0hc06d72bf, 0hc1b6d966, 0hc0de6d7d, 0h4208695c, 0h419194b0,
|
||||
0hc1b6d966, 0h419194b0, 0h4208695c, 0hc0de6d7d, 0hc1d2a716, 0h416b8e00, 0h41f50507, 0h416b8e00,
|
||||
0hc1f50507, 0h41d2a716, 0hc16b8e00, 0hc16b8e00, 0hc208695c, 0h41b6d966, 0hc19194b0, 0h40de6d7d,
|
||||
0hc208695c, 0h41b6d966, 0h40de6d7d, 0hc19194b0, 0hc22076c5, 0h41a58418, 0h406d72bf, 0h406d72bf,
|
||||
0hc1a58418, 0h422076c5, 0hc06d72bf, 0hc06d72bf, 0hc1b6d966, 0h4208695c, 0hc0de6d7d, 0h419194b0,
|
||||
0hc1b6d966, 0h4208695c, 0h419194b0, 0hc0de6d7d, 0hc1d2a716, 0h41f50507, 0h416b8e00, 0h416b8e00,
|
||||
0h41d2a716, 0hc1f50507, 0hc16b8e00, 0hc16b8e00, 0h41b6d966, 0hc208695c, 0hc19194b0, 0h40de6d7d,
|
||||
0h41b6d966, 0hc208695c, 0h40de6d7d, 0hc19194b0, 0h41a58418, 0hc22076c5, 0h406d72bf, 0h406d72bf,
|
||||
0h422076c5, 0hc1a58418, 0hc06d72bf, 0hc06d72bf, 0h4208695c, 0hc1b6d966, 0hc0de6d7d, 0h419194b0,
|
||||
0h4208695c, 0hc1b6d966, 0h419194b0, 0hc0de6d7d, 0h41f50507, 0hc1d2a716, 0h416b8e00, 0h416b8e00,
|
||||
0hc208ee18, 0hc18a0670, 0hc18a0670, 0hc18a0670, 0hc20e2b7a, 0hc19d18ee, 0hc19d18ee, 0h40b05c85,
|
||||
0hc20e2b7a, 0hc19d18ee, 0h40b05c85, 0hc19d18ee, 0hc20e2b7a, 0h40b05c85, 0hc19d18ee, 0hc19d18ee,
|
||||
0hc21c1252, 0hc1b8e69d, 0h40024b8d, 0h40024b8d, 0hc21c1252, 0h40024b8d, 0hc1b8e69d, 0h40024b8d,
|
||||
0hc21c1252, 0h40024b8d, 0h40024b8d, 0hc1b8e69d, 0hc235739c, 0hbfc4b564, 0hbfc4b564, 0hbfc4b564,
|
||||
0hc18a0670, 0hc208ee18, 0hc18a0670, 0hc18a0670, 0hc19d18ee, 0hc20e2b7a, 0hc19d18ee, 0h40b05c85,
|
||||
0hc19d18ee, 0hc20e2b7a, 0h40b05c85, 0hc19d18ee, 0h40b05c85, 0hc20e2b7a, 0hc19d18ee, 0hc19d18ee,
|
||||
0hc1b8e69d, 0hc21c1252, 0h40024b8d, 0h40024b8d, 0h40024b8d, 0hc21c1252, 0hc1b8e69d, 0h40024b8d,
|
||||
0h40024b8d, 0hc21c1252, 0h40024b8d, 0hc1b8e69d, 0hbfc4b564, 0hc235739c, 0hbfc4b564, 0hbfc4b564,
|
||||
0hc18a0670, 0hc18a0670, 0hc208ee18, 0hc18a0670, 0hc19d18ee, 0hc19d18ee, 0hc20e2b7a, 0h40b05c85,
|
||||
0hc19d18ee, 0h40b05c85, 0hc20e2b7a, 0hc19d18ee, 0h40b05c85, 0hc19d18ee, 0hc20e2b7a, 0hc19d18ee,
|
||||
0hc1b8e69d, 0h40024b8d, 0hc21c1252, 0h40024b8d, 0h40024b8d, 0hc1b8e69d, 0hc21c1252, 0h40024b8d,
|
||||
0h40024b8d, 0h40024b8d, 0hc21c1252, 0hc1b8e69d, 0hbfc4b564, 0hbfc4b564, 0hc235739c, 0hbfc4b564,
|
||||
0hc18a0670, 0hc18a0670, 0hc18a0670, 0hc208ee18, 0hc19d18ee, 0hc19d18ee, 0h40b05c85, 0hc20e2b7a,
|
||||
0hc19d18ee, 0h40b05c85, 0hc19d18ee, 0hc20e2b7a, 0h40b05c85, 0hc19d18ee, 0hc19d18ee, 0hc20e2b7a,
|
||||
0hc1b8e69d, 0h40024b8d, 0h40024b8d, 0hc21c1252, 0h40024b8d, 0hc1b8e69d, 0h40024b8d, 0hc21c1252,
|
||||
0h40024b8d, 0h40024b8d, 0hc1b8e69d, 0hc21c1252, 0hbfc4b564, 0hbfc4b564, 0hbfc4b564, 0hc235739c,
|
||||
0hc16b8e00, 0hc1f50507, 0hc16b8e00, 0h41d2a716, 0hc19194b0, 0hc208695c, 0h40de6d7d, 0h41b6d966,
|
||||
0h40de6d7d, 0hc208695c, 0hc19194b0, 0h41b6d966, 0h406d72bf, 0hc22076c5, 0h406d72bf, 0h41a58418,
|
||||
0hc06d72bf, 0hc1a58418, 0hc06d72bf, 0h422076c5, 0hc0de6d7d, 0hc1b6d966, 0h419194b0, 0h4208695c,
|
||||
0h419194b0, 0hc1b6d966, 0hc0de6d7d, 0h4208695c, 0h416b8e00, 0hc1d2a716, 0h416b8e00, 0h41f50507,
|
||||
0hc16b8e00, 0hc16b8e00, 0hc1f50507, 0h41d2a716, 0hc19194b0, 0h40de6d7d, 0hc208695c, 0h41b6d966,
|
||||
0h40de6d7d, 0hc19194b0, 0hc208695c, 0h41b6d966, 0h406d72bf, 0h406d72bf, 0hc22076c5, 0h41a58418,
|
||||
0hc06d72bf, 0hc06d72bf, 0hc1a58418, 0h422076c5, 0hc0de6d7d, 0h419194b0, 0hc1b6d966, 0h4208695c,
|
||||
0h419194b0, 0hc0de6d7d, 0hc1b6d966, 0h4208695c, 0h416b8e00, 0h416b8e00, 0hc1d2a716, 0h41f50507,
|
||||
0hc16b8e00, 0hc1f50507, 0h41d2a716, 0hc16b8e00, 0hc19194b0, 0hc208695c, 0h41b6d966, 0h40de6d7d,
|
||||
0h40de6d7d, 0hc208695c, 0h41b6d966, 0hc19194b0, 0h406d72bf, 0hc22076c5, 0h41a58418, 0h406d72bf,
|
||||
0hc06d72bf, 0hc1a58418, 0h422076c5, 0hc06d72bf, 0hc0de6d7d, 0hc1b6d966, 0h4208695c, 0h419194b0,
|
||||
0h419194b0, 0hc1b6d966, 0h4208695c, 0hc0de6d7d, 0h416b8e00, 0hc1d2a716, 0h41f50507, 0h416b8e00,
|
||||
0hc16b8e00, 0hc16b8e00, 0h41d2a716, 0hc1f50507, 0hc19194b0, 0h40de6d7d, 0h41b6d966, 0hc208695c,
|
||||
0h40de6d7d, 0hc19194b0, 0h41b6d966, 0hc208695c, 0h406d72bf, 0h406d72bf, 0h41a58418, 0hc22076c5,
|
||||
0hc06d72bf, 0hc06d72bf, 0h422076c5, 0hc1a58418, 0hc0de6d7d, 0h419194b0, 0h4208695c, 0hc1b6d966,
|
||||
0h419194b0, 0hc0de6d7d, 0h4208695c, 0hc1b6d966, 0h416b8e00, 0h416b8e00, 0h41f50507, 0hc1d2a716,
|
||||
0hc16b8e00, 0h41d2a716, 0hc1f50507, 0hc16b8e00, 0hc19194b0, 0h41b6d966, 0hc208695c, 0h40de6d7d,
|
||||
0h40de6d7d, 0h41b6d966, 0hc208695c, 0hc19194b0, 0h406d72bf, 0h41a58418, 0hc22076c5, 0h406d72bf,
|
||||
0hc06d72bf, 0h422076c5, 0hc1a58418, 0hc06d72bf, 0hc0de6d7d, 0h4208695c, 0hc1b6d966, 0h419194b0,
|
||||
0h419194b0, 0h4208695c, 0hc1b6d966, 0hc0de6d7d, 0h416b8e00, 0h41f50507, 0hc1d2a716, 0h416b8e00,
|
||||
0hc16b8e00, 0h41d2a716, 0hc16b8e00, 0hc1f50507, 0hc19194b0, 0h41b6d966, 0h40de6d7d, 0hc208695c,
|
||||
0h40de6d7d, 0h41b6d966, 0hc19194b0, 0hc208695c, 0h406d72bf, 0h41a58418, 0h406d72bf, 0hc22076c5,
|
||||
0hc06d72bf, 0h422076c5, 0hc06d72bf, 0hc1a58418, 0hc0de6d7d, 0h4208695c, 0h419194b0, 0hc1b6d966,
|
||||
0h419194b0, 0h4208695c, 0hc0de6d7d, 0hc1b6d966, 0h416b8e00, 0h41f50507, 0h416b8e00, 0hc1d2a716,
|
||||
0h41d2a716, 0hc16b8e00, 0hc1f50507, 0hc16b8e00, 0h41b6d966, 0hc19194b0, 0hc208695c, 0h40de6d7d,
|
||||
0h41b6d966, 0h40de6d7d, 0hc208695c, 0hc19194b0, 0h41a58418, 0h406d72bf, 0hc22076c5, 0h406d72bf,
|
||||
0h422076c5, 0hc06d72bf, 0hc1a58418, 0hc06d72bf, 0h4208695c, 0hc0de6d7d, 0hc1b6d966, 0h419194b0,
|
||||
0h4208695c, 0h419194b0, 0hc1b6d966, 0hc0de6d7d, 0h41f50507, 0h416b8e00, 0hc1d2a716, 0h416b8e00,
|
||||
0h41d2a716, 0hc16b8e00, 0hc16b8e00, 0hc1f50507, 0h41b6d966, 0hc19194b0, 0h40de6d7d, 0hc208695c,
|
||||
0h41b6d966, 0h40de6d7d, 0hc19194b0, 0hc208695c, 0h41a58418, 0h406d72bf, 0h406d72bf, 0hc22076c5,
|
||||
0h422076c5, 0hc06d72bf, 0hc06d72bf, 0hc1a58418, 0h4208695c, 0hc0de6d7d, 0h419194b0, 0hc1b6d966,
|
||||
0h4208695c, 0h419194b0, 0hc0de6d7d, 0hc1b6d966, 0h41f50507, 0h416b8e00, 0h416b8e00, 0hc1d2a716,
|
||||
0h3fc4b564, 0h3fc4b564, 0h3fc4b564, 0h4235739c, 0hc0024b8d, 0hc0024b8d, 0h41b8e69d, 0h421c1252,
|
||||
0hc0024b8d, 0h41b8e69d, 0hc0024b8d, 0h421c1252, 0hc0b05c85, 0h419d18ee, 0h419d18ee, 0h420e2b7a,
|
||||
0h41b8e69d, 0hc0024b8d, 0hc0024b8d, 0h421c1252, 0h419d18ee, 0hc0b05c85, 0h419d18ee, 0h420e2b7a,
|
||||
0h419d18ee, 0h419d18ee, 0hc0b05c85, 0h420e2b7a, 0h418a0670, 0h418a0670, 0h418a0670, 0h4208ee18,
|
||||
0h3fc4b564, 0h3fc4b564, 0h4235739c, 0h3fc4b564, 0hc0024b8d, 0h40024b8d, 0h421c1252, 0h41b8e69d,
|
||||
0hc0024b8d, 0h41b8e69d, 0h421c1252, 0hc0024b8d, 0hc0b05c85, 0h419d18ee, 0h420e2b7a, 0h419d18ee,
|
||||
0h41b8e69d, 0hc0024b8d, 0h421c1252, 0hc0024b8d, 0h419d18ee, 0hc0b05c85, 0h420e2b7a, 0h419d18ee,
|
||||
0h419d18ee, 0h419d18ee, 0h420e2b7a, 0hc0b05c85, 0h418a0670, 0h418a0670, 0h4208ee18, 0h418a0670,
|
||||
0h3fc4b564, 0h4235739c, 0h3fc4b564, 0h3fc4b564, 0hc0024b8d, 0h421c1252, 0hc0024b8d, 0h41b8e69d,
|
||||
0hc0024b8d, 0h421c1252, 0h41b8e69d, 0hc0024b8d, 0hc0b05c85, 0h420e2b7a, 0h419d18ee, 0h419d18ee,
|
||||
0h41b8e69d, 0h421c1252, 0hc0024b8d, 0hc0024b8d, 0h419d18ee, 0h420e2b7a, 0hc0b05c85, 0h419d18ee,
|
||||
0h419d18ee, 0h420e2b7a, 0h419d18ee, 0hc0b05c85, 0h418a0670, 0h4208ee18, 0h418a0670, 0h418a0670,
|
||||
0h4235739c, 0h3fc4b564, 0h3fc4b564, 0h3fc4b564, 0h421c1252, 0hc0024b8d, 0hc0024b8d, 0h41b8e69d,
|
||||
0h421c1252, 0hc0024b8d, 0h41b8e69d, 0hc0024b8d, 0h420e2b7a, 0hc0b05c85, 0h419d18ee, 0h419d18ee,
|
||||
0h421c1252, 0h41b8e69d, 0hc0024b8d, 0hc0024b8d, 0h420e2b7a, 0h419d18ee, 0hc0b05c85, 0h419d18ee,
|
||||
0h420e2b7a, 0h419d18ee, 0h419d18ee, 0hc0b05c85, 0h4208ee18, 0h418a0670, 0h418a0670, 0h418a0670,
|
||||
0hc1f50507, 0hc16b8e00, 0hc16b8e00, 0h41d2a716, 0hc208695c, 0hc19194b0, 0h40de6d7d, 0h41b6d966,
|
||||
0hc208695c, 0h40de6d7d, 0hc19194b0, 0h41b6d966, 0hc22076c5, 0h406d72bf, 0h406d72bf, 0h41a58418,
|
||||
0hc1a58418, 0hc06d72bf, 0hc06d72bf, 0h422076c5, 0hc1b6d966, 0hc0de6d7d, 0h419194b0, 0h4208695c,
|
||||
0hc1b6d966, 0h419194b0, 0hc0de6d7d, 0h4208695c, 0hc1d2a716, 0h416b8e00, 0h416b8e00, 0h41f50507,
|
||||
0hc1f50507, 0hc16b8e00, 0h41d2a716, 0hc16b8e00, 0hc208695c, 0hc19194b0, 0h41b6d966, 0h40de6d7d,
|
||||
0hc208695c, 0h40de6d7d, 0h41b6d966, 0hc19194b0, 0hc22076c5, 0h406d72bf, 0h41a58418, 0h406d72bf,
|
||||
0hc1a58418, 0hc06d72bf, 0h422076c5, 0hc06d72bf, 0hc1b6d966, 0hc0de6d7d, 0h4208695c, 0h419194b0,
|
||||
0hc1b6d966, 0h419194b0, 0h4208695c, 0hc0de6d7d, 0hc1d2a716, 0h416b8e00, 0h41f50507, 0h416b8e00,
|
||||
0hc1f50507, 0h41d2a716, 0hc16b8e00, 0hc16b8e00, 0hc208695c, 0h41b6d966, 0hc19194b0, 0h40de6d7d,
|
||||
0hc208695c, 0h41b6d966, 0h40de6d7d, 0hc19194b0, 0hc22076c5, 0h41a58418, 0h406d72bf, 0h406d72bf,
|
||||
0hc1a58418, 0h422076c5, 0hc06d72bf, 0hc06d72bf, 0hc1b6d966, 0h4208695c, 0hc0de6d7d, 0h419194b0,
|
||||
0hc1b6d966, 0h4208695c, 0h419194b0, 0hc0de6d7d, 0hc1d2a716, 0h41f50507, 0h416b8e00, 0h416b8e00,
|
||||
0h41d2a716, 0hc1f50507, 0hc16b8e00, 0hc16b8e00, 0h41b6d966, 0hc208695c, 0hc19194b0, 0h40de6d7d,
|
||||
0h41b6d966, 0hc208695c, 0h40de6d7d, 0hc19194b0, 0h41a58418, 0hc22076c5, 0h406d72bf, 0h406d72bf,
|
||||
0h422076c5, 0hc1a58418, 0hc06d72bf, 0hc06d72bf, 0h4208695c, 0hc1b6d966, 0hc0de6d7d, 0h419194b0,
|
||||
0h4208695c, 0hc1b6d966, 0h419194b0, 0hc0de6d7d, 0h41f50507, 0hc1d2a716, 0h416b8e00, 0h416b8e00,
|
||||
0hc208ee18, 0hc18a0670, 0hc18a0670, 0hc18a0670, 0hc20e2b7a, 0hc19d18ee, 0hc19d18ee, 0h40b05c85,
|
||||
0hc20e2b7a, 0hc19d18ee, 0h40b05c85, 0hc19d18ee, 0hc20e2b7a, 0h40b05c85, 0hc19d18ee, 0hc19d18ee,
|
||||
0hc21c1252, 0hc1b8e69d, 0h40024b8d, 0h40024b8d, 0hc21c1252, 0h40024b8d, 0hc1b8e69d, 0h40024b8d,
|
||||
0hc21c1252, 0h40024b8d, 0h40024b8d, 0hc1b8e69d, 0hc235739c, 0hbfc4b564, 0hbfc4b564, 0hbfc4b564,
|
||||
0hc18a0670, 0hc208ee18, 0hc18a0670, 0hc18a0670, 0hc19d18ee, 0hc20e2b7a, 0hc19d18ee, 0h40b05c85,
|
||||
0hc19d18ee, 0hc20e2b7a, 0h40b05c85, 0hc19d18ee, 0h40b05c85, 0hc20e2b7a, 0hc19d18ee, 0hc19d18ee,
|
||||
0hc1b8e69d, 0hc21c1252, 0h40024b8d, 0h40024b8d, 0h40024b8d, 0hc21c1252, 0hc1b8e69d, 0h40024b8d,
|
||||
0h40024b8d, 0hc21c1252, 0h40024b8d, 0hc1b8e69d, 0hbfc4b564, 0hc235739c, 0hbfc4b564, 0hbfc4b564,
|
||||
0hc18a0670, 0hc18a0670, 0hc208ee18, 0hc18a0670, 0hc19d18ee, 0hc19d18ee, 0hc20e2b7a, 0h40b05c85,
|
||||
0hc19d18ee, 0h40b05c85, 0hc20e2b7a, 0hc19d18ee, 0h40b05c85, 0hc19d18ee, 0hc20e2b7a, 0hc19d18ee,
|
||||
0hc1b8e69d, 0h40024b8d, 0hc21c1252, 0h40024b8d, 0h40024b8d, 0hc1b8e69d, 0hc21c1252, 0h40024b8d,
|
||||
0h40024b8d, 0h40024b8d, 0hc21c1252, 0hc1b8e69d, 0hbfc4b564, 0hbfc4b564, 0hc235739c, 0hbfc4b564,
|
||||
0hc18a0670, 0hc18a0670, 0hc18a0670, 0hc208ee18, 0hc19d18ee, 0hc19d18ee, 0h40b05c85, 0hc20e2b7a,
|
||||
0hc19d18ee, 0h40b05c85, 0hc19d18ee, 0hc20e2b7a, 0h40b05c85, 0hc19d18ee, 0hc19d18ee, 0hc20e2b7a,
|
||||
0hc1b8e69d, 0h40024b8d, 0h40024b8d, 0hc21c1252, 0h40024b8d, 0hc1b8e69d, 0h40024b8d, 0hc21c1252,
|
||||
0h40024b8d, 0h40024b8d, 0hc1b8e69d, 0hc21c1252, 0hbfc4b564, 0hbfc4b564, 0hbfc4b564, 0hc235739c,
|
||||
0hc16b8e00, 0hc1f50507, 0hc16b8e00, 0h41d2a716, 0hc19194b0, 0hc208695c, 0h40de6d7d, 0h41b6d966,
|
||||
0h40de6d7d, 0hc208695c, 0hc19194b0, 0h41b6d966, 0h406d72bf, 0hc22076c5, 0h406d72bf, 0h41a58418,
|
||||
0hc06d72bf, 0hc1a58418, 0hc06d72bf, 0h422076c5, 0hc0de6d7d, 0hc1b6d966, 0h419194b0, 0h4208695c,
|
||||
0h419194b0, 0hc1b6d966, 0hc0de6d7d, 0h4208695c, 0h416b8e00, 0hc1d2a716, 0h416b8e00, 0h41f50507,
|
||||
0hc16b8e00, 0hc16b8e00, 0hc1f50507, 0h41d2a716, 0hc19194b0, 0h40de6d7d, 0hc208695c, 0h41b6d966,
|
||||
0h40de6d7d, 0hc19194b0, 0hc208695c, 0h41b6d966, 0h406d72bf, 0h406d72bf, 0hc22076c5, 0h41a58418,
|
||||
0hc06d72bf, 0hc06d72bf, 0hc1a58418, 0h422076c5, 0hc0de6d7d, 0h419194b0, 0hc1b6d966, 0h4208695c,
|
||||
0h419194b0, 0hc0de6d7d, 0hc1b6d966, 0h4208695c, 0h416b8e00, 0h416b8e00, 0hc1d2a716, 0h41f50507,
|
||||
0hc16b8e00, 0hc1f50507, 0h41d2a716, 0hc16b8e00, 0hc19194b0, 0hc208695c, 0h41b6d966, 0h40de6d7d,
|
||||
0h40de6d7d, 0hc208695c, 0h41b6d966, 0hc19194b0, 0h406d72bf, 0hc22076c5, 0h41a58418, 0h406d72bf,
|
||||
0hc06d72bf, 0hc1a58418, 0h422076c5, 0hc06d72bf, 0hc0de6d7d, 0hc1b6d966, 0h4208695c, 0h419194b0,
|
||||
0h419194b0, 0hc1b6d966, 0h4208695c, 0hc0de6d7d, 0h416b8e00, 0hc1d2a716, 0h41f50507, 0h416b8e00,
|
||||
0hc16b8e00, 0hc16b8e00, 0h41d2a716, 0hc1f50507, 0hc19194b0, 0h40de6d7d, 0h41b6d966, 0hc208695c,
|
||||
0h40de6d7d, 0hc19194b0, 0h41b6d966, 0hc208695c, 0h406d72bf, 0h406d72bf, 0h41a58418, 0hc22076c5,
|
||||
0hc06d72bf, 0hc06d72bf, 0h422076c5, 0hc1a58418, 0hc0de6d7d, 0h419194b0, 0h4208695c, 0hc1b6d966,
|
||||
0h419194b0, 0hc0de6d7d, 0h4208695c, 0hc1b6d966, 0h416b8e00, 0h416b8e00, 0h41f50507, 0hc1d2a716,
|
||||
0hc16b8e00, 0h41d2a716, 0hc1f50507, 0hc16b8e00, 0hc19194b0, 0h41b6d966, 0hc208695c, 0h40de6d7d,
|
||||
0h40de6d7d, 0h41b6d966, 0hc208695c, 0hc19194b0, 0h406d72bf, 0h41a58418, 0hc22076c5, 0h406d72bf,
|
||||
0hc06d72bf, 0h422076c5, 0hc1a58418, 0hc06d72bf, 0hc0de6d7d, 0h4208695c, 0hc1b6d966, 0h419194b0,
|
||||
0h419194b0, 0h4208695c, 0hc1b6d966, 0hc0de6d7d, 0h416b8e00, 0h41f50507, 0hc1d2a716, 0h416b8e00,
|
||||
0hc16b8e00, 0h41d2a716, 0hc16b8e00, 0hc1f50507, 0hc19194b0, 0h41b6d966, 0h40de6d7d, 0hc208695c,
|
||||
0h40de6d7d, 0h41b6d966, 0hc19194b0, 0hc208695c, 0h406d72bf, 0h41a58418, 0h406d72bf, 0hc22076c5,
|
||||
0hc06d72bf, 0h422076c5, 0hc06d72bf, 0hc1a58418, 0hc0de6d7d, 0h4208695c, 0h419194b0, 0hc1b6d966,
|
||||
0h419194b0, 0h4208695c, 0hc0de6d7d, 0hc1b6d966, 0h416b8e00, 0h41f50507, 0h416b8e00, 0hc1d2a716,
|
||||
0h41d2a716, 0hc16b8e00, 0hc1f50507, 0hc16b8e00, 0h41b6d966, 0hc19194b0, 0hc208695c, 0h40de6d7d,
|
||||
0h41b6d966, 0h40de6d7d, 0hc208695c, 0hc19194b0, 0h41a58418, 0h406d72bf, 0hc22076c5, 0h406d72bf,
|
||||
0h422076c5, 0hc06d72bf, 0hc1a58418, 0hc06d72bf, 0h4208695c, 0hc0de6d7d, 0hc1b6d966, 0h419194b0,
|
||||
0h4208695c, 0h419194b0, 0hc1b6d966, 0hc0de6d7d, 0h41f50507, 0h416b8e00, 0hc1d2a716, 0h416b8e00,
|
||||
0h41d2a716, 0hc16b8e00, 0hc16b8e00, 0hc1f50507, 0h41b6d966, 0hc19194b0, 0h40de6d7d, 0hc208695c,
|
||||
0h41b6d966, 0h40de6d7d, 0hc19194b0, 0hc208695c, 0h41a58418, 0h406d72bf, 0h406d72bf, 0hc22076c5,
|
||||
0h422076c5, 0hc06d72bf, 0hc06d72bf, 0hc1a58418, 0h4208695c, 0hc0de6d7d, 0h419194b0, 0hc1b6d966,
|
||||
0h4208695c, 0h419194b0, 0hc0de6d7d, 0hc1b6d966, 0h41f50507, 0h416b8e00, 0h416b8e00, 0hc1d2a716,
|
||||
0h3fc4b564, 0h3fc4b564, 0h3fc4b564, 0h4235739c, 0hc0024b8d, 0hc0024b8d, 0h41b8e69d, 0h421c1252,
|
||||
0hc0024b8d, 0h41b8e69d, 0hc0024b8d, 0h421c1252, 0hc0b05c85, 0h419d18ee, 0h419d18ee, 0h420e2b7a,
|
||||
0h41b8e69d, 0hc0024b8d, 0hc0024b8d, 0h421c1252, 0h419d18ee, 0hc0b05c85, 0h419d18ee, 0h420e2b7a,
|
||||
0h419d18ee, 0h419d18ee, 0hc0b05c85, 0h420e2b7a, 0h418a0670, 0h418a0670, 0h418a0670, 0h4208ee18,
|
||||
0h3fc4b564, 0h3fc4b564, 0h4235739c, 0h3fc4b564, 0hc0024b8d, 0h40024b8d, 0h421c1252, 0h41b8e69d,
|
||||
0hc0024b8d, 0h41b8e69d, 0h421c1252, 0hc0024b8d, 0hc0b05c85, 0h419d18ee, 0h420e2b7a, 0h419d18ee,
|
||||
0h41b8e69d, 0hc0024b8d, 0h421c1252, 0hc0024b8d, 0h419d18ee, 0hc0b05c85, 0h420e2b7a, 0h419d18ee,
|
||||
0h419d18ee, 0h419d18ee, 0h420e2b7a, 0hc0b05c85, 0h418a0670, 0h418a0670, 0h4208ee18, 0h418a0670,
|
||||
0h3fc4b564, 0h4235739c, 0h3fc4b564, 0h3fc4b564, 0hc0024b8d, 0h421c1252, 0hc0024b8d, 0h41b8e69d,
|
||||
0hc0024b8d, 0h421c1252, 0h41b8e69d, 0hc0024b8d, 0hc0b05c85, 0h420e2b7a, 0h419d18ee, 0h419d18ee,
|
||||
0h41b8e69d, 0h421c1252, 0hc0024b8d, 0hc0024b8d, 0h419d18ee, 0h420e2b7a, 0hc0b05c85, 0h419d18ee,
|
||||
0h419d18ee, 0h420e2b7a, 0h419d18ee, 0hc0b05c85, 0h418a0670, 0h4208ee18, 0h418a0670, 0h418a0670,
|
||||
0h4235739c, 0h3fc4b564, 0h3fc4b564, 0h3fc4b564, 0h421c1252, 0hc0024b8d, 0hc0024b8d, 0h41b8e69d,
|
||||
0h421c1252, 0hc0024b8d, 0h41b8e69d, 0hc0024b8d, 0h420e2b7a, 0hc0b05c85, 0h419d18ee, 0h419d18ee,
|
||||
0h421c1252, 0h41b8e69d, 0hc0024b8d, 0hc0024b8d, 0h420e2b7a, 0h419d18ee, 0hc0b05c85, 0h419d18ee,
|
||||
0h420e2b7a, 0h419d18ee, 0h419d18ee, 0hc0b05c85, 0h4208ee18, 0h418a0670, 0h418a0670, 0h418a0670,
|
||||
0hc1f50507, 0hc16b8e00, 0hc16b8e00, 0h41d2a716, 0hc208695c, 0hc19194b0, 0h40de6d7d, 0h41b6d966,
|
||||
0hc208695c, 0h40de6d7d, 0hc19194b0, 0h41b6d966, 0hc22076c5, 0h406d72bf, 0h406d72bf, 0h41a58418,
|
||||
0hc1a58418, 0hc06d72bf, 0hc06d72bf, 0h422076c5, 0hc1b6d966, 0hc0de6d7d, 0h419194b0, 0h4208695c,
|
||||
0hc1b6d966, 0h419194b0, 0hc0de6d7d, 0h4208695c, 0hc1d2a716, 0h416b8e00, 0h416b8e00, 0h41f50507,
|
||||
0hc1f50507, 0hc16b8e00, 0h41d2a716, 0hc16b8e00, 0hc208695c, 0hc19194b0, 0h41b6d966, 0h40de6d7d,
|
||||
0hc208695c, 0h40de6d7d, 0h41b6d966, 0hc19194b0, 0hc22076c5, 0h406d72bf, 0h41a58418, 0h406d72bf,
|
||||
0hc1a58418, 0hc06d72bf, 0h422076c5, 0hc06d72bf, 0hc1b6d966, 0hc0de6d7d, 0h4208695c, 0h419194b0,
|
||||
0hc1b6d966, 0h419194b0, 0h4208695c, 0hc0de6d7d, 0hc1d2a716, 0h416b8e00, 0h41f50507, 0h416b8e00,
|
||||
0hc1f50507, 0h41d2a716, 0hc16b8e00, 0hc16b8e00, 0hc208695c, 0h41b6d966, 0hc19194b0, 0h40de6d7d,
|
||||
0hc208695c, 0h41b6d966, 0h40de6d7d, 0hc19194b0, 0hc22076c5, 0h41a58418, 0h406d72bf, 0h406d72bf,
|
||||
0hc1a58418, 0h422076c5, 0hc06d72bf, 0hc06d72bf, 0hc1b6d966, 0h4208695c, 0hc0de6d7d, 0h419194b0,
|
||||
0hc1b6d966, 0h4208695c, 0h419194b0, 0hc0de6d7d, 0hc1d2a716, 0h41f50507, 0h416b8e00, 0h416b8e00,
|
||||
0h41d2a716, 0hc1f50507, 0hc16b8e00, 0hc16b8e00, 0h41b6d966, 0hc208695c, 0hc19194b0, 0h40de6d7d,
|
||||
0h41b6d966, 0hc208695c, 0h40de6d7d, 0hc19194b0, 0h41a58418, 0hc22076c5, 0h406d72bf, 0h406d72bf,
|
||||
0h422076c5, 0hc1a58418, 0hc06d72bf, 0hc06d72bf, 0h4208695c, 0hc1b6d966, 0hc0de6d7d, 0h419194b0,
|
||||
0h4208695c, 0hc1b6d966, 0h419194b0, 0hc0de6d7d, 0h41f50507, 0hc1d2a716, 0h416b8e00, 0h416b8e00,
|
||||
}
|
||||
|
||||
/*
|
||||
2D Simplex noise base.
|
||||
*/
|
||||
_internal_noise_2d_unskewed_base :: proc(seed: i64, coord: Vec2) -> (value: f32) {
|
||||
// Get base points and offsets.
|
||||
base := [2]i64{fast_floor(coord.x), fast_floor(coord.y)}
|
||||
i := [2]f32{f32(coord.x - f64(base.x)), f32(coord.y - f64(base.y))}
|
||||
|
||||
// Prime pre-multiplication for hash.
|
||||
bp := base * [2]i64{PRIME_X, PRIME_Y}
|
||||
|
||||
// Unskew.
|
||||
t := f32(i.x + i.y) * f32(UNSKEW_2D)
|
||||
d0 := i + [2]f32{t, t}
|
||||
|
||||
// First vertex.
|
||||
a0 := RSQUARED_2D - d0.x * d0.x - d0.y * d0.y
|
||||
if a0 > 0 {
|
||||
value = (a0 * a0) * (a0 * a0) * grad(seed, [2]i64{bp.x, bp.y}, d0)
|
||||
}
|
||||
|
||||
// Second vertex.
|
||||
a1 := f32(2 * (1 + 2 * UNSKEW_2D) * (1 / UNSKEW_2D + 2)) * t + f32(-2 * (1 + 2 * UNSKEW_2D) * (1 + 2 * UNSKEW_2D)) + a0
|
||||
if a1 > 0 {
|
||||
d1 := d0 - [2]f32{f32(1 + 2 * UNSKEW_2D), f32(1 + 2 * UNSKEW_2D)}
|
||||
value += (a1 * a1) * (a1 * a1) * grad(seed, [2]i64{bp.x + PRIME_X, bp.y + PRIME_Y}, d1)
|
||||
}
|
||||
|
||||
// Third vertex.
|
||||
if d0.y > d0.x {
|
||||
d2 := d0 - [2]f32{f32(UNSKEW_2D), f32(UNSKEW_2D + 1)}
|
||||
a2 := RSQUARED_2D - d2.x * d2.x - d2.y * d2.y
|
||||
if(a2 > 0) {
|
||||
value += (a2 * a2) * (a2 * a2) * grad(seed, [2]i64{bp.x, bp.y + PRIME_Y}, d2)
|
||||
}
|
||||
} else {
|
||||
d2 := d0 - [2]f32{f32(UNSKEW_2D + 1), f32(UNSKEW_2D)}
|
||||
a2 := RSQUARED_2D - d2.x * d2.x - d2.y * d2.y
|
||||
if(a2 > 0) {
|
||||
value += (a2 * a2) * (a2 * a2) * grad(seed, [2]i64{bp.x + PRIME_X, bp.y}, d2)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Generate overlapping cubic lattices for 3D OpenSimplex2 noise.
|
||||
*/
|
||||
_internal_noise_3d_unrotated_base :: proc(seed: i64, coord: Vec3) -> (value: f32) {
|
||||
seed := seed
|
||||
// Get base points and offsets.
|
||||
// xr, yr, zr := coord.x, coord.y, coord.z
|
||||
|
||||
rb := [3]i64{fast_round(coord.x), fast_round(coord.y), fast_round(coord.z)}
|
||||
ri := [3]f32{f32(coord.x - f64(rb.x)), f32(coord.y - f64(rb.y)), f32(coord.z - f64(rb.z))}
|
||||
|
||||
// -1 if positive, 1 if negative.
|
||||
i_sign := [3]i64{i64(-1.0 - ri.x) | 1, i64(-1.0 - ri.y) | 1, i64(-1.0 - ri.z) | 1}
|
||||
f_sign := [3]f32{f32(i_sign.x), f32(i_sign.y), f32(i_sign.z)}
|
||||
|
||||
// Compute absolute values, using the above as a shortcut. This was faster in my tests for some reason.
|
||||
a0 := f_sign * -ri
|
||||
|
||||
// Prime pre-multiplication for hash.
|
||||
rbp := rb * [3]i64{PRIME_X, PRIME_Y, PRIME_Z}
|
||||
|
||||
// Loop: Pick an edge on each lattice copy.
|
||||
a := (RSQUARED_3D - ri.x * ri.x) - (ri.y * ri.y + ri.z * ri.z)
|
||||
|
||||
l := 0
|
||||
for {
|
||||
defer l += 1
|
||||
|
||||
// Closest point on cube.
|
||||
if a > 0 {
|
||||
a2 := a * a; a4 := a2 * a2
|
||||
value += a4 * grad(seed, rbp, ri)
|
||||
}
|
||||
|
||||
// Second-closest point.
|
||||
if a0.x >= a0.y && a0.x >= a0.z {
|
||||
b := a + a0.x + a0.x
|
||||
if b > 1 {
|
||||
b -= 1
|
||||
b2 := b * b; b4 := b2 * b2
|
||||
value += b4 * grad(seed, [3]i64{rbp.x - i_sign.x * PRIME_X, rbp.y, rbp.z}, [3]f32{ri.x + f_sign.x, ri.y, ri.z})
|
||||
}
|
||||
} else if a0.y > a0.x && a0.y >= a0.z {
|
||||
b := a + a0.y + a0.y
|
||||
if b > 1 {
|
||||
b -= 1
|
||||
b2 := b * b; b4 := b2 * b2
|
||||
value += b4 * grad(seed, [3]i64{rbp.x, rbp.y - i_sign.y * PRIME_Y, rbp.z}, [3]f32{ri.x, ri.y + f_sign.y, ri.z})
|
||||
}
|
||||
} else {
|
||||
b := a + a0.z + a0.z
|
||||
if b > 1 {
|
||||
b -= 1
|
||||
b2 := b * b; b4 := b2 * b2
|
||||
value += b4 * grad(seed, [3]i64{rbp.x, rbp.y, rbp.z - i_sign.z * PRIME_Z}, [3]f32{ri.x, ri.y, ri.z + f_sign.z})
|
||||
}
|
||||
}
|
||||
|
||||
// Break from loop if we're done, skipping updates below.
|
||||
if l == 1 {
|
||||
break
|
||||
}
|
||||
|
||||
// Update absolute value.
|
||||
a0 = 0.5 - a0
|
||||
|
||||
// Update relative coordinate.
|
||||
ri = a0 * f_sign
|
||||
|
||||
// Update falloff.
|
||||
a += (0.75 - a0.x) - (a0.y + a0.z)
|
||||
|
||||
// Update prime for hash.
|
||||
rbp += [3]i64{i_sign.x >> 1, i_sign.y >> 1, i_sign.z >> 1} & {PRIME_X, PRIME_Y, PRIME_Z}
|
||||
|
||||
// Update the reverse sign indicators.
|
||||
i_sign = -i_sign
|
||||
f_sign = -f_sign
|
||||
|
||||
// And finally update the seed for the other lattice copy.
|
||||
seed ~= SEED_FLIP_3D
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
/*
|
||||
4D OpenSimplex2 noise base.
|
||||
*/
|
||||
_internal_noise_4d_unskewed_base :: proc(seed: i64, coord: Vec4) -> (value: f32) {
|
||||
seed := seed
|
||||
|
||||
// Get base points and offsets
|
||||
base := [4]i64{fast_floor(coord.x), fast_floor(coord.y), fast_floor(coord.z), fast_floor(coord.w)}
|
||||
si := [4]f32{f32(coord.x - f64(base.x)), f32(coord.y - f64(base.y)), f32(coord.z - f64(base.z)), f32(coord.w - f64(base.w))}
|
||||
|
||||
// Determine which lattice we can be confident has a contributing point its corresponding cell's base simplex.
|
||||
// We only look at the spaces between the diagonal planes. This proved effective in all of my tests.
|
||||
si_sum := (si.x + si.y) + (si.z + si.w)
|
||||
starting_lattice := i64(si_sum * 1.25)
|
||||
|
||||
// Offset for seed based on first lattice copy.
|
||||
seed += starting_lattice * SEED_OFFSET_4D
|
||||
|
||||
// Offset for lattice point relative positions (skewed)
|
||||
starting_lattice_offset := f32(starting_lattice) * -LATTICE_STEP_4D
|
||||
si += starting_lattice_offset
|
||||
|
||||
// Prep for vertex contributions.
|
||||
ssi := (si_sum + starting_lattice_offset * 4) * UNSKEW_4D
|
||||
|
||||
// Prime pre-multiplication for hash.
|
||||
svp := base * [4]i64{PRIME_X, PRIME_Y, PRIME_Z, PRIME_W}
|
||||
|
||||
// Five points to add, total, from five copies of the A4 lattice.
|
||||
for i : i64 = 0; ; i += 1 {
|
||||
|
||||
// Next point is the closest vertex on the 4-simplex whose base vertex is the aforementioned vertex.
|
||||
score := 1.0 + ssi * (-1.0 / UNSKEW_4D) // Seems slightly faster than 1.0-xsi-ysi-zsi-wsi
|
||||
if si.x >= si.x && si.x >= si.z && si.x >= si.w && si.x >= score {
|
||||
svp.x += PRIME_X
|
||||
si.x -= 1
|
||||
ssi -= UNSKEW_4D
|
||||
}
|
||||
else if si.y > si.x && si.y >= si.z && si.y >= si.w && si.y >= score {
|
||||
svp.y += PRIME_Y
|
||||
si.y -= 1
|
||||
ssi -= UNSKEW_4D
|
||||
}
|
||||
else if si.z > si.x && si.z > si.y && si.z >= si.w && si.z >= score {
|
||||
svp.z += PRIME_Z
|
||||
si.z -= 1
|
||||
ssi -= UNSKEW_4D
|
||||
}
|
||||
else if si.w > si.x && si.w > si.y && si.w > si.z && si.w >= score {
|
||||
svp.w += PRIME_W
|
||||
si.w -= 1
|
||||
ssi -= UNSKEW_4D
|
||||
}
|
||||
|
||||
// gradient contribution with falloff.
|
||||
d := si + ssi
|
||||
a := (d.x * d.x + d.y * d.y) + (d.z * d.z + d.w * d.w)
|
||||
|
||||
if a < RSQUARED_4D {
|
||||
a -= RSQUARED_4D
|
||||
a *= a; a4 := a * a
|
||||
value += a4 * grad(seed, svp, d)
|
||||
}
|
||||
|
||||
// Break from loop if we're done, skipping updates below.
|
||||
if i == 4 {
|
||||
break
|
||||
}
|
||||
|
||||
// Update for next lattice copy shifted down by <-0.2, -0.2, -0.2, -0.2>.
|
||||
si += LATTICE_STEP_4D
|
||||
ssi += LATTICE_STEP_4D * 4 * UNSKEW_4D
|
||||
seed -= SEED_OFFSET_4D
|
||||
|
||||
// Because we don't always start on the same lattice copy, there's a special reset case.
|
||||
if i == starting_lattice {
|
||||
svp -= {PRIME_X, PRIME_Y, PRIME_Z, PRIME_W}
|
||||
seed += SEED_OFFSET_4D * 5
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
Utility functions
|
||||
*/
|
||||
@(optimization_mode="speed")
|
||||
grad_2d :: proc(seed: i64, svp: [2]i64, delta: [2]f32) -> (value: f32) {
|
||||
hash := seed ~ svp.x ~ svp.y
|
||||
hash *= HASH_MULTIPLIER
|
||||
hash ~= hash >> (64 - N_GRADS_2D_EXPONENT + 1)
|
||||
|
||||
gi := hash & ((N_GRADS_2D - 1) << 1)
|
||||
return GRADIENTS_2D[gi] * delta.x + GRADIENTS_2D[gi | 1] * delta.y
|
||||
}
|
||||
|
||||
@(optimization_mode="speed")
|
||||
grad_3d :: proc(seed: i64, rvp: [3]i64, delta: [3]f32) -> (value: f32) {
|
||||
hash := (seed ~ rvp.x) ~ (rvp.y ~ rvp.z)
|
||||
hash *= HASH_MULTIPLIER
|
||||
hash ~= hash >> (64 - N_GRADS_3D_EXPONENT + 2)
|
||||
|
||||
gi := hash & ((N_GRADS_3D - 1) << 2)
|
||||
return GRADIENTS_3D[gi] * delta.x + GRADIENTS_3D[gi | 1] * delta.y + GRADIENTS_3D[gi | 2] * delta.z
|
||||
}
|
||||
|
||||
@(optimization_mode="speed")
|
||||
grad_4d :: proc(seed: i64, svp: [4]i64, delta: [4]f32) -> (value: f32) {
|
||||
hash := seed ~ (svp.x ~ svp.y) ~ (svp.z ~ svp.w)
|
||||
hash *= HASH_MULTIPLIER
|
||||
hash ~= hash >> (64 - N_GRADS_4D_EXPONENT + 2)
|
||||
|
||||
gi := hash & ((N_GRADS_4D - 1) << 2)
|
||||
return (GRADIENTS_4D[gi] * delta.x + GRADIENTS_4D[gi | 1] * delta.y) + (GRADIENTS_4D[gi | 2] * delta.z + GRADIENTS_4D[gi | 3] * delta.w)
|
||||
}
|
||||
|
||||
grad :: proc {grad_2d, grad_3d, grad_4d}
|
||||
|
||||
@(optimization_mode="speed")
|
||||
fast_floor :: proc(x: f64) -> (floored: i64) {
|
||||
xi := i64(x)
|
||||
return x < f64(xi) ? xi - 1 : xi
|
||||
}
|
||||
|
||||
@(optimization_mode="speed")
|
||||
fast_round :: proc(x: f64) -> (rounded: i64) {
|
||||
return x < 0 ? i64(x - 0.5) : i64(x + 0.5)
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
OpenSimplex2 noise implementation.
|
||||
|
||||
Ported from https://github.com/KdotJPG/OpenSimplex2.
|
||||
Copyright 2022 Yuki2 (https://github.com/NoahR02)
|
||||
*/
|
||||
package math_noise
|
||||
|
||||
/*
|
||||
Input coordinate vectors
|
||||
*/
|
||||
Vec2 :: [2]f64
|
||||
Vec3 :: [3]f64
|
||||
Vec4 :: [4]f64
|
||||
|
||||
/*
|
||||
Noise Evaluators
|
||||
*/
|
||||
|
||||
/*
|
||||
2D Simplex noise, standard lattice orientation.
|
||||
*/
|
||||
noise_2d :: proc(seed: i64, coord: Vec2) -> (value: f32) {
|
||||
// Get points for A2* lattice
|
||||
skew := SKEW_2D * (coord.x + coord.y)
|
||||
skewed := coord + skew
|
||||
|
||||
return _internal_noise_2d_unskewed_base(seed, skewed)
|
||||
}
|
||||
|
||||
/*
|
||||
2D Simplex noise, with Y pointing down the main diagonal.
|
||||
Might be better for a 2D sandbox style game, where Y is vertical.
|
||||
Probably slightly less optimal for heightmaps or continent maps,
|
||||
unless your map is centered around an equator. It's a subtle
|
||||
difference, but the option is here to make it an easy choice.
|
||||
*/
|
||||
noise_2d_improve_x :: proc(seed: i64, coord: Vec2) -> (value: f32) {
|
||||
// Skew transform and rotation baked into one.
|
||||
xx := coord.x * ROOT_2_OVER_2
|
||||
yy := coord.y * (ROOT_2_OVER_2 * (1 + 2 * SKEW_2D))
|
||||
return _internal_noise_2d_unskewed_base(seed, Vec2{yy + xx, yy - xx})
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
3D OpenSimplex2 noise, with better visual isotropy in (X, Y).
|
||||
Recommended for 3D terrain and time-varied animations.
|
||||
The Z coordinate should always be the "different" coordinate in whatever your use case is.
|
||||
If Y is vertical in world coordinates, call `noise_3d_improve_xz(x, z, Y)` or use `noise_3d_xz_before_y`.
|
||||
If Z is vertical in world coordinates, call `noise_3d_improve_xz(x, y, Z)`.
|
||||
For a time varied animation, call `noise_3d_improve_xz(x, y, T)`.
|
||||
*/
|
||||
noise_3d_improve_xy :: proc(seed: i64, coord: Vec3) -> (value: f32) {
|
||||
/*
|
||||
Re-orient the cubic lattices without skewing, so Z points up the main lattice diagonal,
|
||||
and the planes formed by XY are moved far out of alignment with the cube faces.
|
||||
Orthonormal rotation. Not a skew transform.
|
||||
*/
|
||||
xy := coord.x + coord.y
|
||||
s2 := xy * ROTATE_3D_ORTHOGONALIZER
|
||||
zz := coord.z * ROOT_3_OVER_3
|
||||
|
||||
r := Vec3{coord.x + s2 + zz, coord.y + s2 + zz, xy * -ROOT_3_OVER_3 + zz}
|
||||
|
||||
// Evaluate both lattices to form a BCC lattice.
|
||||
return _internal_noise_3d_unrotated_base(seed, r)
|
||||
}
|
||||
|
||||
/*
|
||||
3D OpenSimplex2 noise, with better visual isotropy in (X, Z).
|
||||
Recommended for 3D terrain and time-varied animations.
|
||||
The Y coordinate should always be the "different" coordinate in whatever your use case is.
|
||||
If Y is vertical in world coordinates, call `noise_3d_improve_xz(x, Y, z)`.
|
||||
If Z is vertical in world coordinates, call `noise_3d_improve_xz(x, Z, y)` or use `noise_3d_improve_xy`.
|
||||
For a time varied animation, call `noise_3d_improve_xz(x, T, y)` or use `noise_3d_improve_xy`.
|
||||
*/
|
||||
noise_3d_improve_xz :: proc(seed: i64, coord: Vec3) -> (value: f32) {
|
||||
/*
|
||||
Re-orient the cubic lattices without skewing, so Y points up the main lattice diagonal,
|
||||
and the planes formed by XZ are moved far out of alignment with the cube faces.
|
||||
Orthonormal rotation. Not a skew transform.
|
||||
*/
|
||||
xz := coord.x + coord.z
|
||||
s2 := xz * ROTATE_3D_ORTHOGONALIZER
|
||||
yy := coord.y * ROOT_3_OVER_3
|
||||
|
||||
r := Vec3{coord.x + s2 + yy, xz * -ROOT_3_OVER_3 + yy, coord.z + s2 + yy}
|
||||
|
||||
// Evaluate both lattices to form a BCC lattice.
|
||||
return _internal_noise_3d_unrotated_base(seed, r)
|
||||
}
|
||||
|
||||
/*
|
||||
3D OpenSimplex2 noise, fallback rotation option
|
||||
Use `noise_3d_improve_xy` or `noise_3d_improve_xz` instead, wherever appropriate.
|
||||
They have less diagonal bias. This function's best use is as a fallback.
|
||||
*/
|
||||
noise_3d_fallback :: proc(seed: i64, coord: Vec3) -> (value: f32) {
|
||||
/*
|
||||
Re-orient the cubic lattices via rotation, to produce a familiar look.
|
||||
Orthonormal rotation. Not a skew transform.
|
||||
*/
|
||||
bias := FALLBACK_ROTATE_3D * (coord.x + coord.y + coord.z)
|
||||
biased := bias - coord
|
||||
// Evaluate both lattices to form a BCC lattice.
|
||||
return _internal_noise_3d_unrotated_base(seed, biased)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
4D OpenSimplex2 noise, with XYZ oriented like `noise_3d_improve_xy`
|
||||
and W for an extra degree of freedom. W repeats eventually.
|
||||
Recommended for time-varied animations which texture a 3D object (W=time)
|
||||
in a space where Z is vertical.
|
||||
*/
|
||||
noise_4d_improve_xyz_improve_xy :: proc(seed: i64, coord: Vec4) -> (value: f32) {
|
||||
xy := coord.x + coord.y
|
||||
s2 := xy * -0.21132486540518699998
|
||||
zz := coord.z * 0.28867513459481294226
|
||||
ww := coord.w * 0.2236067977499788
|
||||
|
||||
xr, yr : f64 = coord.x + (zz + ww + s2), coord.y + (zz + ww + s2)
|
||||
zr : f64 = xy * -0.57735026918962599998 + (zz + ww)
|
||||
wr : f64 = coord.z * -0.866025403784439 + ww
|
||||
|
||||
return _internal_noise_4d_unskewed_base(seed, Vec4{xr, yr, zr, wr})
|
||||
}
|
||||
|
||||
/*
|
||||
4D OpenSimplex2 noise, with XYZ oriented like `noise_3d_improve_xz`
|
||||
and W for an extra degree of freedom. W repeats eventually.
|
||||
Recommended for time-varied animations which texture a 3D object (W=time)
|
||||
in a space where Y is vertical.
|
||||
*/
|
||||
noise_4d_improve_xyz_improve_xz :: proc(seed: i64, coord: Vec4) -> (value: f32) {
|
||||
xz := coord.x + coord.z
|
||||
s2 := xz * -0.21132486540518699998
|
||||
yy := coord.y * 0.28867513459481294226
|
||||
ww := coord.w * 0.2236067977499788
|
||||
|
||||
xr, zr : f64 = coord.x + (yy + ww + s2), coord.z + (yy + ww + s2)
|
||||
yr := xz * -0.57735026918962599998 + (yy + ww)
|
||||
wr := coord.y * -0.866025403784439 + ww
|
||||
|
||||
return _internal_noise_4d_unskewed_base(seed, Vec4{xr, yr, zr, wr})
|
||||
}
|
||||
|
||||
/*
|
||||
4D OpenSimplex2 noise, with XYZ oriented like `noise_3d_fallback`
|
||||
and W for an extra degree of freedom. W repeats eventually.
|
||||
Recommended for time-varied animations which texture a 3D object (W=time)
|
||||
where there isn't a clear distinction between horizontal and vertical
|
||||
*/
|
||||
noise_4d_improve_xyz :: proc(seed: i64, coord: Vec4) -> (value: f32) {
|
||||
xyz := coord.x + coord.y + coord.z
|
||||
ww := coord.w * 0.2236067977499788
|
||||
s2 := xyz * -0.16666666666666666 + ww
|
||||
|
||||
skewed := Vec4{coord.x + s2, coord.y + s2, coord.z + s2, -0.5 * xyz + ww}
|
||||
return _internal_noise_4d_unskewed_base(seed, skewed)
|
||||
}
|
||||
|
||||
/*
|
||||
4D OpenSimplex2 noise, fallback lattice orientation.
|
||||
*/
|
||||
noise_4d_fallback :: proc(seed: i64, coord: Vec4) -> (value: f32) {
|
||||
// Get points for A4 lattice
|
||||
skew := f64(SKEW_4D) * (coord.x + coord.y + coord.z + coord.w)
|
||||
return _internal_noise_4d_unskewed_base(seed, coord + skew)
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
package rand
|
||||
|
||||
import "core:math"
|
||||
|
||||
// exp_float64 returns a exponential distribution in the range (0, max(f64)],
|
||||
// with an exponential distribution who rate parameter is 1 (lambda) and whose mean
|
||||
// is 1 (1/lambda).
|
||||
//
|
||||
// To produce a distribution with a differetn rate parameter, divide the result by
|
||||
// the desired rate parameter
|
||||
//
|
||||
// "The Ziggurat Method for Generating Random Variables"
|
||||
// Authors: George Marsaglia, Wai Wan Tsang
|
||||
// Submitted: 2000-04-15. Published: 2000-10-02.
|
||||
// https://www.jstatsoft.org/index.php/jss/article/view/v005i08/ziggurat.pdf [pdf]
|
||||
// https://www.jstatsoft.org/article/view/v005i08 [web page]
|
||||
//
|
||||
exp_float64 :: proc(r: ^Rand = nil) -> f64 {
|
||||
re :: 7.69711747013104972
|
||||
|
||||
@(static)
|
||||
ke := [256]u32{
|
||||
0xe290a139, 0x0, 0x9beadebc, 0xc377ac71, 0xd4ddb990,
|
||||
0xde893fb8, 0xe4a8e87c, 0xe8dff16a, 0xebf2deab, 0xee49a6e8,
|
||||
0xf0204efd, 0xf19bdb8e, 0xf2d458bb, 0xf3da104b, 0xf4b86d78,
|
||||
0xf577ad8a, 0xf61de83d, 0xf6afb784, 0xf730a573, 0xf7a37651,
|
||||
0xf80a5bb6, 0xf867189d, 0xf8bb1b4f, 0xf9079062, 0xf94d70ca,
|
||||
0xf98d8c7d, 0xf9c8928a, 0xf9ff175b, 0xfa319996, 0xfa6085f8,
|
||||
0xfa8c3a62, 0xfab5084e, 0xfadb36c8, 0xfaff0410, 0xfb20a6ea,
|
||||
0xfb404fb4, 0xfb5e2951, 0xfb7a59e9, 0xfb95038c, 0xfbae44ba,
|
||||
0xfbc638d8, 0xfbdcf892, 0xfbf29a30, 0xfc0731df, 0xfc1ad1ed,
|
||||
0xfc2d8b02, 0xfc3f6c4d, 0xfc5083ac, 0xfc60ddd1, 0xfc708662,
|
||||
0xfc7f8810, 0xfc8decb4, 0xfc9bbd62, 0xfca9027c, 0xfcb5c3c3,
|
||||
0xfcc20864, 0xfccdd70a, 0xfcd935e3, 0xfce42ab0, 0xfceebace,
|
||||
0xfcf8eb3b, 0xfd02c0a0, 0xfd0c3f59, 0xfd156b7b, 0xfd1e48d6,
|
||||
0xfd26daff, 0xfd2f2552, 0xfd372af7, 0xfd3eeee5, 0xfd4673e7,
|
||||
0xfd4dbc9e, 0xfd54cb85, 0xfd5ba2f2, 0xfd62451b, 0xfd68b415,
|
||||
0xfd6ef1da, 0xfd750047, 0xfd7ae120, 0xfd809612, 0xfd8620b4,
|
||||
0xfd8b8285, 0xfd90bcf5, 0xfd95d15e, 0xfd9ac10b, 0xfd9f8d36,
|
||||
0xfda43708, 0xfda8bf9e, 0xfdad2806, 0xfdb17141, 0xfdb59c46,
|
||||
0xfdb9a9fd, 0xfdbd9b46, 0xfdc170f6, 0xfdc52bd8, 0xfdc8ccac,
|
||||
0xfdcc542d, 0xfdcfc30b, 0xfdd319ef, 0xfdd6597a, 0xfdd98245,
|
||||
0xfddc94e5, 0xfddf91e6, 0xfde279ce, 0xfde54d1f, 0xfde80c52,
|
||||
0xfdeab7de, 0xfded5034, 0xfdefd5be, 0xfdf248e3, 0xfdf4aa06,
|
||||
0xfdf6f984, 0xfdf937b6, 0xfdfb64f4, 0xfdfd818d, 0xfdff8dd0,
|
||||
0xfe018a08, 0xfe03767a, 0xfe05536c, 0xfe07211c, 0xfe08dfc9,
|
||||
0xfe0a8fab, 0xfe0c30fb, 0xfe0dc3ec, 0xfe0f48b1, 0xfe10bf76,
|
||||
0xfe122869, 0xfe1383b4, 0xfe14d17c, 0xfe1611e7, 0xfe174516,
|
||||
0xfe186b2a, 0xfe19843e, 0xfe1a9070, 0xfe1b8fd6, 0xfe1c8289,
|
||||
0xfe1d689b, 0xfe1e4220, 0xfe1f0f26, 0xfe1fcfbc, 0xfe2083ed,
|
||||
0xfe212bc3, 0xfe21c745, 0xfe225678, 0xfe22d95f, 0xfe234ffb,
|
||||
0xfe23ba4a, 0xfe241849, 0xfe2469f2, 0xfe24af3c, 0xfe24e81e,
|
||||
0xfe25148b, 0xfe253474, 0xfe2547c7, 0xfe254e70, 0xfe25485a,
|
||||
0xfe25356a, 0xfe251586, 0xfe24e88f, 0xfe24ae64, 0xfe2466e1,
|
||||
0xfe2411df, 0xfe23af34, 0xfe233eb4, 0xfe22c02c, 0xfe22336b,
|
||||
0xfe219838, 0xfe20ee58, 0xfe20358c, 0xfe1f6d92, 0xfe1e9621,
|
||||
0xfe1daef0, 0xfe1cb7ac, 0xfe1bb002, 0xfe1a9798, 0xfe196e0d,
|
||||
0xfe1832fd, 0xfe16e5fe, 0xfe15869d, 0xfe141464, 0xfe128ed3,
|
||||
0xfe10f565, 0xfe0f478c, 0xfe0d84b1, 0xfe0bac36, 0xfe09bd73,
|
||||
0xfe07b7b5, 0xfe059a40, 0xfe03644c, 0xfe011504, 0xfdfeab88,
|
||||
0xfdfc26e9, 0xfdf98629, 0xfdf6c83b, 0xfdf3ec01, 0xfdf0f04a,
|
||||
0xfdedd3d1, 0xfdea953d, 0xfde7331e, 0xfde3abe9, 0xfddffdfb,
|
||||
0xfddc2791, 0xfdd826cd, 0xfdd3f9a8, 0xfdcf9dfc, 0xfdcb1176,
|
||||
0xfdc65198, 0xfdc15bb3, 0xfdbc2ce2, 0xfdb6c206, 0xfdb117be,
|
||||
0xfdab2a63, 0xfda4f5fd, 0xfd9e7640, 0xfd97a67a, 0xfd908192,
|
||||
0xfd8901f2, 0xfd812182, 0xfd78d98e, 0xfd7022bb, 0xfd66f4ed,
|
||||
0xfd5d4732, 0xfd530f9c, 0xfd48432b, 0xfd3cd59a, 0xfd30b936,
|
||||
0xfd23dea4, 0xfd16349e, 0xfd07a7a3, 0xfcf8219b, 0xfce7895b,
|
||||
0xfcd5c220, 0xfcc2aadb, 0xfcae1d5e, 0xfc97ed4e, 0xfc7fe6d4,
|
||||
0xfc65ccf3, 0xfc495762, 0xfc2a2fc8, 0xfc07ee19, 0xfbe213c1,
|
||||
0xfbb8051a, 0xfb890078, 0xfb5411a5, 0xfb180005, 0xfad33482,
|
||||
0xfa839276, 0xfa263b32, 0xf9b72d1c, 0xf930a1a2, 0xf889f023,
|
||||
0xf7b577d2, 0xf69c650c, 0xf51530f0, 0xf2cb0e3c, 0xeeefb15d,
|
||||
0xe6da6ecf,
|
||||
}
|
||||
@(static)
|
||||
we := [256]f32{
|
||||
2.0249555e-09, 1.486674e-11, 2.4409617e-11, 3.1968806e-11,
|
||||
3.844677e-11, 4.4228204e-11, 4.9516443e-11, 5.443359e-11,
|
||||
5.905944e-11, 6.344942e-11, 6.7643814e-11, 7.1672945e-11,
|
||||
7.556032e-11, 7.932458e-11, 8.298079e-11, 8.654132e-11,
|
||||
9.0016515e-11, 9.3415074e-11, 9.674443e-11, 1.0001099e-10,
|
||||
1.03220314e-10, 1.06377254e-10, 1.09486115e-10, 1.1255068e-10,
|
||||
1.1557435e-10, 1.1856015e-10, 1.2151083e-10, 1.2442886e-10,
|
||||
1.2731648e-10, 1.3017575e-10, 1.3300853e-10, 1.3581657e-10,
|
||||
1.3860142e-10, 1.4136457e-10, 1.4410738e-10, 1.4683108e-10,
|
||||
1.4953687e-10, 1.5222583e-10, 1.54899e-10, 1.5755733e-10,
|
||||
1.6020171e-10, 1.6283301e-10, 1.6545203e-10, 1.6805951e-10,
|
||||
1.7065617e-10, 1.732427e-10, 1.7581973e-10, 1.7838787e-10,
|
||||
1.8094774e-10, 1.8349985e-10, 1.8604476e-10, 1.8858298e-10,
|
||||
1.9111498e-10, 1.9364126e-10, 1.9616223e-10, 1.9867835e-10,
|
||||
2.0119004e-10, 2.0369768e-10, 2.0620168e-10, 2.087024e-10,
|
||||
2.1120022e-10, 2.136955e-10, 2.1618855e-10, 2.1867974e-10,
|
||||
2.2116936e-10, 2.2365775e-10, 2.261452e-10, 2.2863202e-10,
|
||||
2.311185e-10, 2.3360494e-10, 2.360916e-10, 2.3857874e-10,
|
||||
2.4106667e-10, 2.4355562e-10, 2.4604588e-10, 2.485377e-10,
|
||||
2.5103128e-10, 2.5352695e-10, 2.560249e-10, 2.585254e-10,
|
||||
2.6102867e-10, 2.6353494e-10, 2.6604446e-10, 2.6855745e-10,
|
||||
2.7107416e-10, 2.7359479e-10, 2.761196e-10, 2.7864877e-10,
|
||||
2.8118255e-10, 2.8372119e-10, 2.8626485e-10, 2.888138e-10,
|
||||
2.9136826e-10, 2.939284e-10, 2.9649452e-10, 2.9906677e-10,
|
||||
3.016454e-10, 3.0423064e-10, 3.0682268e-10, 3.0942177e-10,
|
||||
3.1202813e-10, 3.1464195e-10, 3.1726352e-10, 3.19893e-10,
|
||||
3.2253064e-10, 3.251767e-10, 3.2783135e-10, 3.3049485e-10,
|
||||
3.3316744e-10, 3.3584938e-10, 3.3854083e-10, 3.4124212e-10,
|
||||
3.4395342e-10, 3.46675e-10, 3.4940711e-10, 3.5215003e-10,
|
||||
3.5490397e-10, 3.5766917e-10, 3.6044595e-10, 3.6323455e-10,
|
||||
3.660352e-10, 3.6884823e-10, 3.7167386e-10, 3.745124e-10,
|
||||
3.773641e-10, 3.802293e-10, 3.8310827e-10, 3.860013e-10,
|
||||
3.8890866e-10, 3.918307e-10, 3.9476775e-10, 3.9772008e-10,
|
||||
4.0068804e-10, 4.0367196e-10, 4.0667217e-10, 4.09689e-10,
|
||||
4.1272286e-10, 4.1577405e-10, 4.1884296e-10, 4.2192994e-10,
|
||||
4.250354e-10, 4.281597e-10, 4.313033e-10, 4.3446652e-10,
|
||||
4.3764986e-10, 4.408537e-10, 4.4407847e-10, 4.4732465e-10,
|
||||
4.5059267e-10, 4.5388301e-10, 4.571962e-10, 4.6053267e-10,
|
||||
4.6389292e-10, 4.6727755e-10, 4.70687e-10, 4.741219e-10,
|
||||
4.7758275e-10, 4.810702e-10, 4.845848e-10, 4.8812715e-10,
|
||||
4.9169796e-10, 4.9529775e-10, 4.989273e-10, 5.0258725e-10,
|
||||
5.0627835e-10, 5.100013e-10, 5.1375687e-10, 5.1754584e-10,
|
||||
5.21369e-10, 5.2522725e-10, 5.2912136e-10, 5.330522e-10,
|
||||
5.370208e-10, 5.4102806e-10, 5.45075e-10, 5.491625e-10,
|
||||
5.532918e-10, 5.5746385e-10, 5.616799e-10, 5.6594107e-10,
|
||||
5.7024857e-10, 5.746037e-10, 5.7900773e-10, 5.834621e-10,
|
||||
5.8796823e-10, 5.925276e-10, 5.971417e-10, 6.018122e-10,
|
||||
6.065408e-10, 6.113292e-10, 6.1617933e-10, 6.2109295e-10,
|
||||
6.260722e-10, 6.3111916e-10, 6.3623595e-10, 6.4142497e-10,
|
||||
6.4668854e-10, 6.5202926e-10, 6.5744976e-10, 6.6295286e-10,
|
||||
6.6854156e-10, 6.742188e-10, 6.79988e-10, 6.858526e-10,
|
||||
6.9181616e-10, 6.978826e-10, 7.04056e-10, 7.103407e-10,
|
||||
7.167412e-10, 7.2326256e-10, 7.2990985e-10, 7.366886e-10,
|
||||
7.4360473e-10, 7.5066453e-10, 7.5787476e-10, 7.6524265e-10,
|
||||
7.7277595e-10, 7.80483e-10, 7.883728e-10, 7.9645507e-10,
|
||||
8.047402e-10, 8.1323964e-10, 8.219657e-10, 8.309319e-10,
|
||||
8.401528e-10, 8.496445e-10, 8.594247e-10, 8.6951274e-10,
|
||||
8.799301e-10, 8.9070046e-10, 9.018503e-10, 9.134092e-10,
|
||||
9.254101e-10, 9.378904e-10, 9.508923e-10, 9.644638e-10,
|
||||
9.786603e-10, 9.935448e-10, 1.0091913e-09, 1.025686e-09,
|
||||
1.0431306e-09, 1.0616465e-09, 1.08138e-09, 1.1025096e-09,
|
||||
1.1252564e-09, 1.1498986e-09, 1.1767932e-09, 1.206409e-09,
|
||||
1.2393786e-09, 1.276585e-09, 1.3193139e-09, 1.3695435e-09,
|
||||
1.4305498e-09, 1.508365e-09, 1.6160854e-09, 1.7921248e-09,
|
||||
}
|
||||
@(static)
|
||||
fe := [256]f32{
|
||||
1, 0.9381437, 0.90046996, 0.87170434, 0.8477855, 0.8269933,
|
||||
0.8084217, 0.7915276, 0.77595687, 0.7614634, 0.7478686,
|
||||
0.7350381, 0.72286767, 0.71127474, 0.70019263, 0.6895665,
|
||||
0.67935055, 0.6695063, 0.66000086, 0.65080583, 0.6418967,
|
||||
0.63325197, 0.6248527, 0.6166822, 0.60872537, 0.60096896,
|
||||
0.5934009, 0.58601034, 0.5787874, 0.57172304, 0.5648092,
|
||||
0.5580383, 0.5514034, 0.5448982, 0.5385169, 0.53225386,
|
||||
0.5261042, 0.52006316, 0.5141264, 0.50828975, 0.5025495,
|
||||
0.496902, 0.49134386, 0.485872, 0.48048335, 0.4751752,
|
||||
0.46994483, 0.46478975, 0.45970762, 0.45469615, 0.44975325,
|
||||
0.44487688, 0.44006512, 0.43531612, 0.43062815, 0.42599955,
|
||||
0.42142874, 0.4169142, 0.41245446, 0.40804818, 0.403694,
|
||||
0.3993907, 0.39513698, 0.39093173, 0.38677382, 0.38266218,
|
||||
0.37859577, 0.37457356, 0.37059465, 0.3666581, 0.362763,
|
||||
0.35890847, 0.35509375, 0.351318, 0.3475805, 0.34388044,
|
||||
0.34021714, 0.3365899, 0.33299807, 0.32944095, 0.32591796,
|
||||
0.3224285, 0.3189719, 0.31554767, 0.31215525, 0.30879408,
|
||||
0.3054636, 0.3021634, 0.29889292, 0.2956517, 0.29243928,
|
||||
0.28925523, 0.28609908, 0.28297043, 0.27986884, 0.27679393,
|
||||
0.2737453, 0.2707226, 0.2677254, 0.26475343, 0.26180625,
|
||||
0.25888354, 0.25598502, 0.2531103, 0.25025907, 0.24743107,
|
||||
0.24462597, 0.24184346, 0.23908329, 0.23634516, 0.23362878,
|
||||
0.23093392, 0.2282603, 0.22560766, 0.22297576, 0.22036438,
|
||||
0.21777324, 0.21520215, 0.21265087, 0.21011916, 0.20760682,
|
||||
0.20511365, 0.20263945, 0.20018397, 0.19774707, 0.19532852,
|
||||
0.19292815, 0.19054577, 0.1881812, 0.18583426, 0.18350479,
|
||||
0.1811926, 0.17889754, 0.17661946, 0.17435817, 0.17211354,
|
||||
0.1698854, 0.16767362, 0.16547804, 0.16329853, 0.16113494,
|
||||
0.15898713, 0.15685499, 0.15473837, 0.15263714, 0.15055119,
|
||||
0.14848037, 0.14642459, 0.14438373, 0.14235765, 0.14034624,
|
||||
0.13834943, 0.13636707, 0.13439907, 0.13244532, 0.13050574,
|
||||
0.1285802, 0.12666863, 0.12477092, 0.12288698, 0.12101672,
|
||||
0.119160056, 0.1173169, 0.115487166, 0.11367077, 0.11186763,
|
||||
0.11007768, 0.10830083, 0.10653701, 0.10478614, 0.10304816,
|
||||
0.101323, 0.09961058, 0.09791085, 0.09622374, 0.09454919,
|
||||
0.09288713, 0.091237515, 0.08960028, 0.087975375, 0.08636274,
|
||||
0.08476233, 0.083174095, 0.081597984, 0.08003395, 0.07848195,
|
||||
0.076941945, 0.07541389, 0.07389775, 0.072393484, 0.07090106,
|
||||
0.069420435, 0.06795159, 0.066494495, 0.06504912, 0.063615434,
|
||||
0.062193416, 0.060783047, 0.059384305, 0.057997175,
|
||||
0.05662164, 0.05525769, 0.053905312, 0.052564494, 0.051235236,
|
||||
0.049917534, 0.048611384, 0.047316793, 0.046033762, 0.0447623,
|
||||
0.043502413, 0.042254124, 0.041017443, 0.039792392,
|
||||
0.038578995, 0.037377283, 0.036187284, 0.035009038,
|
||||
0.033842582, 0.032687962, 0.031545233, 0.030414443, 0.02929566,
|
||||
0.02818895, 0.027094385, 0.026012046, 0.024942026, 0.023884421,
|
||||
0.022839336, 0.021806888, 0.020787204, 0.019780423, 0.0187867,
|
||||
0.0178062, 0.016839107, 0.015885621, 0.014945968, 0.014020392,
|
||||
0.013109165, 0.012212592, 0.011331013, 0.01046481, 0.009614414,
|
||||
0.008780315, 0.007963077, 0.0071633533, 0.006381906,
|
||||
0.0056196423, 0.0048776558, 0.004157295, 0.0034602648,
|
||||
0.0027887989, 0.0021459677, 0.0015362998, 0.0009672693,
|
||||
0.00045413437,
|
||||
}
|
||||
|
||||
for {
|
||||
j := uint32(r)
|
||||
i := j & 0xFF
|
||||
x := f64(j) * f64(we[i])
|
||||
if j < ke[i] {
|
||||
return x
|
||||
}
|
||||
if i == 0 {
|
||||
return re - math.ln(float64(r))
|
||||
}
|
||||
if fe[i]+f32(float64(r))*(fe[i-1]-fe[i]) < f32(math.exp(-x)) {
|
||||
return x
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,12 @@ package rand
|
||||
|
||||
import "core:math"
|
||||
|
||||
|
||||
// norm_float64 returns a normally distributed f64 in the range -max(f64) through +max(f64) inclusive,
|
||||
// with a standard normal distribution with a mean of 0 and standard deviation of 1.
|
||||
//
|
||||
// sample = norm_float64() * std_dev + mean
|
||||
//
|
||||
//
|
||||
// Normal distribution
|
||||
//
|
||||
@@ -11,12 +17,6 @@ import "core:math"
|
||||
// https://www.jstatsoft.org/index.php/jss/article/view/v005i08/ziggurat.pdf [pdf]
|
||||
// https://www.jstatsoft.org/article/view/v005i08 [web page]
|
||||
//
|
||||
|
||||
// norm_float64 returns a normally distributed f64 in the range -max(f64) through +max(f64) inclusive,
|
||||
// with a standard normal distribution with a mean of 0 and standard deviation of 1.
|
||||
//
|
||||
// sample = norm_float64() * std_dev + mean
|
||||
//
|
||||
norm_float64 :: proc(r: ^Rand = nil) -> f64 {
|
||||
rn :: 3.442619855899
|
||||
|
||||
@@ -49,7 +49,6 @@ norm_float64 :: proc(r: ^Rand = nil) -> f64 {
|
||||
0x7da61a1e, 0x7d72a0fb, 0x7d30e097, 0x7cd9b4ab, 0x7c600f1a,
|
||||
0x7ba90bdc, 0x7a722176, 0x77d664e5,
|
||||
}
|
||||
|
||||
@(static)
|
||||
wn := [128]f32{
|
||||
1.7290405e-09, 1.2680929e-10, 1.6897518e-10, 1.9862688e-10,
|
||||
@@ -85,7 +84,6 @@ norm_float64 :: proc(r: ^Rand = nil) -> f64 {
|
||||
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{
|
||||
1.00000000, 0.9635997, 0.9362827, 0.9130436, 0.89228165,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package rand
|
||||
|
||||
import "core:intrinsics"
|
||||
|
||||
Rand :: struct {
|
||||
state: u64,
|
||||
inc: u64,
|
||||
@@ -7,9 +9,7 @@ Rand :: struct {
|
||||
|
||||
|
||||
@(private)
|
||||
_GLOBAL_SEED_DATA := 1234567890
|
||||
@(private)
|
||||
global_rand := create(u64(uintptr(&_GLOBAL_SEED_DATA)))
|
||||
global_rand := create(u64(intrinsics.read_cycle_counter()))
|
||||
|
||||
set_global_seed :: proc(seed: u64) {
|
||||
init(&global_rand, seed)
|
||||
@@ -70,7 +70,7 @@ int31_max :: proc(n: i32, r: ^Rand = nil) -> i32 {
|
||||
if n&(n-1) == 0 {
|
||||
return int31(r) & (n-1)
|
||||
}
|
||||
max := i32((1<<31) - 1 - (1<<31)&u32(n))
|
||||
max := i32((1<<31) - 1 - (1<<31)%u32(n))
|
||||
v := int31(r)
|
||||
for v > max {
|
||||
v = int31(r)
|
||||
@@ -85,7 +85,7 @@ int63_max :: proc(n: i64, r: ^Rand = nil) -> i64 {
|
||||
if n&(n-1) == 0 {
|
||||
return int63(r) & (n-1)
|
||||
}
|
||||
max := i64((1<<63) - 1 - (1<<63)&u64(n))
|
||||
max := i64((1<<63) - 1 - (1<<63)%u64(n))
|
||||
v := int63(r)
|
||||
for v > max {
|
||||
v = int63(r)
|
||||
@@ -100,7 +100,7 @@ int127_max :: proc(n: i128, r: ^Rand = nil) -> i128 {
|
||||
if n&(n-1) == 0 {
|
||||
return int127(r) & (n-1)
|
||||
}
|
||||
max := i128((1<<63) - 1 - (1<<63)&u128(n))
|
||||
max := i128((1<<127) - 1 - (1<<127)%u128(n))
|
||||
v := int127(r)
|
||||
for v > max {
|
||||
v = int127(r)
|
||||
@@ -142,8 +142,8 @@ read :: proc(p: []byte, r: ^Rand = nil) -> (n: int) {
|
||||
}
|
||||
|
||||
// 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)
|
||||
perm :: proc(n: int, r: ^Rand = nil, allocator := context.allocator) -> []int {
|
||||
m := make([]int, n, allocator)
|
||||
for i := 0; i < n; i += 1 {
|
||||
j := int_max(i+1, r)
|
||||
m[i] = m[j]
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
package mem implements various types of allocators.
|
||||
|
||||
|
||||
An example of how to use the `Tracking_Allocator` to track subsequent allocations
|
||||
in your program and report leaks and bad frees:
|
||||
|
||||
```odin
|
||||
package foo
|
||||
|
||||
import "core:mem"
|
||||
import "core:fmt"
|
||||
|
||||
_main :: proc() {
|
||||
do stuff
|
||||
}
|
||||
|
||||
main :: proc() {
|
||||
track: mem.Tracking_Allocator
|
||||
mem.tracking_allocator_init(&track, context.allocator)
|
||||
context.allocator = mem.tracking_allocator(&track)
|
||||
|
||||
_main()
|
||||
|
||||
for _, v in track.allocation_map {
|
||||
fmt.printf("%v leaked %v bytes", v.location, v.size)
|
||||
}
|
||||
for bf in track.bad_free_array {
|
||||
fmt.printf("%v allocation %p was freed badly", bf.location, bf.memory)
|
||||
}
|
||||
}
|
||||
```
|
||||
*/
|
||||
package mem
|
||||
@@ -151,6 +151,7 @@ Comp_Lit :: struct {
|
||||
open: tokenizer.Pos,
|
||||
elems: []^Expr,
|
||||
close: tokenizer.Pos,
|
||||
tag: ^Expr,
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ String :: distinct Array(byte)
|
||||
|
||||
Version_Type_Major :: 0
|
||||
Version_Type_Minor :: 2
|
||||
Version_Type_Patch :: 3
|
||||
Version_Type_Patch :: 4
|
||||
|
||||
Version_Type :: struct {
|
||||
major, minor, patch: u8,
|
||||
@@ -77,9 +77,15 @@ Pkg :: struct {
|
||||
flags: Pkg_Flags,
|
||||
docs: String,
|
||||
files: Array(File_Index),
|
||||
entities: Array(Entity_Index),
|
||||
entries: Array(Scope_Entry),
|
||||
}
|
||||
|
||||
Scope_Entry :: struct {
|
||||
name: String,
|
||||
entity: Entity_Index,
|
||||
}
|
||||
|
||||
|
||||
Entity_Kind :: enum u32le {
|
||||
Invalid = 0,
|
||||
Constant = 1,
|
||||
@@ -89,6 +95,7 @@ Entity_Kind :: enum u32le {
|
||||
Proc_Group = 5,
|
||||
Import_Name = 6,
|
||||
Library_Name = 7,
|
||||
Builtin = 8,
|
||||
}
|
||||
|
||||
Entity_Flag :: enum u32le {
|
||||
@@ -105,6 +112,9 @@ Entity_Flag :: enum u32le {
|
||||
|
||||
Type_Alias = 20,
|
||||
|
||||
Builtin_Pkg_Builtin = 30,
|
||||
Builtin_Pkg_Intrinsics = 31,
|
||||
|
||||
Var_Thread_Local = 40,
|
||||
Var_Static = 41,
|
||||
|
||||
|
||||
@@ -2273,6 +2273,24 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
||||
return original_type
|
||||
|
||||
case "partial":
|
||||
tag := ast.new(ast.Basic_Directive, tok.pos, end_pos(name))
|
||||
tag.tok = tok
|
||||
tag.name = name.text
|
||||
original_expr := parse_expr(p, lhs)
|
||||
expr := ast.unparen_expr(original_expr)
|
||||
switch t in &expr.derived {
|
||||
case ast.Comp_Lit:
|
||||
t.tag = tag
|
||||
case ast.Array_Type:
|
||||
t.tag = tag
|
||||
error(p, tok.pos, "#%s has been replaced with #sparse for non-contiguous enumerated array types", name.text)
|
||||
case:
|
||||
error(p, tok.pos, "expected a compound literal after #%s", name.text)
|
||||
|
||||
}
|
||||
return original_expr
|
||||
|
||||
case "sparse":
|
||||
tag := ast.new(ast.Basic_Directive, tok.pos, end_pos(name))
|
||||
tag.tok = tok
|
||||
tag.name = name.text
|
||||
@@ -2319,7 +2337,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
||||
return rt
|
||||
|
||||
case "force_inline", "force_no_inline":
|
||||
return parse_inlining_operand(p, lhs, tok)
|
||||
return parse_inlining_operand(p, lhs, name)
|
||||
case:
|
||||
expr := parse_expr(p, lhs)
|
||||
te := ast.new(ast.Tag_Expr, tok.pos, expr.pos)
|
||||
|
||||
+10
-2
@@ -206,11 +206,19 @@ heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
|
||||
}
|
||||
}
|
||||
|
||||
aligned_resize :: proc(p: rawptr, old_size: int, new_size: int, new_alignment: int) -> ([]byte, mem.Allocator_Error) {
|
||||
aligned_resize :: proc(p: rawptr, old_size: int, new_size: int, new_alignment: int) -> (new_memory: []byte, err: mem.Allocator_Error) {
|
||||
if p == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return aligned_alloc(new_size, new_alignment, p)
|
||||
|
||||
new_memory = aligned_alloc(new_size, new_alignment, p) or_return
|
||||
|
||||
// NOTE: heap_resize does not zero the new memory, so we do it
|
||||
if new_size > old_size {
|
||||
new_region := mem.raw_data(new_memory[old_size:])
|
||||
mem.zero(new_region, new_size - old_size)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
switch mode {
|
||||
|
||||
+82
-5
@@ -290,13 +290,21 @@ foreign libc {
|
||||
@(link_name="fstat64") _unix_fstat :: proc(fd: Handle, stat: ^OS_Stat) -> c.int ---
|
||||
@(link_name="readlink") _unix_readlink :: proc(path: cstring, buf: ^byte, bufsiz: c.size_t) -> c.ssize_t ---
|
||||
@(link_name="access") _unix_access :: proc(path: cstring, mask: int) -> int ---
|
||||
@(link_name="fdopendir$INODE64") _unix_fdopendir :: proc(fd: Handle) -> Dir ---
|
||||
|
||||
@(link_name="fdopendir$INODE64") _unix_fdopendir_amd64 :: proc(fd: Handle) -> Dir ---
|
||||
@(link_name="readdir_r$INODE64") _unix_readdir_r_amd64 :: proc(dirp: Dir, entry: ^Dirent, result: ^^Dirent) -> c.int ---
|
||||
@(link_name="fdopendir") _unix_fdopendir_arm64 :: proc(fd: Handle) -> Dir ---
|
||||
@(link_name="readdir_r") _unix_readdir_r_arm64 :: proc(dirp: Dir, entry: ^Dirent, result: ^^Dirent) -> c.int ---
|
||||
|
||||
@(link_name="closedir") _unix_closedir :: proc(dirp: Dir) -> c.int ---
|
||||
@(link_name="rewinddir") _unix_rewinddir :: proc(dirp: Dir) ---
|
||||
@(link_name="readdir_r$INODE64") _unix_readdir_r :: proc(dirp: Dir, entry: ^Dirent, result: ^^Dirent) -> c.int ---
|
||||
|
||||
@(link_name="fcntl") _unix_fcntl :: proc(fd: Handle, cmd: c.int, buf: ^byte) -> c.int ---
|
||||
|
||||
@(link_name="fchmod") _unix_fchmod :: proc(fildes: Handle, mode: u16) -> c.int ---;
|
||||
@(link_name="rename") _unix_rename :: proc(old: cstring, new: cstring) -> c.int ---
|
||||
@(link_name="remove") _unix_remove :: proc(path: cstring) -> c.int ---
|
||||
|
||||
@(link_name="fchmod") _unix_fchmod :: proc(fildes: Handle, mode: u16) -> c.int ---
|
||||
|
||||
@(link_name="malloc") _unix_malloc :: proc(size: int) -> rawptr ---
|
||||
@(link_name="calloc") _unix_calloc :: proc(num, size: int) -> rawptr ---
|
||||
@@ -307,11 +315,19 @@ foreign libc {
|
||||
@(link_name="chdir") _unix_chdir :: proc(buf: cstring) -> c.int ---
|
||||
@(link_name="realpath") _unix_realpath :: proc(path: cstring, resolved_path: rawptr) -> rawptr ---
|
||||
|
||||
@(link_name="strerror") _darwin_string_error :: proc(num : c.int) -> cstring ---;
|
||||
@(link_name="strerror") _darwin_string_error :: proc(num : c.int) -> cstring ---
|
||||
|
||||
@(link_name="exit") _unix_exit :: proc(status: c.int) -> ! ---
|
||||
}
|
||||
|
||||
when ODIN_ARCH != "arm64" {
|
||||
_unix_fdopendir :: proc {_unix_fdopendir_amd64}
|
||||
_unix_readdir_r :: proc {_unix_readdir_r_amd64}
|
||||
} else {
|
||||
_unix_fdopendir :: proc {_unix_fdopendir_arm64}
|
||||
_unix_readdir_r :: proc {_unix_readdir_r_arm64}
|
||||
}
|
||||
|
||||
foreign dl {
|
||||
@(link_name="dlopen") _unix_dlopen :: proc(filename: cstring, flags: int) -> rawptr ---
|
||||
@(link_name="dlsym") _unix_dlsym :: proc(handle: rawptr, symbol: cstring) -> rawptr ---
|
||||
@@ -324,7 +340,7 @@ get_last_error :: proc() -> int {
|
||||
}
|
||||
|
||||
get_last_error_string :: proc() -> string {
|
||||
return cast(string)_darwin_string_error(cast(c.int)get_last_error());
|
||||
return cast(string)_darwin_string_error(cast(c.int)get_last_error())
|
||||
}
|
||||
|
||||
open :: proc(path: string, flags: int = O_RDWR, mode: int = 0) -> (Handle, Errno) {
|
||||
@@ -412,6 +428,65 @@ is_path_separator :: proc(r: rune) -> bool {
|
||||
return r == '/'
|
||||
}
|
||||
|
||||
is_file_handle :: proc(fd: Handle) -> bool {
|
||||
s, err := _fstat(fd)
|
||||
if err != ERROR_NONE {
|
||||
return false
|
||||
}
|
||||
return S_ISREG(cast(u32)s.mode)
|
||||
}
|
||||
|
||||
is_file_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
s: OS_Stat
|
||||
err: Errno
|
||||
if follow_links {
|
||||
s, err = _stat(path)
|
||||
} else {
|
||||
s, err = _lstat(path)
|
||||
}
|
||||
if err != ERROR_NONE {
|
||||
return false
|
||||
}
|
||||
return S_ISREG(cast(u32)s.mode)
|
||||
}
|
||||
|
||||
|
||||
is_dir_handle :: proc(fd: Handle) -> bool {
|
||||
s, err := _fstat(fd)
|
||||
if err != ERROR_NONE {
|
||||
return false
|
||||
}
|
||||
return S_ISDIR(cast(u32)s.mode)
|
||||
}
|
||||
|
||||
is_dir_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||
s: OS_Stat
|
||||
err: Errno
|
||||
if follow_links {
|
||||
s, err = _stat(path)
|
||||
} else {
|
||||
s, err = _lstat(path)
|
||||
}
|
||||
if err != ERROR_NONE {
|
||||
return false
|
||||
}
|
||||
return S_ISDIR(cast(u32)s.mode)
|
||||
}
|
||||
|
||||
is_file :: proc {is_file_path, is_file_handle}
|
||||
is_dir :: proc {is_dir_path, is_dir_handle}
|
||||
|
||||
|
||||
rename :: proc(old: string, new: string) -> bool {
|
||||
old_cstr := strings.clone_to_cstring(old, context.temp_allocator)
|
||||
new_cstr := strings.clone_to_cstring(new, context.temp_allocator)
|
||||
return _unix_rename(old_cstr, new_cstr) != -1
|
||||
}
|
||||
|
||||
remove :: proc(path: string) -> bool {
|
||||
path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
||||
return _unix_remove(path_cstr) != -1
|
||||
}
|
||||
|
||||
@private
|
||||
_stat :: proc(path: string) -> (OS_Stat, Errno) {
|
||||
@@ -553,6 +628,8 @@ heap_alloc :: proc(size: int) -> rawptr {
|
||||
return _unix_calloc(1, size)
|
||||
}
|
||||
heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
|
||||
// NOTE: _unix_realloc doesn't guarantee new memory will be zeroed on
|
||||
// POSIX platforms. Ensure your caller takes this into account.
|
||||
return _unix_realloc(ptr, new_size)
|
||||
}
|
||||
heap_free :: proc(ptr: rawptr) {
|
||||
|
||||
@@ -378,6 +378,8 @@ heap_alloc :: proc(size: int) -> rawptr {
|
||||
}
|
||||
|
||||
heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
|
||||
// NOTE: _unix_realloc doesn't guarantee new memory will be zeroed on
|
||||
// POSIX platforms. Ensure your caller takes this into account.
|
||||
return _unix_realloc(ptr, c.size_t(new_size));
|
||||
}
|
||||
|
||||
|
||||
@@ -727,6 +727,8 @@ heap_alloc :: proc(size: int) -> rawptr {
|
||||
}
|
||||
|
||||
heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
|
||||
// NOTE: _unix_realloc doesn't guarantee new memory will be zeroed on
|
||||
// POSIX platforms. Ensure your caller takes this into account.
|
||||
return _unix_realloc(ptr, c.size_t(new_size))
|
||||
}
|
||||
|
||||
|
||||
@@ -227,11 +227,10 @@ glob :: proc(pattern: string, allocator := context.allocator) -> (matches: []str
|
||||
return m[:], .None
|
||||
}
|
||||
|
||||
temp_buf: [8]byte
|
||||
|
||||
dir, file := split(pattern)
|
||||
volume_len := 0
|
||||
when ODIN_OS == .Windows {
|
||||
temp_buf: [8]byte
|
||||
volume_len, dir = clean_glob_path_windows(dir, temp_buf[:])
|
||||
} else {
|
||||
dir = clean_glob_path(dir)
|
||||
|
||||
@@ -71,7 +71,7 @@ _walk :: proc(info: os.File_Info, walk_proc: Walk_Proc) -> (err: os.Errno, skip_
|
||||
|
||||
@(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, os.O_RDONLY)
|
||||
if err != 0 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ is_nil :: proc(v: any) -> bool {
|
||||
return true
|
||||
}
|
||||
data := as_bytes(v)
|
||||
if data != nil {
|
||||
if data == nil {
|
||||
return true
|
||||
}
|
||||
for v in data {
|
||||
|
||||
@@ -472,6 +472,9 @@ write_type_writer :: proc(w: io.Writer, ti: ^Type_Info, n_written: ^int = nil) -
|
||||
write_type(w, info.elem, &n) or_return
|
||||
|
||||
case Type_Info_Enumerated_Array:
|
||||
if info.is_sparse {
|
||||
io.write_string(w, "#sparse", &n) or_return
|
||||
}
|
||||
io.write_string(w, "[", &n) or_return
|
||||
write_type(w, info.index, &n) or_return
|
||||
io.write_string(w, "]", &n) or_return
|
||||
|
||||
@@ -95,6 +95,7 @@ Type_Info_Enumerated_Array :: struct {
|
||||
count: int,
|
||||
min_value: Type_Info_Enum_Value,
|
||||
max_value: Type_Info_Enum_Value,
|
||||
is_sparse: bool,
|
||||
}
|
||||
Type_Info_Dynamic_Array :: struct {elem: ^Type_Info, elem_size: int}
|
||||
Type_Info_Slice :: struct {elem: ^Type_Info, elem_size: int}
|
||||
|
||||
@@ -614,6 +614,10 @@ raw_data :: proc{raw_array_data, raw_slice_data, raw_dynamic_array_data, raw_str
|
||||
@(disabled=ODIN_DISABLE_ASSERT)
|
||||
assert :: proc(condition: bool, message := "", loc := #caller_location) {
|
||||
if !condition {
|
||||
// NOTE(bill): This is wrapped in a procedure call
|
||||
// to improve performance to make the CPU not
|
||||
// execute speculatively, making it about an order of
|
||||
// magnitude faster
|
||||
proc(message: string, loc: Source_Code_Location) {
|
||||
p := context.assertion_failure_proc
|
||||
if p == nil {
|
||||
|
||||
@@ -37,10 +37,8 @@ bswap_64 :: proc "contextless" (x: u64) -> u64 {
|
||||
|
||||
bswap_128 :: proc "contextless" (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])
|
||||
z[0], z[3] = bswap_32(z[3]), bswap_32(z[0])
|
||||
z[1], z[2] = bswap_32(z[2]), bswap_32(z[1])
|
||||
return transmute(u128)z
|
||||
}
|
||||
|
||||
|
||||
+18
-5
@@ -143,11 +143,21 @@ print_int :: proc "contextless" (x: int) { print_i64(i64(x)) }
|
||||
|
||||
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(')')
|
||||
when ODIN_ERROR_POS_STYLE == .Default {
|
||||
print_byte('(')
|
||||
print_u64(u64(line))
|
||||
print_byte(':')
|
||||
print_u64(u64(column))
|
||||
print_byte(')')
|
||||
} else when ODIN_ERROR_POS_STYLE == .Unix {
|
||||
print_byte(':')
|
||||
print_u64(u64(line))
|
||||
print_byte(':')
|
||||
print_u64(u64(column))
|
||||
print_byte(':')
|
||||
} else {
|
||||
#panic("unhandled ODIN_ERROR_POS_STYLE")
|
||||
}
|
||||
}
|
||||
print_typeid :: proc "contextless" (id: typeid) {
|
||||
if id == nil {
|
||||
@@ -250,6 +260,9 @@ print_type :: proc "contextless" (ti: ^Type_Info) {
|
||||
print_type(info.elem)
|
||||
|
||||
case Type_Info_Enumerated_Array:
|
||||
if info.is_sparse {
|
||||
print_string("#sparse")
|
||||
}
|
||||
print_byte('[')
|
||||
print_type(info.index)
|
||||
print_byte(']')
|
||||
|
||||
+12
-12
@@ -305,21 +305,21 @@ filter :: proc(s: $S/[]$U, f: proc(U) -> bool, allocator := context.allocator) -
|
||||
}
|
||||
|
||||
scanner :: proc (s: $S/[]$U, initializer: $V, f: proc(V, U)->V, allocator := context.allocator) -> []V {
|
||||
if len(s) == 0 { return {} }
|
||||
if len(s) == 0 { return {} }
|
||||
|
||||
res := make([]V, len(s), allocator)
|
||||
p := as_ptr(s)
|
||||
q := as_ptr(res)
|
||||
r := initializer
|
||||
res := make([]V, len(s), allocator)
|
||||
p := as_ptr(s)
|
||||
q := as_ptr(res)
|
||||
r := initializer
|
||||
|
||||
for l := len(s); l > 0; l -= 1 {
|
||||
r = f(r, p[0])
|
||||
q[0] = r
|
||||
p = p[1:]
|
||||
q = q[1:]
|
||||
}
|
||||
for l := len(s); l > 0; l -= 1 {
|
||||
r = f(r, p[0])
|
||||
q[0] = r
|
||||
p = p[1:]
|
||||
q = q[1:]
|
||||
}
|
||||
|
||||
return res
|
||||
return res
|
||||
}
|
||||
|
||||
|
||||
|
||||
+31
-488
@@ -1,10 +1,5 @@
|
||||
package slice
|
||||
|
||||
import "core:intrinsics"
|
||||
_ :: intrinsics
|
||||
|
||||
ORD :: intrinsics.type_is_ordered
|
||||
|
||||
Ordering :: enum {
|
||||
Less = -1,
|
||||
Equal = 0,
|
||||
@@ -38,7 +33,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_general(data, 0, n, _max_depth(n), struct{}{}, .Ordered)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,7 +43,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_general(data, 0, n, _max_depth(n), less, .Less)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -56,7 +51,33 @@ 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_general(data, 0, n, _max_depth(n), cmp, .Cmp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// stable_sort sorts a slice
|
||||
stable_sort :: proc(data: $T/[]$E) where ORD(E) {
|
||||
when size_of(E) != 0 {
|
||||
if n := len(data); n > 1 {
|
||||
_stable_sort_general(data, struct{}{}, .Ordered)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// stable_sort_by sorts a slice with a given procedure to test whether two values are ordered "i < j"
|
||||
stable_sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) {
|
||||
when size_of(E) != 0 {
|
||||
if n := len(data); n > 1 {
|
||||
_stable_sort_general(data, less, .Less)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stable_sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) {
|
||||
when size_of(E) != 0 {
|
||||
if n := len(data); n > 1 {
|
||||
_stable_sort_general(data, cmp, .Cmp)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -79,6 +100,7 @@ is_sorted_by :: proc(array: $T/[]$E, less: proc(i, j: E) -> bool) -> bool {
|
||||
return true
|
||||
}
|
||||
|
||||
is_sorted_by_cmp :: is_sorted_cmp
|
||||
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 {
|
||||
@@ -140,489 +162,10 @@ is_sorted_by_key :: proc(array: $T/[]$E, key: proc(E) -> $K) -> bool where ORD(K
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
|
||||
@(private)
|
||||
_max_depth :: proc(n: int) -> int { // 2*ceil(log2(n+1))
|
||||
depth: int
|
||||
_max_depth :: proc(n: int) -> (depth: int) { // 2*ceil(log2(n+1))
|
||||
for i := n; i > 0; i >>= 1 {
|
||||
depth += 1
|
||||
}
|
||||
return depth * 2
|
||||
}
|
||||
|
||||
@(private)
|
||||
_quick_sort :: proc(data: $T/[]$E, a, b, max_depth: int) where ORD(E) #no_bounds_check {
|
||||
median3 :: proc(data: T, m1, m0, m2: int) #no_bounds_check {
|
||||
if data[m1] < data[m0] {
|
||||
swap(data, m1, m0)
|
||||
}
|
||||
if data[m2] < data[m1] {
|
||||
swap(data, m2, m1)
|
||||
if data[m1] < data[m0] {
|
||||
swap(data, m1, m0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
do_pivot :: proc(data: T, lo, hi: int) -> (midlo, midhi: int) #no_bounds_check {
|
||||
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)
|
||||
}
|
||||
median3(data, lo, m, hi-1)
|
||||
|
||||
|
||||
pivot := lo
|
||||
a, c := lo+1, hi-1
|
||||
|
||||
for ; a < c && data[a] < data[pivot]; a += 1 {
|
||||
}
|
||||
b := a
|
||||
|
||||
for {
|
||||
for ; b < c && !(data[pivot] < data[b]); b += 1 { // data[b] <= pivot
|
||||
}
|
||||
for ; b < c && data[pivot] < data[c-1]; c -=1 { // data[c-1] > pivot
|
||||
}
|
||||
if b >= c {
|
||||
break
|
||||
}
|
||||
|
||||
swap(data, b, c-1)
|
||||
b += 1
|
||||
c -= 1
|
||||
}
|
||||
|
||||
protect := hi-c < 5
|
||||
if !protect && hi-c < (hi-lo)/4 {
|
||||
dups := 0
|
||||
if !(data[pivot] < data[hi-1]) {
|
||||
swap(data, c, hi-1)
|
||||
c += 1
|
||||
dups += 1
|
||||
}
|
||||
if !(data[b-1] < data[pivot]) {
|
||||
b -= 1
|
||||
dups += 1
|
||||
}
|
||||
|
||||
if !(data[m] < data[pivot]) {
|
||||
swap(data, m, b-1)
|
||||
b -= 1
|
||||
dups += 1
|
||||
}
|
||||
protect = dups > 1
|
||||
}
|
||||
if protect {
|
||||
for {
|
||||
for ; a < b && !(data[b-1] < data[pivot]); b -= 1 {
|
||||
}
|
||||
for ; a < b && data[a] < data[pivot]; a += 1 {
|
||||
}
|
||||
if a >= b {
|
||||
break
|
||||
}
|
||||
swap(data, a, b-1)
|
||||
a += 1
|
||||
b -= 1
|
||||
}
|
||||
}
|
||||
swap(data, pivot, b-1)
|
||||
return b-1, c
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
max_depth -= 1
|
||||
mlo, mhi := do_pivot(data, a, b)
|
||||
if mlo-a < b-mhi {
|
||||
_quick_sort(data, a, mlo, max_depth)
|
||||
a = mhi
|
||||
} else {
|
||||
_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)
|
||||
}
|
||||
}
|
||||
_insertion_sort(data, a, b)
|
||||
}
|
||||
}
|
||||
|
||||
@(private)
|
||||
_insertion_sort :: proc(data: $T/[]$E, a, b: int) where ORD(E) #no_bounds_check {
|
||||
for i in a+1..<b {
|
||||
for j := i; j > a && data[j] < data[j-1]; j -= 1 {
|
||||
swap(data, j, j-1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@(private)
|
||||
_heap_sort :: proc(data: $T/[]$E, a, b: int) where ORD(E) #no_bounds_check {
|
||||
sift_down :: proc(data: T, lo, hi, first: int) #no_bounds_check {
|
||||
root := lo
|
||||
for {
|
||||
child := 2*root + 1
|
||||
if child >= hi {
|
||||
break
|
||||
}
|
||||
if child+1 < hi && data[first+child] < data[first+child+1] {
|
||||
child += 1
|
||||
}
|
||||
if !(data[first+root] < data[first+child]) {
|
||||
return
|
||||
}
|
||||
swap(data, first+root, first+child)
|
||||
root = child
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
first, lo, hi := a, 0, b-a
|
||||
|
||||
for i := (hi-1)/2; i >= 0; i -= 1 {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@(private)
|
||||
_quick_sort_less :: proc(data: $T/[]$E, a, b, max_depth: int, less: proc(i, j: E) -> bool) #no_bounds_check {
|
||||
median3 :: proc(data: T, m1, m0, m2: int, less: proc(i, j: E) -> bool) #no_bounds_check {
|
||||
if less(data[m1], data[m0]) {
|
||||
swap(data, m1, m0)
|
||||
}
|
||||
if less(data[m2], data[m1]) {
|
||||
swap(data, m2, m1)
|
||||
if less(data[m1], data[m0]) {
|
||||
swap(data, m1, m0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
do_pivot :: proc(data: T, lo, hi: int, less: proc(i, j: E) -> bool) -> (midlo, midhi: int) #no_bounds_check {
|
||||
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)
|
||||
}
|
||||
median3(data, lo, m, hi-1, less)
|
||||
|
||||
pivot := lo
|
||||
a, c := lo+1, hi-1
|
||||
|
||||
for ; a < c && less(data[a], data[pivot]); a += 1 {
|
||||
}
|
||||
b := a
|
||||
|
||||
for {
|
||||
for ; b < c && !less(data[pivot], data[b]); b += 1 { // data[b] <= pivot
|
||||
}
|
||||
for ; b < c && less(data[pivot], data[c-1]); c -=1 { // data[c-1] > pivot
|
||||
}
|
||||
if b >= c {
|
||||
break
|
||||
}
|
||||
|
||||
swap(data, b, c-1)
|
||||
b += 1
|
||||
c -= 1
|
||||
}
|
||||
|
||||
protect := hi-c < 5
|
||||
if !protect && hi-c < (hi-lo)/4 {
|
||||
dups := 0
|
||||
if !less(data[pivot], data[hi-1]) {
|
||||
swap(data, c, hi-1)
|
||||
c += 1
|
||||
dups += 1
|
||||
}
|
||||
if !less(data[b-1], data[pivot]) {
|
||||
b -= 1
|
||||
dups += 1
|
||||
}
|
||||
|
||||
if !less(data[m], data[pivot]) {
|
||||
swap(data, m, b-1)
|
||||
b -= 1
|
||||
dups += 1
|
||||
}
|
||||
protect = dups > 1
|
||||
}
|
||||
if protect {
|
||||
for {
|
||||
for ; a < b && !less(data[b-1], data[pivot]); b -= 1 {
|
||||
}
|
||||
for ; a < b && less(data[a], data[pivot]); a += 1 {
|
||||
}
|
||||
if a >= b {
|
||||
break
|
||||
}
|
||||
swap(data, a, b-1)
|
||||
a += 1
|
||||
b -= 1
|
||||
}
|
||||
}
|
||||
swap(data, pivot, b-1)
|
||||
return b-1, c
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
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
|
||||
} else {
|
||||
_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)
|
||||
}
|
||||
}
|
||||
_insertion_sort_less(data, a, b, less)
|
||||
}
|
||||
}
|
||||
|
||||
@(private)
|
||||
_insertion_sort_less :: proc(data: $T/[]$E, a, b: int, less: proc(i, j: E) -> bool) #no_bounds_check {
|
||||
for i in a+1..<b {
|
||||
for j := i; j > a && less(data[j], data[j-1]); j -= 1 {
|
||||
swap(data, j, j-1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@(private)
|
||||
_heap_sort_less :: proc(data: $T/[]$E, a, b: int, less: proc(i, j: E) -> bool) #no_bounds_check {
|
||||
sift_down :: proc(data: T, lo, hi, first: int, less: proc(i, j: E) -> bool) #no_bounds_check {
|
||||
root := lo
|
||||
for {
|
||||
child := 2*root + 1
|
||||
if child >= hi {
|
||||
break
|
||||
}
|
||||
if child+1 < hi && less(data[first+child], data[first+child+1]) {
|
||||
child += 1
|
||||
}
|
||||
if !less(data[first+root], data[first+child]) {
|
||||
return
|
||||
}
|
||||
swap(data, first+root, first+child)
|
||||
root = child
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
first, lo, hi := a, 0, b-a
|
||||
|
||||
for i := (hi-1)/2; i >= 0; i -= 1 {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@(private)
|
||||
_quick_sort_cmp :: proc(data: $T/[]$E, a, b, max_depth: int, cmp: proc(i, j: E) -> Ordering) #no_bounds_check {
|
||||
median3 :: proc(data: T, m1, m0, m2: int, cmp: proc(i, j: E) -> Ordering) #no_bounds_check {
|
||||
if cmp(data[m1], data[m0]) == .Less {
|
||||
swap(data, m1, m0)
|
||||
}
|
||||
if cmp(data[m2], data[m1]) == .Less {
|
||||
swap(data, m2, m1)
|
||||
if cmp(data[m1], data[m0]) == .Less {
|
||||
swap(data, m1, m0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
do_pivot :: proc(data: T, lo, hi: int, cmp: proc(i, j: E) -> Ordering) -> (midlo, midhi: int) #no_bounds_check {
|
||||
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)
|
||||
}
|
||||
median3(data, lo, m, hi-1, cmp)
|
||||
|
||||
pivot := lo
|
||||
a, c := lo+1, hi-1
|
||||
|
||||
for ; a < c && cmp(data[a], data[pivot]) == .Less; a += 1 {
|
||||
}
|
||||
b := a
|
||||
|
||||
for {
|
||||
for ; b < c && cmp(data[pivot], data[b]) >= .Equal; b += 1 { // data[b] <= pivot
|
||||
}
|
||||
for ; b < c && cmp(data[pivot], data[c-1]) == .Less; c -=1 { // data[c-1] > pivot
|
||||
}
|
||||
if b >= c {
|
||||
break
|
||||
}
|
||||
|
||||
swap(data, b, c-1)
|
||||
b += 1
|
||||
c -= 1
|
||||
}
|
||||
|
||||
protect := hi-c < 5
|
||||
if !protect && hi-c < (hi-lo)/4 {
|
||||
dups := 0
|
||||
if cmp(data[pivot], data[hi-1]) != .Less {
|
||||
swap(data, c, hi-1)
|
||||
c += 1
|
||||
dups += 1
|
||||
}
|
||||
if cmp(data[b-1], data[pivot]) != .Less {
|
||||
b -= 1
|
||||
dups += 1
|
||||
}
|
||||
|
||||
if cmp(data[m], data[pivot]) != .Less {
|
||||
swap(data, m, b-1)
|
||||
b -= 1
|
||||
dups += 1
|
||||
}
|
||||
protect = dups > 1
|
||||
}
|
||||
if protect {
|
||||
for {
|
||||
for ; a < b && cmp(data[b-1], data[pivot]) >= .Equal; b -= 1 {
|
||||
}
|
||||
for ; a < b && cmp(data[a], data[pivot]) == .Less; a += 1 {
|
||||
}
|
||||
if a >= b {
|
||||
break
|
||||
}
|
||||
swap(data, a, b-1)
|
||||
a += 1
|
||||
b -= 1
|
||||
}
|
||||
}
|
||||
swap(data, pivot, b-1)
|
||||
return b-1, c
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
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
|
||||
} else {
|
||||
_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)
|
||||
}
|
||||
}
|
||||
_insertion_sort_cmp(data, a, b, cmp)
|
||||
}
|
||||
}
|
||||
|
||||
@(private)
|
||||
_insertion_sort_cmp :: proc(data: $T/[]$E, a, b: int, cmp: proc(i, j: E) -> Ordering) #no_bounds_check {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@(private)
|
||||
_heap_sort_cmp :: proc(data: $T/[]$E, a, b: int, cmp: proc(i, j: E) -> Ordering) #no_bounds_check {
|
||||
sift_down :: proc(data: T, lo, hi, first: int, cmp: proc(i, j: E) -> Ordering) #no_bounds_check {
|
||||
root := lo
|
||||
for {
|
||||
child := 2*root + 1
|
||||
if child >= hi {
|
||||
break
|
||||
}
|
||||
if child+1 < hi && cmp(data[first+child], data[first+child+1]) == .Less {
|
||||
child += 1
|
||||
}
|
||||
if cmp(data[first+root], data[first+child]) >= .Equal {
|
||||
return
|
||||
}
|
||||
swap(data, first+root, first+child)
|
||||
root = child
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
first, lo, hi := a, 0, b-a
|
||||
|
||||
for i := (hi-1)/2; i >= 0; i -= 1 {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
//+private
|
||||
package slice
|
||||
|
||||
import "core:intrinsics"
|
||||
_ :: intrinsics
|
||||
|
||||
ORD :: intrinsics.type_is_ordered
|
||||
|
||||
Sort_Kind :: enum {
|
||||
Ordered,
|
||||
Less,
|
||||
Cmp,
|
||||
}
|
||||
|
||||
_quick_sort_general :: proc(data: $T/[]$E, a, b, max_depth: int, call: $P, $KIND: Sort_Kind) where (ORD(E) && KIND == .Ordered) || (KIND != .Ordered) #no_bounds_check {
|
||||
less :: #force_inline proc(a, b: E, call: P) -> bool {
|
||||
when KIND == .Ordered {
|
||||
return a < b
|
||||
} else when KIND == .Less {
|
||||
return call(a, b)
|
||||
} else when KIND == .Cmp {
|
||||
return call(a, b) == .Less
|
||||
} else {
|
||||
#panic("unhandled Sort_Kind")
|
||||
}
|
||||
}
|
||||
|
||||
insertion_sort :: proc(data: $T/[]$E, a, b: int, call: P) #no_bounds_check {
|
||||
for i in a+1..<b {
|
||||
for j := i; j > a && less(data[j], data[j-1], call); j -= 1 {
|
||||
swap(data, j, j-1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
heap_sort :: proc(data: $T/[]$E, a, b: int, call: P) #no_bounds_check {
|
||||
sift_down :: proc(data: T, lo, hi, first: int, call: P) #no_bounds_check {
|
||||
root := lo
|
||||
for {
|
||||
child := 2*root + 1
|
||||
if child >= hi {
|
||||
break
|
||||
}
|
||||
if child+1 < hi && less(data[first+child], data[first+child+1], call) {
|
||||
child += 1
|
||||
}
|
||||
if !less(data[first+root], data[first+child], call) {
|
||||
return
|
||||
}
|
||||
swap(data, first+root, first+child)
|
||||
root = child
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
first, lo, hi := a, 0, b-a
|
||||
|
||||
for i := (hi-1)/2; i >= 0; i -= 1 {
|
||||
sift_down(data, i, hi, first, call)
|
||||
}
|
||||
|
||||
for i := hi-1; i >= 0; i -= 1 {
|
||||
swap(data, first, first+i)
|
||||
sift_down(data, lo, i, first, call)
|
||||
}
|
||||
}
|
||||
|
||||
median3 :: proc(data: T, m1, m0, m2: int, call: P) #no_bounds_check {
|
||||
if less(data[m1], data[m0], call) {
|
||||
swap(data, m1, m0)
|
||||
}
|
||||
if less(data[m2], data[m1], call) {
|
||||
swap(data, m2, m1)
|
||||
if less(data[m1], data[m0], call) {
|
||||
swap(data, m1, m0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
do_pivot :: proc(data: T, lo, hi: int, call: P) -> (midlo, midhi: int) #no_bounds_check {
|
||||
m := int(uint(lo+hi)>>1)
|
||||
if hi-lo > 40 {
|
||||
s := (hi-lo)/8
|
||||
median3(data, lo, lo+s, lo+s*2, call)
|
||||
median3(data, m, m-s, m+s, call)
|
||||
median3(data, hi-1, hi-1-s, hi-1-s*2, call)
|
||||
}
|
||||
median3(data, lo, m, hi-1, call)
|
||||
|
||||
pivot := lo
|
||||
a, c := lo+1, hi-1
|
||||
|
||||
|
||||
for ; a < c && less(data[a], data[pivot], call); a += 1 {
|
||||
}
|
||||
b := a
|
||||
|
||||
for {
|
||||
for ; b < c && !less(data[pivot], data[b], call); b += 1 { // data[b] <= pivot
|
||||
}
|
||||
for ; b < c && less(data[pivot], data[c-1], call); c -=1 { // data[c-1] > pivot
|
||||
}
|
||||
if b >= c {
|
||||
break
|
||||
}
|
||||
|
||||
swap(data, b, c-1)
|
||||
b += 1
|
||||
c -= 1
|
||||
}
|
||||
|
||||
protect := hi-c < 5
|
||||
if !protect && hi-c < (hi-lo)/4 {
|
||||
dups := 0
|
||||
if !less(data[pivot], data[hi-1], call) {
|
||||
swap(data, c, hi-1)
|
||||
c += 1
|
||||
dups += 1
|
||||
}
|
||||
if !less(data[b-1], data[pivot], call) {
|
||||
b -= 1
|
||||
dups += 1
|
||||
}
|
||||
|
||||
if !less(data[m], data[pivot], call) {
|
||||
swap(data, m, b-1)
|
||||
b -= 1
|
||||
dups += 1
|
||||
}
|
||||
protect = dups > 1
|
||||
}
|
||||
if protect {
|
||||
for {
|
||||
for ; a < b && !less(data[b-1], data[pivot], call); b -= 1 {
|
||||
}
|
||||
for ; a < b && less(data[a], data[pivot], call); a += 1 {
|
||||
}
|
||||
if a >= b {
|
||||
break
|
||||
}
|
||||
swap(data, a, b-1)
|
||||
a += 1
|
||||
b -= 1
|
||||
}
|
||||
}
|
||||
swap(data, pivot, b-1)
|
||||
return b-1, c
|
||||
}
|
||||
|
||||
|
||||
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, call)
|
||||
return
|
||||
}
|
||||
max_depth -= 1
|
||||
mlo, mhi := do_pivot(data, a, b, call)
|
||||
if mlo-a < b-mhi {
|
||||
_quick_sort_general(data, a, mlo, max_depth, call, KIND)
|
||||
a = mhi
|
||||
} else {
|
||||
_quick_sort_general(data, mhi, b, max_depth, call, KIND)
|
||||
b = mlo
|
||||
}
|
||||
}
|
||||
if b-a > 1 {
|
||||
// Shell short with gap 6
|
||||
for i in a+6..<b {
|
||||
if less(data[i], data[i-6], call) {
|
||||
swap(data, i, i-6)
|
||||
}
|
||||
}
|
||||
insertion_sort(data, a, b, call)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// merge sort
|
||||
_stable_sort_general :: proc(data: $T/[]$E, call: $P, $KIND: Sort_Kind) where (ORD(E) && KIND == .Ordered) || (KIND != .Ordered) #no_bounds_check {
|
||||
less :: #force_inline proc(a, b: E, call: P) -> bool {
|
||||
when KIND == .Ordered {
|
||||
return a < b
|
||||
} else when KIND == .Less {
|
||||
return call(a, b)
|
||||
} else when KIND == .Cmp {
|
||||
return call(a, b) == .Less
|
||||
} else {
|
||||
#panic("unhandled Sort_Kind")
|
||||
}
|
||||
}
|
||||
|
||||
n := len(data)
|
||||
for i in 1..<n {
|
||||
for j := i; j > 0 && less(data[j], data[j-1], call); j -= 1 {
|
||||
swap(data, j, j-1)
|
||||
}
|
||||
}
|
||||
}
|
||||
+68
-33
@@ -298,13 +298,7 @@ split_after_n :: proc(s, sep: string, n: int, allocator := context.allocator) ->
|
||||
|
||||
|
||||
@private
|
||||
_split_iterator :: proc(s: ^string, sep: string, sep_save, n: int) -> (res: string, ok: bool) {
|
||||
s, n := s, n
|
||||
|
||||
if n == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
_split_iterator :: proc(s: ^string, sep: string, sep_save: int) -> (res: string, ok: bool) {
|
||||
if sep == "" {
|
||||
res = s[:]
|
||||
ok = true
|
||||
@@ -312,47 +306,88 @@ _split_iterator :: proc(s: ^string, sep: string, sep_save, n: int) -> (res: stri
|
||||
return
|
||||
}
|
||||
|
||||
if n < 0 {
|
||||
n = count(s^, sep) + 1
|
||||
}
|
||||
|
||||
n -= 1
|
||||
|
||||
i := 0
|
||||
for ; i < n; i += 1 {
|
||||
m := index(s^, sep)
|
||||
if m < 0 {
|
||||
break
|
||||
}
|
||||
m := index(s^, sep)
|
||||
if m < 0 {
|
||||
// not found
|
||||
res = s[:]
|
||||
ok = res != ""
|
||||
s^ = s[len(s):]
|
||||
} else {
|
||||
res = s[:m+sep_save]
|
||||
ok = true
|
||||
s^ = s[m+len(sep):]
|
||||
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)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
split_after_iterator :: proc(s: ^string, sep: string) -> (string, bool) {
|
||||
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))
|
||||
}
|
||||
|
||||
|
||||
@(private)
|
||||
_trim_cr :: proc(s: string) -> string {
|
||||
n := len(s)
|
||||
if n > 0 {
|
||||
if s[n-1] == '\r' {
|
||||
return s[:n-1]
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
split_lines :: proc(s: string, allocator := context.allocator) -> []string {
|
||||
sep :: "\n"
|
||||
lines := _split(s, sep, 0, -1, allocator)
|
||||
for line in &lines {
|
||||
line = _trim_cr(line)
|
||||
}
|
||||
return lines
|
||||
}
|
||||
|
||||
split_lines_n :: proc(s: string, n: int, allocator := context.allocator) -> []string {
|
||||
sep :: "\n"
|
||||
lines := _split(s, sep, 0, n, allocator)
|
||||
for line in &lines {
|
||||
line = _trim_cr(line)
|
||||
}
|
||||
return lines
|
||||
}
|
||||
|
||||
split_lines_after :: proc(s: string, allocator := context.allocator) -> []string {
|
||||
sep :: "\n"
|
||||
lines := _split(s, sep, len(sep), -1, allocator)
|
||||
for line in &lines {
|
||||
line = _trim_cr(line)
|
||||
}
|
||||
return lines
|
||||
}
|
||||
|
||||
split_lines_after_n :: proc(s: string, n: int, allocator := context.allocator) -> []string {
|
||||
sep :: "\n"
|
||||
lines := _split(s, sep, len(sep), n, allocator)
|
||||
for line in &lines {
|
||||
line = _trim_cr(line)
|
||||
}
|
||||
return lines
|
||||
}
|
||||
|
||||
split_lines_iterator :: proc(s: ^string) -> (line: string, ok: bool) {
|
||||
sep :: "\n"
|
||||
line = _split_iterator(s, sep, 0) or_return
|
||||
return _trim_cr(line), true
|
||||
}
|
||||
|
||||
split_lines_after_iterator :: proc(s: ^string) -> (line: string, ok: bool) {
|
||||
sep :: "\n"
|
||||
line = _split_iterator(s, sep, len(sep)) or_return
|
||||
return _trim_cr(line), true
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import "core:time"
|
||||
|
||||
run_internal_test :: proc(t: ^T, it: Internal_Test) {
|
||||
// TODO(bill): Catch panics on other platforms
|
||||
it.p(t);
|
||||
it.p(t)
|
||||
}
|
||||
|
||||
_fail_timeout :: proc(t: ^T, duration: time.Duration, loc := #caller_location) {
|
||||
|
||||
@@ -167,8 +167,6 @@ _join_multiple :: proc(threads: ..^Thread) {
|
||||
|
||||
_destroy :: proc(t: ^Thread) {
|
||||
_join(t)
|
||||
sync.condition_destroy(&t.start_gate)
|
||||
sync.mutex_destroy(&t.start_mutex)
|
||||
t.unix_thread = {}
|
||||
free(t, t.creation_allocator)
|
||||
}
|
||||
|
||||
@@ -5,25 +5,65 @@ package all
|
||||
|
||||
import bufio "core:bufio"
|
||||
import bytes "core:bytes"
|
||||
|
||||
import c "core:c"
|
||||
import libc "core:c/libc"
|
||||
|
||||
import compress "core:compress"
|
||||
import gzip "core:compress/gzip"
|
||||
import zlib "core:compress/zlib"
|
||||
import container "core:container"
|
||||
|
||||
import bit_array "core:container/bit_array"
|
||||
import priority_queue "core:container/priority_queue"
|
||||
import queue "core:container/queue"
|
||||
import small_array "core:container/small_array"
|
||||
import lru "core:container/lru"
|
||||
|
||||
import crypto "core:crypto"
|
||||
import blake "core:crypto/blake"
|
||||
import blake2b "core:crypto/blake2b"
|
||||
import blake2s "core:crypto/blake2s"
|
||||
import chacha20 "core:crypto/chacha20"
|
||||
import chacha20poly1305 "core:crypto/chacha20poly1305"
|
||||
import gost "core:crypto/gost"
|
||||
import groestl "core:crypto/groestl"
|
||||
import haval "core:crypto/haval"
|
||||
import jh "core:crypto/jh"
|
||||
import keccak "core:crypto/keccak"
|
||||
import md2 "core:crypto/md2"
|
||||
import md4 "core:crypto/md4"
|
||||
import md5 "core:crypto/md5"
|
||||
import poly1305 "core:crypto/poly1305"
|
||||
import ripemd "core:crypto/ripemd"
|
||||
import sha1 "core:crypto/sha1"
|
||||
import sha2 "core:crypto/sha2"
|
||||
import sha3 "core:crypto/sha3"
|
||||
import shake "core:crypto/shake"
|
||||
import sm3 "core:crypto/sm3"
|
||||
import streebog "core:crypto/streebog"
|
||||
import tiger "core:crypto/tiger"
|
||||
import tiger2 "core:crypto/tiger2"
|
||||
import crypto_util "core:crypto/util"
|
||||
import whirlpool "core:crypto/whirlpool"
|
||||
import x25519 "core:crypto/x25519"
|
||||
|
||||
import dynlib "core:dynlib"
|
||||
import encoding "core:encoding"
|
||||
|
||||
import base32 "core:encoding/base32"
|
||||
import base64 "core:encoding/base64"
|
||||
import csv "core:encoding/csv"
|
||||
import hxa "core:encoding/hxa"
|
||||
import json "core:encoding/json"
|
||||
|
||||
import fmt "core:fmt"
|
||||
import hash "core:hash"
|
||||
|
||||
import image "core:image"
|
||||
import png "core:image/png"
|
||||
|
||||
import io "core:io"
|
||||
import log "core:log"
|
||||
|
||||
import math "core:math"
|
||||
import big "core:math/big"
|
||||
import bits "core:math/bits"
|
||||
@@ -32,16 +72,22 @@ import linalg "core:math/linalg"
|
||||
import glm "core:math/linalg/glsl"
|
||||
import hlm "core:math/linalg/hlsl"
|
||||
import rand "core:math/rand"
|
||||
|
||||
import mem "core:mem"
|
||||
// import virtual "core:mem/virtual"
|
||||
|
||||
import ast "core:odin/ast"
|
||||
import doc_format "core:odin/doc-format"
|
||||
import odin_format "core:odin/format"
|
||||
import odin_parser "core:odin/parser"
|
||||
import odin_printer "core:odin/printer"
|
||||
import odin_tokenizer "core:odin/tokenizer"
|
||||
|
||||
import os "core:os"
|
||||
|
||||
import slashpath "core:path/slashpath"
|
||||
import filepath "core:path/filepath"
|
||||
|
||||
import reflect "core:reflect"
|
||||
import runtime "core:runtime"
|
||||
import slice "core:slice"
|
||||
@@ -50,9 +96,11 @@ import strconv "core:strconv"
|
||||
import strings "core:strings"
|
||||
import sync "core:sync"
|
||||
import sync2 "core:sync/sync2"
|
||||
import testing "core:testing"
|
||||
import scanner "core:text/scanner"
|
||||
import thread "core:thread"
|
||||
import time "core:time"
|
||||
|
||||
import unicode "core:unicode"
|
||||
import utf8 "core:unicode/utf8"
|
||||
import utf16 "core:unicode/utf16"
|
||||
@@ -67,9 +115,38 @@ _ :: libc
|
||||
_ :: compress
|
||||
_ :: gzip
|
||||
_ :: zlib
|
||||
_ :: container
|
||||
_ :: bit_array
|
||||
_ :: priority_queue
|
||||
_ :: queue
|
||||
_ :: small_array
|
||||
_ :: crypto
|
||||
_ :: blake
|
||||
_ :: blake2b
|
||||
_ :: blake2s
|
||||
_ :: chacha20
|
||||
_ :: chacha20poly1305
|
||||
_ :: gost
|
||||
_ :: groestl
|
||||
_ :: haval
|
||||
_ :: jh
|
||||
_ :: keccak
|
||||
_ :: md2
|
||||
_ :: md4
|
||||
_ :: md5
|
||||
_ :: poly1305
|
||||
_ :: ripemd
|
||||
_ :: sha1
|
||||
_ :: sha2
|
||||
_ :: sha3
|
||||
_ :: shake
|
||||
_ :: sm3
|
||||
_ :: streebog
|
||||
_ :: tiger
|
||||
_ :: tiger2
|
||||
_ :: crypto_util
|
||||
_ :: whirlpool
|
||||
_ :: x25519
|
||||
_ :: dynlib
|
||||
_ :: encoding
|
||||
_ :: base32
|
||||
_ :: base64
|
||||
_ :: csv
|
||||
@@ -107,6 +184,7 @@ _ :: strconv
|
||||
_ :: strings
|
||||
_ :: sync
|
||||
_ :: sync2
|
||||
_ :: testing
|
||||
_ :: scanner
|
||||
_ :: thread
|
||||
_ :: time
|
||||
|
||||
@@ -1,26 +1,47 @@
|
||||
//+build windows
|
||||
package all
|
||||
|
||||
import glfw "vendor:glfw"
|
||||
import gl "vendor:OpenGL"
|
||||
import rl "vendor:raylib"
|
||||
import PM "vendor:portmidi"
|
||||
|
||||
import botan "vendor:botan"
|
||||
import ENet "vendor:ENet"
|
||||
import gl "vendor:OpenGL"
|
||||
import glfw "vendor:glfw"
|
||||
import microui "vendor:microui"
|
||||
import miniaudio "vendor:miniaudio"
|
||||
import PM "vendor:portmidi"
|
||||
import rl "vendor:raylib"
|
||||
|
||||
import SDL "vendor:sdl2"
|
||||
import IMG "vendor:sdl2/image"
|
||||
import SDLNet "vendor:sdl2/net"
|
||||
import IMG "vendor:sdl2/image"
|
||||
import MIX "vendor:sdl2/mixer"
|
||||
import TTF "vendor:sdl2/ttf"
|
||||
import vk "vendor:vulkan"
|
||||
import ENet "vendor:ENet"
|
||||
|
||||
_ :: glfw
|
||||
import stb_easy_font "vendor:stb/easy_font"
|
||||
import stbi "vendor:stb/image"
|
||||
import stbrp "vendor:stb/rect_pack"
|
||||
import stbtt "vendor:stb/truetype"
|
||||
import stb_vorbis "vendor:stb/vorbis"
|
||||
|
||||
import vk "vendor:vulkan"
|
||||
|
||||
|
||||
_ :: botan
|
||||
_ :: ENet
|
||||
_ :: gl
|
||||
_ :: rl
|
||||
_ :: glfw
|
||||
_ :: microui
|
||||
_ :: miniaudio
|
||||
_ :: PM
|
||||
_ :: rl
|
||||
_ :: SDL
|
||||
_ :: IMG
|
||||
_ :: SDLNet
|
||||
_ :: IMG
|
||||
_ :: MIX
|
||||
_ :: TTF
|
||||
_ :: vk
|
||||
_ :: ENet
|
||||
_ :: stb_easy_font
|
||||
_ :: stbi
|
||||
_ :: stbrp
|
||||
_ :: stbtt
|
||||
_ :: stb_vorbis
|
||||
_ :: vk
|
||||
@@ -1921,14 +1921,14 @@ constant_literal_expressions :: proc() {
|
||||
|
||||
fmt.println("-------")
|
||||
|
||||
Partial_Baz :: enum{A=5, B, C, D=16}
|
||||
#assert(len(Partial_Baz) < len(#partial [Partial_Baz]int))
|
||||
PARTIAL_ENUM_ARRAY_CONST :: #partial [Partial_Baz]int{.A ..= .C = 1, .D = 16}
|
||||
Sparse_Baz :: enum{A=5, B, C, D=16}
|
||||
#assert(len(Sparse_Baz) < len(#sparse[Sparse_Baz]int))
|
||||
SPARSE_ENUM_ARRAY_CONST :: #sparse[Sparse_Baz]int{.A ..= .C = 1, .D = 16}
|
||||
|
||||
fmt.println(PARTIAL_ENUM_ARRAY_CONST[.A])
|
||||
fmt.println(PARTIAL_ENUM_ARRAY_CONST[.B])
|
||||
fmt.println(PARTIAL_ENUM_ARRAY_CONST[.C])
|
||||
fmt.println(PARTIAL_ENUM_ARRAY_CONST[.D])
|
||||
fmt.println(SPARSE_ENUM_ARRAY_CONST[.A])
|
||||
fmt.println(SPARSE_ENUM_ARRAY_CONST[.B])
|
||||
fmt.println(SPARSE_ENUM_ARRAY_CONST[.C])
|
||||
fmt.println(SPARSE_ENUM_ARRAY_CONST[.D])
|
||||
|
||||
fmt.println("-------")
|
||||
|
||||
|
||||
+52
-1
@@ -165,6 +165,13 @@ enum TimingsExportFormat : i32 {
|
||||
TimingsExportCSV = 2,
|
||||
};
|
||||
|
||||
enum ErrorPosStyle {
|
||||
ErrorPosStyle_Default, // path(line:column) msg
|
||||
ErrorPosStyle_Unix, // path:line:column: msg
|
||||
|
||||
ErrorPosStyle_COUNT
|
||||
};
|
||||
|
||||
// This stores the information for the specify architecture of this build
|
||||
struct BuildContext {
|
||||
// Constants
|
||||
@@ -175,7 +182,9 @@ struct BuildContext {
|
||||
String ODIN_ROOT; // Odin ROOT
|
||||
bool ODIN_DEBUG; // Odin in debug mode
|
||||
bool ODIN_DISABLE_ASSERT; // Whether the default 'assert' et al is disabled in code or not
|
||||
bool ODIN_DEFAULT_TO_NIL_ALLOCATOR; // Whether the default allocator is a "nil" allocator or not (i.e. it does nothing)
|
||||
bool ODIN_DEFAULT_TO_NIL_ALLOCATOR; // Whether the default allocator is a "nil" allocator or not (i.e. it does nothing)
|
||||
|
||||
ErrorPosStyle ODIN_ERROR_POS_STYLE;
|
||||
|
||||
TargetEndianKind endian_kind;
|
||||
|
||||
@@ -254,6 +263,7 @@ bool ODIN_DEFAULT_TO_NIL_ALLOCATOR; // Whether the default allocator is a "nil
|
||||
isize thread_count;
|
||||
|
||||
PtrMap<char const *, ExactValue> defined_values;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -843,6 +853,22 @@ bool has_asm_extension(String const &path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// temporary
|
||||
char *token_pos_to_string(TokenPos const &pos) {
|
||||
gbString s = gb_string_make_reserve(temporary_allocator(), 128);
|
||||
String file = get_file_path_string(pos.file_id);
|
||||
switch (build_context.ODIN_ERROR_POS_STYLE) {
|
||||
default: /*fallthrough*/
|
||||
case ErrorPosStyle_Default:
|
||||
s = gb_string_append_fmt(s, "%.*s(%d:%d)", LIT(file), pos.line, pos.column);
|
||||
break;
|
||||
case ErrorPosStyle_Unix:
|
||||
s = gb_string_append_fmt(s, "%.*s:%d:%d:", LIT(file), pos.line, pos.column);
|
||||
break;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
void init_build_context(TargetMetrics *cross_target) {
|
||||
BuildContext *bc = &build_context;
|
||||
@@ -855,6 +881,31 @@ void init_build_context(TargetMetrics *cross_target) {
|
||||
bc->ODIN_VENDOR = str_lit("odin");
|
||||
bc->ODIN_VERSION = ODIN_VERSION;
|
||||
bc->ODIN_ROOT = odin_root_dir();
|
||||
|
||||
{
|
||||
char const *found = gb_get_env("ODIN_ERROR_POS_STYLE", permanent_allocator());
|
||||
if (found) {
|
||||
ErrorPosStyle kind = ErrorPosStyle_Default;
|
||||
String style = make_string_c(found);
|
||||
style = string_trim_whitespace(style);
|
||||
if (style == "" || style == "default" || style == "odin") {
|
||||
kind = ErrorPosStyle_Default;
|
||||
} else if (style == "unix" || style == "gcc" || style == "clang" || style == "llvm") {
|
||||
kind = ErrorPosStyle_Unix;
|
||||
} else {
|
||||
gb_printf_err("Invalid ODIN_ERROR_POS_STYLE: got %.*s\n", LIT(style));
|
||||
gb_printf_err("Valid formats:\n");
|
||||
gb_printf_err("\t\"default\" or \"odin\"\n");
|
||||
gb_printf_err("\t\tpath(line:column) message\n");
|
||||
gb_printf_err("\t\"unix\"\n");
|
||||
gb_printf_err("\t\tpath:line:column: message\n");
|
||||
gb_exit(1);
|
||||
}
|
||||
|
||||
build_context.ODIN_ERROR_POS_STYLE = kind;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bc->copy_file_contents = true;
|
||||
|
||||
|
||||
+39
-4
@@ -2183,9 +2183,43 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
||||
}
|
||||
|
||||
operand->mode = Addressing_Value;
|
||||
if (is_type_array(t)) {
|
||||
if (t->kind == Type_Array) {
|
||||
i32 rank = type_math_rank(t);
|
||||
// Do nothing
|
||||
operand->type = x.type;
|
||||
operand->type = x.type;
|
||||
if (rank > 2) {
|
||||
gbString s = type_to_string(x.type);
|
||||
error(call, "'%.*s' expects a matrix or array with a rank of 2, got %s of rank %d", LIT(builtin_name), s, rank);
|
||||
gb_string_free(s);
|
||||
return false;
|
||||
} else if (rank == 2) {
|
||||
Type *inner = base_type(t->Array.elem);
|
||||
GB_ASSERT(inner->kind == Type_Array);
|
||||
Type *elem = inner->Array.elem;
|
||||
Type *array_inner = alloc_type_array(elem, t->Array.count);
|
||||
Type *array_outer = alloc_type_array(array_inner, inner->Array.count);
|
||||
operand->type = array_outer;
|
||||
|
||||
i64 elements = t->Array.count*inner->Array.count;
|
||||
i64 size = type_size_of(operand->type);
|
||||
if (!is_type_valid_for_matrix_elems(elem)) {
|
||||
gbString s = type_to_string(x.type);
|
||||
error(call, "'%.*s' expects a matrix or array with a base element type of an integer, float, or complex number, got %s", LIT(builtin_name), s);
|
||||
gb_string_free(s);
|
||||
} else if (elements > MATRIX_ELEMENT_COUNT_MAX) {
|
||||
gbString s = type_to_string(x.type);
|
||||
error(call, "'%.*s' expects a matrix or array with a maximum of %d elements, got %s with %lld elements", LIT(builtin_name), MATRIX_ELEMENT_COUNT_MAX, s, elements);
|
||||
gb_string_free(s);
|
||||
} else if (elements > MATRIX_ELEMENT_COUNT_MAX) {
|
||||
gbString s = type_to_string(x.type);
|
||||
error(call, "'%.*s' expects a matrix or array with non-zero elements, got %s", LIT(builtin_name), MATRIX_ELEMENT_COUNT_MAX, s);
|
||||
gb_string_free(s);
|
||||
} else if (size > MATRIX_ELEMENT_MAX_SIZE) {
|
||||
gbString s = type_to_string(x.type);
|
||||
error(call, "Too large of a type for '%.*s', got %s of size %lld, maximum size %d", LIT(builtin_name), s, cast(long long)size, MATRIX_ELEMENT_MAX_SIZE);
|
||||
gb_string_free(s);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
GB_ASSERT(t->kind == Type_Matrix);
|
||||
operand->type = alloc_type_matrix(t->Matrix.elem, t->Matrix.column_count, t->Matrix.row_count);
|
||||
@@ -3310,9 +3344,11 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
||||
case BuiltinProc_type_is_simple_compare:
|
||||
case BuiltinProc_type_is_dereferenceable:
|
||||
case BuiltinProc_type_is_valid_map_key:
|
||||
case BuiltinProc_type_is_valid_matrix_elements:
|
||||
case BuiltinProc_type_is_named:
|
||||
case BuiltinProc_type_is_pointer:
|
||||
case BuiltinProc_type_is_array:
|
||||
case BuiltinProc_type_is_enumerated_array:
|
||||
case BuiltinProc_type_is_slice:
|
||||
case BuiltinProc_type_is_dynamic_array:
|
||||
case BuiltinProc_type_is_map:
|
||||
@@ -3320,10 +3356,9 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
||||
case BuiltinProc_type_is_union:
|
||||
case BuiltinProc_type_is_enum:
|
||||
case BuiltinProc_type_is_proc:
|
||||
case BuiltinProc_type_is_bit_field:
|
||||
case BuiltinProc_type_is_bit_field_value:
|
||||
case BuiltinProc_type_is_bit_set:
|
||||
case BuiltinProc_type_is_simd_vector:
|
||||
case BuiltinProc_type_is_matrix:
|
||||
case BuiltinProc_type_is_specialized_polymorphic_record:
|
||||
case BuiltinProc_type_is_unspecialized_polymorphic_record:
|
||||
case BuiltinProc_type_has_nil:
|
||||
|
||||
+89
-2
@@ -238,6 +238,51 @@ isize total_attribute_count(DeclInfo *decl) {
|
||||
return attribute_count;
|
||||
}
|
||||
|
||||
Type *clone_enum_type(CheckerContext *ctx, Type *original_enum_type, Type *named_type) {
|
||||
// NOTE(bill, 2022-02-05): Stupid edge case for `distinct` declarations
|
||||
//
|
||||
// X :: enum {A, B, C}
|
||||
// Y :: distinct X
|
||||
//
|
||||
// To make Y be just like X, it will need to copy the elements of X and change their type
|
||||
// so that they match Y rather than X.
|
||||
GB_ASSERT(original_enum_type != nullptr);
|
||||
GB_ASSERT(named_type != nullptr);
|
||||
GB_ASSERT(original_enum_type->kind == Type_Enum);
|
||||
GB_ASSERT(named_type->kind == Type_Named);
|
||||
|
||||
Scope *parent = original_enum_type->Enum.scope->parent;
|
||||
Scope *scope = create_scope(nullptr, parent);
|
||||
|
||||
|
||||
Type *et = alloc_type_enum();
|
||||
et->Enum.base_type = original_enum_type->Enum.base_type;
|
||||
et->Enum.min_value = original_enum_type->Enum.min_value;
|
||||
et->Enum.max_value = original_enum_type->Enum.max_value;
|
||||
et->Enum.min_value_index = original_enum_type->Enum.min_value_index;
|
||||
et->Enum.max_value_index = original_enum_type->Enum.max_value_index;
|
||||
et->Enum.scope = scope;
|
||||
|
||||
auto fields = array_make<Entity *>(permanent_allocator(), original_enum_type->Enum.fields.count);
|
||||
for_array(i, fields) {
|
||||
Entity *old = original_enum_type->Enum.fields[i];
|
||||
|
||||
Entity *e = alloc_entity_constant(scope, old->token, named_type, old->Constant.value);
|
||||
e->file = old->file;
|
||||
e->identifier = clone_ast(old->identifier);
|
||||
e->flags |= EntityFlag_Visited;
|
||||
e->state = EntityState_Resolved;
|
||||
e->Constant.flags = old->Constant.flags;
|
||||
e->Constant.docs = old->Constant.docs;
|
||||
e->Constant.comment = old->Constant.comment;
|
||||
|
||||
fields[i] = e;
|
||||
add_entity(ctx, scope, nullptr, e);
|
||||
add_entity_use(ctx, e->identifier, e);
|
||||
}
|
||||
et->Enum.fields = fields;
|
||||
return et;
|
||||
}
|
||||
|
||||
void check_type_decl(CheckerContext *ctx, Entity *e, Ast *init_expr, Type *def) {
|
||||
GB_ASSERT(e->type == nullptr);
|
||||
@@ -258,7 +303,11 @@ void check_type_decl(CheckerContext *ctx, Entity *e, Ast *init_expr, Type *def)
|
||||
Type *bt = check_type_expr(ctx, te, named);
|
||||
check_type_path_pop(ctx);
|
||||
|
||||
named->Named.base = base_type(bt);
|
||||
Type *base = base_type(bt);
|
||||
if (is_distinct && bt->kind == Type_Named && base->kind == Type_Enum) {
|
||||
base = clone_enum_type(ctx, base, named);
|
||||
}
|
||||
named->Named.base = base;
|
||||
|
||||
if (is_distinct && is_type_typeid(e->type)) {
|
||||
error(init_expr, "'distinct' cannot be applied to 'typeid'");
|
||||
@@ -385,7 +434,45 @@ void check_const_decl(CheckerContext *ctx, Entity *e, Ast *type_expr, Ast *init,
|
||||
Operand operand = {};
|
||||
|
||||
if (init != nullptr) {
|
||||
Entity *entity = nullptr;
|
||||
Entity *entity = check_entity_from_ident_or_selector(ctx, init, false);
|
||||
if (entity != nullptr && entity->kind == Entity_TypeName) {
|
||||
// @TypeAliasingProblem
|
||||
// NOTE(bill, 2022-02-03): This is used to solve the problem caused by type aliases
|
||||
// being "confused" as constants
|
||||
//
|
||||
// A :: B
|
||||
// C :: proc "c" (^A)
|
||||
// B :: struct {x: C}
|
||||
//
|
||||
// A gets evaluated first, and then checks B.
|
||||
// B then checks C.
|
||||
// C then tries to check A which is unresolved but thought to be a constant.
|
||||
// Therefore within C's check, A errs as "not a type".
|
||||
//
|
||||
// This is because a const declaration may or may not be a type and this cannot
|
||||
// be determined from a syntactical standpoint.
|
||||
// This check allows the compiler to override the entity to be checked as a type.
|
||||
//
|
||||
// There is no problem if B is prefixed with the `#type` helper enforcing at
|
||||
// both a syntax and semantic level that B must be a type.
|
||||
//
|
||||
// A :: #type B
|
||||
//
|
||||
// This approach is not fool proof and can fail in case such as:
|
||||
//
|
||||
// X :: type_of(x)
|
||||
// X :: Foo(int).Type
|
||||
//
|
||||
// Since even these kind of declarations may cause weird checking cycles.
|
||||
// For the time being, these are going to be treated as an unfortunate error
|
||||
// until there is a proper delaying system to try declaration again if they
|
||||
// have failed.
|
||||
|
||||
e->kind = Entity_TypeName;
|
||||
check_type_decl(ctx, e, init, named_type);
|
||||
return;
|
||||
}
|
||||
entity = nullptr;
|
||||
if (init->kind == Ast_Ident) {
|
||||
entity = check_ident(ctx, &operand, init, nullptr, e->type, true);
|
||||
} else if (init->kind == Ast_SelectorExpr) {
|
||||
|
||||
+2083
-1716
File diff suppressed because it is too large
Load Diff
+15
-93
@@ -490,6 +490,14 @@ void check_stmt(CheckerContext *ctx, Ast *node, u32 flags) {
|
||||
out &= ~StateFlag_no_bounds_check;
|
||||
}
|
||||
|
||||
if (in & StateFlag_no_type_assert) {
|
||||
out |= StateFlag_no_type_assert;
|
||||
out &= ~StateFlag_type_assert;
|
||||
} else if (in & StateFlag_type_assert) {
|
||||
out |= StateFlag_type_assert;
|
||||
out &= ~StateFlag_no_type_assert;
|
||||
}
|
||||
|
||||
ctx->state_flags = out;
|
||||
}
|
||||
|
||||
@@ -689,54 +697,6 @@ bool check_using_stmt_entity(CheckerContext *ctx, AstUsingStmt *us, Ast *expr, b
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
struct TypeAndToken {
|
||||
Type *type;
|
||||
Token token;
|
||||
};
|
||||
|
||||
|
||||
void add_constant_switch_case(CheckerContext *ctx, PtrMap<uintptr, TypeAndToken> *seen, Operand operand, bool use_expr = true) {
|
||||
if (operand.mode != Addressing_Constant) {
|
||||
return;
|
||||
}
|
||||
if (operand.value.kind == ExactValue_Invalid) {
|
||||
return;
|
||||
}
|
||||
|
||||
uintptr key = hash_exact_value(operand.value);
|
||||
TypeAndToken *found = map_get(seen, key);
|
||||
if (found != nullptr) {
|
||||
isize count = multi_map_count(seen, key);
|
||||
TypeAndToken *taps = gb_alloc_array(temporary_allocator(), TypeAndToken, count);
|
||||
|
||||
multi_map_get_all(seen, key, taps);
|
||||
for (isize i = 0; i < count; i++) {
|
||||
TypeAndToken tap = taps[i];
|
||||
if (!are_types_identical(operand.type, tap.type)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
TokenPos pos = tap.token.pos;
|
||||
if (use_expr) {
|
||||
gbString expr_str = expr_to_string(operand.expr);
|
||||
error(operand.expr,
|
||||
"Duplicate case '%s'\n"
|
||||
"\tprevious case at %s",
|
||||
expr_str,
|
||||
token_pos_to_string(pos));
|
||||
gb_string_free(expr_str);
|
||||
} else {
|
||||
error(operand.expr, "Duplicate case found with previous case at %s", token_pos_to_string(pos));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
TypeAndToken tap = {operand.type, ast_token(operand.expr)};
|
||||
multi_map_insert(seen, key, tap);
|
||||
}
|
||||
|
||||
void check_inline_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) {
|
||||
ast_node(irs, UnrollRangeStmt, node);
|
||||
check_open_scope(ctx, node);
|
||||
@@ -961,7 +921,7 @@ void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) {
|
||||
}
|
||||
}
|
||||
|
||||
PtrMap<uintptr, TypeAndToken> seen = {}; // NOTE(bill): Multimap, Key: ExactValue
|
||||
SeenMap seen = {}; // NOTE(bill): Multimap, Key: ExactValue
|
||||
map_init(&seen, heap_allocator());
|
||||
defer (map_destroy(&seen));
|
||||
|
||||
@@ -1001,9 +961,9 @@ void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) {
|
||||
|
||||
TokenKind upper_op = Token_Invalid;
|
||||
switch (be->op.kind) {
|
||||
case Token_Ellipsis: upper_op = Token_GtEq; break;
|
||||
case Token_RangeFull: upper_op = Token_GtEq; break;
|
||||
case Token_RangeHalf: upper_op = Token_Gt; break;
|
||||
case Token_Ellipsis: upper_op = Token_LtEq; break;
|
||||
case Token_RangeFull: upper_op = Token_LtEq; break;
|
||||
case Token_RangeHalf: upper_op = Token_Lt; break;
|
||||
default: GB_PANIC("Invalid range operator"); break;
|
||||
}
|
||||
|
||||
@@ -1024,45 +984,7 @@ void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) {
|
||||
Operand b1 = rhs;
|
||||
check_comparison(ctx, &a1, &b1, Token_LtEq);
|
||||
|
||||
if (is_type_enum(x.type)) {
|
||||
// TODO(bill): Fix this logic so it's fast!!!
|
||||
|
||||
i64 v0 = exact_value_to_i64(lhs.value);
|
||||
i64 v1 = exact_value_to_i64(rhs.value);
|
||||
Operand v = {};
|
||||
v.mode = Addressing_Constant;
|
||||
v.type = x.type;
|
||||
v.expr = x.expr;
|
||||
|
||||
Type *bt = base_type(x.type);
|
||||
GB_ASSERT(bt->kind == Type_Enum);
|
||||
for (i64 vi = v0; vi <= v1; vi++) {
|
||||
if (upper_op != Token_GtEq && vi == v1) {
|
||||
break;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
for_array(j, bt->Enum.fields) {
|
||||
Entity *f = bt->Enum.fields[j];
|
||||
GB_ASSERT(f->kind == Entity_Constant);
|
||||
|
||||
i64 fv = exact_value_to_i64(f->Constant.value);
|
||||
if (fv == vi) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
v.value = exact_value_i64(vi);
|
||||
add_constant_switch_case(ctx, &seen, v);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
add_constant_switch_case(ctx, &seen, lhs);
|
||||
if (upper_op == Token_GtEq) {
|
||||
add_constant_switch_case(ctx, &seen, rhs);
|
||||
}
|
||||
}
|
||||
add_to_seen_map(ctx, &seen, upper_op, x, lhs, rhs);
|
||||
|
||||
if (is_type_string(x.type)) {
|
||||
// NOTE(bill): Force dependency for strings here
|
||||
@@ -1107,7 +1029,7 @@ void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) {
|
||||
continue;
|
||||
}
|
||||
update_untyped_expr_type(ctx, z.expr, x.type, !is_type_untyped(x.type));
|
||||
add_constant_switch_case(ctx, &seen, y);
|
||||
add_to_seen_map(ctx, &seen, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1143,7 +1065,7 @@ void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) {
|
||||
if (unhandled.count == 1) {
|
||||
error_no_newline(node, "Unhandled switch case: %.*s", LIT(unhandled[0]->token.string));
|
||||
} else {
|
||||
error_no_newline(node, "Unhandled switch cases: ");
|
||||
error(node, "Unhandled switch cases:");
|
||||
for_array(i, unhandled) {
|
||||
Entity *f = unhandled[i];
|
||||
error_line("\t%.*s\n", LIT(f->token.string));
|
||||
|
||||
+29
-17
@@ -120,6 +120,8 @@ void check_struct_fields(CheckerContext *ctx, Ast *node, Slice<Entity *> *fields
|
||||
ast_node(p, Field, param);
|
||||
Ast *type_expr = p->type;
|
||||
Type *type = nullptr;
|
||||
CommentGroup *docs = p->docs;
|
||||
CommentGroup *comment = p->comment;
|
||||
|
||||
if (type_expr != nullptr) {
|
||||
type = check_type_expr(ctx, type_expr, nullptr);
|
||||
@@ -156,6 +158,14 @@ void check_struct_fields(CheckerContext *ctx, Ast *node, Slice<Entity *> *fields
|
||||
Entity *field = alloc_entity_field(ctx->scope, name_token, type, is_using, field_src_index);
|
||||
add_entity(ctx, ctx->scope, name, field);
|
||||
field->Variable.field_group_index = field_group_index;
|
||||
|
||||
if (j == 0) {
|
||||
field->Variable.docs = docs;
|
||||
}
|
||||
if (j+1 == p->names.count) {
|
||||
field->Variable.comment = comment;
|
||||
}
|
||||
|
||||
array_add(&fields_array, field);
|
||||
String tag = p->tag.string;
|
||||
if (tag.len != 0 && !unquote_string(permanent_allocator(), &tag, 0, tag.text[0] == '`')) {
|
||||
@@ -722,20 +732,19 @@ void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *named_type, Ast
|
||||
Ast *ident = nullptr;
|
||||
Ast *init = nullptr;
|
||||
u32 entity_flags = 0;
|
||||
if (field->kind == Ast_FieldValue) {
|
||||
ast_node(fv, FieldValue, field);
|
||||
if (fv->field == nullptr || fv->field->kind != Ast_Ident) {
|
||||
error(field, "An enum field's name must be an identifier");
|
||||
continue;
|
||||
}
|
||||
ident = fv->field;
|
||||
init = fv->value;
|
||||
} else if (field->kind == Ast_Ident) {
|
||||
ident = field;
|
||||
} else {
|
||||
if (field->kind != Ast_EnumFieldValue) {
|
||||
error(field, "An enum field's name must be an identifier");
|
||||
continue;
|
||||
}
|
||||
ident = field->EnumFieldValue.name;
|
||||
init = field->EnumFieldValue.value;
|
||||
if (ident == nullptr || ident->kind != Ast_Ident) {
|
||||
error(field, "An enum field's name must be an identifier");
|
||||
continue;
|
||||
}
|
||||
CommentGroup *docs = field->EnumFieldValue.docs;
|
||||
CommentGroup *comment = field->EnumFieldValue.comment;
|
||||
|
||||
String name = ident->Ident.token.string;
|
||||
|
||||
if (init != nullptr) {
|
||||
@@ -793,6 +802,8 @@ void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *named_type, Ast
|
||||
e->flags |= EntityFlag_Visited;
|
||||
e->state = EntityState_Resolved;
|
||||
e->Constant.flags |= entity_flags;
|
||||
e->Constant.docs = docs;
|
||||
e->Constant.comment = comment;
|
||||
|
||||
if (scope_lookup_current(ctx->scope, name) != nullptr) {
|
||||
error(ident, "'%.*s' is already declared in this enumeration", LIT(name));
|
||||
@@ -2702,29 +2713,30 @@ bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, Type *named_t
|
||||
|
||||
Type *t = alloc_type_enumerated_array(elem, index, bt->Enum.min_value, bt->Enum.max_value, Token_Invalid);
|
||||
|
||||
bool is_partial = false;
|
||||
bool is_sparse = false;
|
||||
if (at->tag != nullptr) {
|
||||
GB_ASSERT(at->tag->kind == Ast_BasicDirective);
|
||||
String name = at->tag->BasicDirective.name.string;
|
||||
if (name == "partial") {
|
||||
is_partial = true;
|
||||
if (name == "sparse") {
|
||||
is_sparse = true;
|
||||
} else {
|
||||
error(at->tag, "Invalid tag applied to an enumerated array, got #%.*s", LIT(name));
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_partial && t->EnumeratedArray.count > bt->Enum.fields.count) {
|
||||
if (!is_sparse && t->EnumeratedArray.count > bt->Enum.fields.count) {
|
||||
error(e, "Non-contiguous enumeration used as an index in an enumerated array");
|
||||
long long ea_count = cast(long long)t->EnumeratedArray.count;
|
||||
long long enum_count = cast(long long)bt->Enum.fields.count;
|
||||
error_line("\tenumerated array length: %lld\n", ea_count);
|
||||
error_line("\tenum field count: %lld\n", enum_count);
|
||||
error_line("\tSuggestion: prepend #partial to the enumerated array to allow for non-named elements\n");
|
||||
error_line("\tSuggestion: prepend #sparse to the enumerated array to allow for non-contiguous elements\n");
|
||||
if (2*enum_count < ea_count) {
|
||||
error_line("\tWarning: the number of named elements is much smaller than the length of the array, are you sure this is what you want?\n");
|
||||
error_line("\t this warning will be removed if #partial is applied\n");
|
||||
error_line("\t this warning will be removed if #sparse is applied\n");
|
||||
}
|
||||
}
|
||||
t->EnumeratedArray.is_sparse = is_sparse;
|
||||
|
||||
*type = t;
|
||||
|
||||
|
||||
+134
-24
@@ -504,6 +504,7 @@ enum VettedEntityKind {
|
||||
|
||||
VettedEntity_Unused,
|
||||
VettedEntity_Shadowed,
|
||||
VettedEntity_Shadowed_And_Unused,
|
||||
};
|
||||
struct VettedEntity {
|
||||
VettedEntityKind kind;
|
||||
@@ -625,12 +626,18 @@ void check_scope_usage(Checker *c, Scope *scope) {
|
||||
MUTEX_GUARD_BLOCK(scope->mutex) for_array(i, scope->elements.entries) {
|
||||
Entity *e = scope->elements.entries[i].value;
|
||||
if (e == nullptr) continue;
|
||||
VettedEntity ve = {};
|
||||
if (vet_unused && check_vet_unused(c, e, &ve)) {
|
||||
array_add(&vetted_entities, ve);
|
||||
}
|
||||
if (vet_shadowing && check_vet_shadowing(c, e, &ve)) {
|
||||
array_add(&vetted_entities, ve);
|
||||
VettedEntity ve_unused = {};
|
||||
VettedEntity ve_shadowed = {};
|
||||
bool is_unused = vet_unused && check_vet_unused(c, e, &ve_unused);
|
||||
bool is_shadowed = vet_shadowing && check_vet_shadowing(c, e, &ve_shadowed);
|
||||
if (is_unused && is_shadowed) {
|
||||
VettedEntity ve_both = ve_shadowed;
|
||||
ve_both.kind = VettedEntity_Shadowed_And_Unused;
|
||||
array_add(&vetted_entities, ve_both);
|
||||
} else if (is_unused) {
|
||||
array_add(&vetted_entities, ve_unused);
|
||||
} else if (is_shadowed) {
|
||||
array_add(&vetted_entities, ve_shadowed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -642,16 +649,18 @@ void check_scope_usage(Checker *c, Scope *scope) {
|
||||
Entity *other = ve.other;
|
||||
String name = e->token.string;
|
||||
|
||||
if (build_context.vet) {
|
||||
if (ve.kind == VettedEntity_Shadowed_And_Unused) {
|
||||
error(e->token, "'%.*s' declared but not used, possibly shadows declaration at line %d", LIT(name), other->token.pos.line);
|
||||
} else if (build_context.vet) {
|
||||
switch (ve.kind) {
|
||||
case VettedEntity_Unused:
|
||||
error(e->token, "'%.*s' declared but not used", LIT(name));
|
||||
break;
|
||||
case VettedEntity_Shadowed:
|
||||
if (e->flags&EntityFlag_Using) {
|
||||
error(e->token, "Declaration of '%.*s' from 'using' shadows declaration at line %lld", LIT(name), cast(long long)other->token.pos.line);
|
||||
error(e->token, "Declaration of '%.*s' from 'using' shadows declaration at line %d", LIT(name), other->token.pos.line);
|
||||
} else {
|
||||
error(e->token, "Declaration of '%.*s' shadows declaration at line %lld", LIT(name), cast(long long)other->token.pos.line);
|
||||
error(e->token, "Declaration of '%.*s' shadows declaration at line %d", LIT(name), other->token.pos.line);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -688,12 +697,17 @@ void add_dependency(CheckerInfo *info, DeclInfo *d, Entity *e) {
|
||||
ptr_set_add(&d->deps, e);
|
||||
mutex_unlock(&info->deps_mutex);
|
||||
}
|
||||
void add_type_info_dependency(DeclInfo *d, Type *type) {
|
||||
void add_type_info_dependency(CheckerInfo *info, DeclInfo *d, Type *type, bool require_mutex) {
|
||||
if (d == nullptr) {
|
||||
return;
|
||||
}
|
||||
// NOTE(bill): no mutex is required here because the only procedure calling it is wrapped in a mutex already
|
||||
if (require_mutex) {
|
||||
mutex_lock(&info->deps_mutex);
|
||||
}
|
||||
ptr_set_add(&d->type_info_deps, type);
|
||||
if (require_mutex) {
|
||||
mutex_unlock(&info->deps_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
AstPackage *get_core_package(CheckerInfo *info, String name) {
|
||||
@@ -919,6 +933,16 @@ void init_universal(void) {
|
||||
add_global_string_constant("ODIN_ENDIAN_STRING", target_endian_names[target_endians[bc->metrics.arch]]);
|
||||
}
|
||||
|
||||
{
|
||||
GlobalEnumValue values[ErrorPosStyle_COUNT] = {
|
||||
{"Default", ErrorPosStyle_Default},
|
||||
{"Unix", ErrorPosStyle_Unix},
|
||||
};
|
||||
|
||||
auto fields = add_global_enum_type(str_lit("Odin_Error_Pos_Style_Type"), values, gb_count_of(values));
|
||||
add_global_enum_constant(fields, "ODIN_ERROR_POS_STYLE", build_context.ODIN_ERROR_POS_STYLE);
|
||||
}
|
||||
|
||||
|
||||
add_global_bool_constant("ODIN_DEBUG", bc->ODIN_DEBUG);
|
||||
add_global_bool_constant("ODIN_DISABLE_ASSERT", bc->ODIN_DISABLE_ASSERT);
|
||||
@@ -1620,7 +1644,7 @@ void add_type_info_type_internal(CheckerContext *c, Type *t) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_type_info_dependency(c->decl, t);
|
||||
add_type_info_dependency(c->info, c->decl, t, false);
|
||||
|
||||
auto found = map_get(&c->info->type_info_map, t);
|
||||
if (found != nullptr) {
|
||||
@@ -1749,6 +1773,7 @@ void add_type_info_type_internal(CheckerContext *c, Type *t) {
|
||||
} else {
|
||||
add_type_info_type_internal(c, t_type_info_ptr);
|
||||
}
|
||||
add_type_info_type_internal(c, bt->Union.polymorphic_params);
|
||||
for_array(i, bt->Union.variants) {
|
||||
add_type_info_type_internal(c, bt->Union.variants[i]);
|
||||
}
|
||||
@@ -1772,6 +1797,7 @@ void add_type_info_type_internal(CheckerContext *c, Type *t) {
|
||||
}
|
||||
}
|
||||
}
|
||||
add_type_info_type_internal(c, bt->Struct.polymorphic_params);
|
||||
for_array(i, bt->Struct.fields) {
|
||||
Entity *f = bt->Struct.fields[i];
|
||||
add_type_info_type_internal(c, f->type);
|
||||
@@ -1965,6 +1991,7 @@ void add_min_dep_type_info(Checker *c, Type *t) {
|
||||
} else {
|
||||
add_min_dep_type_info(c, t_type_info_ptr);
|
||||
}
|
||||
add_min_dep_type_info(c, bt->Union.polymorphic_params);
|
||||
for_array(i, bt->Union.variants) {
|
||||
add_min_dep_type_info(c, bt->Union.variants[i]);
|
||||
}
|
||||
@@ -1988,6 +2015,7 @@ void add_min_dep_type_info(Checker *c, Type *t) {
|
||||
}
|
||||
}
|
||||
}
|
||||
add_min_dep_type_info(c, bt->Struct.polymorphic_params);
|
||||
for_array(i, bt->Struct.fields) {
|
||||
Entity *f = bt->Struct.fields[i];
|
||||
add_min_dep_type_info(c, f->type);
|
||||
@@ -3479,9 +3507,12 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) {
|
||||
|
||||
if (entity_visibility_kind == EntityVisiblity_Public &&
|
||||
(c->scope->flags&ScopeFlag_File) &&
|
||||
c->scope->file &&
|
||||
(c->scope->file->flags & AstFile_IsPrivate)) {
|
||||
entity_visibility_kind = EntityVisiblity_PrivateToPackage;
|
||||
c->scope->file) {
|
||||
if (c->scope->file->flags & AstFile_IsPrivateFile) {
|
||||
entity_visibility_kind = EntityVisiblity_PrivateToFile;
|
||||
} else if (c->scope->file->flags & AstFile_IsPrivatePkg) {
|
||||
entity_visibility_kind = EntityVisiblity_PrivateToPackage;
|
||||
}
|
||||
}
|
||||
|
||||
if (entity_visibility_kind != EntityVisiblity_Public && !(c->scope->flags&ScopeFlag_File)) {
|
||||
@@ -3572,9 +3603,6 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) {
|
||||
|
||||
if (is_ast_type(init)) {
|
||||
e = alloc_entity_type_name(d->scope, token, nullptr);
|
||||
// if (vd->type != nullptr) {
|
||||
// error(name, "A type declaration cannot have an type parameter");
|
||||
// }
|
||||
} else if (init->kind == Ast_ProcLit) {
|
||||
if (c->scope->flags&ScopeFlag_Type) {
|
||||
error(name, "Procedure declarations are not allowed within a struct");
|
||||
@@ -3677,6 +3705,59 @@ void check_add_foreign_block_decl(CheckerContext *ctx, Ast *decl) {
|
||||
check_collect_entities(&c, block->stmts);
|
||||
}
|
||||
|
||||
bool correct_single_type_alias(CheckerContext *c, Entity *e) {
|
||||
if (e->kind == Entity_Constant) {
|
||||
DeclInfo *d = e->decl_info;
|
||||
if (d != nullptr && d->init_expr != nullptr) {
|
||||
Ast *init = d->init_expr;
|
||||
Entity *alias_of = check_entity_from_ident_or_selector(c, init, true);
|
||||
if (alias_of != nullptr && alias_of->kind == Entity_TypeName) {
|
||||
e->kind = Entity_TypeName;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool correct_type_alias_in_scope_backwards(CheckerContext *c, Scope *s) {
|
||||
isize n = s->elements.entries.count;
|
||||
bool correction = false;
|
||||
for (isize i = n-1; i >= 0; i--) {
|
||||
correction |= correct_single_type_alias(c, s->elements.entries[i].value);
|
||||
}
|
||||
return correction;
|
||||
}
|
||||
bool correct_type_alias_in_scope_forwards(CheckerContext *c, Scope *s) {
|
||||
isize n = s->elements.entries.count;
|
||||
bool correction = false;
|
||||
for (isize i = 0; i < n; i++) {
|
||||
correction |= correct_single_type_alias(c, s->elements.entries[i].value);
|
||||
}
|
||||
return correction;
|
||||
}
|
||||
|
||||
|
||||
void correct_type_aliases_in_scope(CheckerContext *c, Scope *s) {
|
||||
// NOTE(bill, 2022-02-04): This is used to solve the problem caused by type aliases
|
||||
// of type aliases being "confused" as constants
|
||||
//
|
||||
// A :: C
|
||||
// B :: A
|
||||
// C :: struct {b: ^B}
|
||||
//
|
||||
// See @TypeAliasingProblem for more information
|
||||
for (;;) {
|
||||
bool corrections = false;
|
||||
corrections |= correct_type_alias_in_scope_backwards(c, s);
|
||||
corrections |= correct_type_alias_in_scope_forwards(c, s);
|
||||
if (!corrections) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// NOTE(bill): If file_scopes == nullptr, this will act like a local scope
|
||||
void check_collect_entities(CheckerContext *c, Slice<Ast *> const &nodes) {
|
||||
AstFile *curr_file = nullptr;
|
||||
@@ -3748,6 +3829,7 @@ void check_collect_entities(CheckerContext *c, Slice<Ast *> const &nodes) {
|
||||
}
|
||||
}
|
||||
|
||||
// correct_type_aliases(c);
|
||||
|
||||
// NOTE(bill): 'when' stmts need to be handled after the other as the condition may refer to something
|
||||
// declared after this stmt in source
|
||||
@@ -4393,10 +4475,11 @@ bool collect_file_decls(CheckerContext *ctx, Slice<Ast *> const &decls) {
|
||||
|
||||
for_array(i, decls) {
|
||||
if (collect_file_decl(ctx, decls[i])) {
|
||||
correct_type_aliases_in_scope(ctx, ctx->scope);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
correct_type_aliases_in_scope(ctx, ctx->scope);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -4666,6 +4749,15 @@ void check_import_entities(Checker *c) {
|
||||
}
|
||||
add_untyped_expressions(ctx.info, &untyped);
|
||||
}
|
||||
|
||||
for_array(i, pkg->files) {
|
||||
AstFile *f = pkg->files[i];
|
||||
reset_checker_context(&ctx, f, &untyped);
|
||||
ctx.collect_delayed_decls = false;
|
||||
|
||||
correct_type_aliases_in_scope(&ctx, pkg->scope);
|
||||
}
|
||||
|
||||
for_array(i, pkg->files) {
|
||||
AstFile *f = pkg->files[i];
|
||||
reset_checker_context(&ctx, f, &untyped);
|
||||
@@ -4887,6 +4979,9 @@ bool check_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *untyped, Proc
|
||||
bool bounds_check = (pi->tags & ProcTag_bounds_check) != 0;
|
||||
bool no_bounds_check = (pi->tags & ProcTag_no_bounds_check) != 0;
|
||||
|
||||
bool type_assert = (pi->tags & ProcTag_type_assert) != 0;
|
||||
bool no_type_assert = (pi->tags & ProcTag_no_type_assert) != 0;
|
||||
|
||||
if (bounds_check) {
|
||||
ctx.state_flags |= StateFlag_bounds_check;
|
||||
ctx.state_flags &= ~StateFlag_no_bounds_check;
|
||||
@@ -4894,6 +4989,15 @@ bool check_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *untyped, Proc
|
||||
ctx.state_flags |= StateFlag_no_bounds_check;
|
||||
ctx.state_flags &= ~StateFlag_bounds_check;
|
||||
}
|
||||
|
||||
if (type_assert) {
|
||||
ctx.state_flags |= StateFlag_type_assert;
|
||||
ctx.state_flags &= ~StateFlag_no_type_assert;
|
||||
} else if (no_type_assert) {
|
||||
ctx.state_flags |= StateFlag_no_type_assert;
|
||||
ctx.state_flags &= ~StateFlag_type_assert;
|
||||
}
|
||||
|
||||
if (pi->body != nullptr && e != nullptr) {
|
||||
GB_ASSERT((e->flags & EntityFlag_ProcBodyChecked) == 0);
|
||||
}
|
||||
@@ -5307,12 +5411,18 @@ void check_unique_package_names(Checker *c) {
|
||||
string_map_set(&pkgs, key, pkg);
|
||||
continue;
|
||||
}
|
||||
auto *curr = pkg->files[0]->pkg_decl;
|
||||
auto *prev = (*found)->files[0]->pkg_decl;
|
||||
if (curr == prev) {
|
||||
// NOTE(bill): A false positive was found, ignore it
|
||||
continue;
|
||||
}
|
||||
|
||||
error(pkg->files[0]->pkg_decl, "Duplicate declaration of 'package %.*s'", LIT(name));
|
||||
error(curr, "Duplicate declaration of 'package %.*s'", LIT(name));
|
||||
error_line("\tA package name must be unique\n"
|
||||
"\tThere is no relation between a package name and the directory that contains it, so they can be completely different\n"
|
||||
"\tA package name is required for link name prefixing to have a consistent ABI\n");
|
||||
error((*found)->files[0]->pkg_decl, "found at previous location");
|
||||
error(prev, "found at previous location");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5504,9 +5614,6 @@ void check_parsed_files(Checker *c) {
|
||||
TIME_SECTION("calculate global init order");
|
||||
calculate_global_init_order(c);
|
||||
|
||||
TIME_SECTION("generate minimum dependency set");
|
||||
generate_minimum_dependency_set(c, c->info.entry_point);
|
||||
|
||||
TIME_SECTION("check test procedures");
|
||||
check_test_procedures(c);
|
||||
|
||||
@@ -5517,6 +5624,9 @@ void check_parsed_files(Checker *c) {
|
||||
add_type_info_for_type_definitions(c);
|
||||
check_merge_queues_into_arrays(c);
|
||||
|
||||
TIME_SECTION("generate minimum dependency set");
|
||||
generate_minimum_dependency_set(c, c->info.entry_point);
|
||||
|
||||
TIME_SECTION("check entry point");
|
||||
if (build_context.build_mode == BuildMode_Executable && !build_context.no_entry_point && build_context.command_kind != Command_test) {
|
||||
Scope *s = c->info.init_scope;
|
||||
|
||||
@@ -213,8 +213,6 @@ BuiltinProc__type_simple_boolean_begin,
|
||||
BuiltinProc_type_is_union,
|
||||
BuiltinProc_type_is_enum,
|
||||
BuiltinProc_type_is_proc,
|
||||
BuiltinProc_type_is_bit_field,
|
||||
BuiltinProc_type_is_bit_field_value,
|
||||
BuiltinProc_type_is_bit_set,
|
||||
BuiltinProc_type_is_simd_vector,
|
||||
BuiltinProc_type_is_matrix,
|
||||
@@ -466,8 +464,6 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
|
||||
{STR_LIT("type_is_union"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("type_is_enum"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("type_is_proc"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("type_is_bit_field"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("type_is_bit_field_value"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("type_is_bit_set"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("type_is_simd_vector"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("type_is_matrix"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
|
||||
+15
-5
@@ -15,7 +15,7 @@ struct OdinDocVersionType {
|
||||
|
||||
#define OdinDocVersionType_Major 0
|
||||
#define OdinDocVersionType_Minor 2
|
||||
#define OdinDocVersionType_Patch 3
|
||||
#define OdinDocVersionType_Patch 4
|
||||
|
||||
struct OdinDocHeaderBase {
|
||||
u8 magic[8];
|
||||
@@ -154,6 +154,7 @@ enum OdinDocEntityKind : u32 {
|
||||
OdinDocEntity_ProcGroup = 5,
|
||||
OdinDocEntity_ImportName = 6,
|
||||
OdinDocEntity_LibraryName = 7,
|
||||
OdinDocEntity_Builtin = 8,
|
||||
};
|
||||
|
||||
enum OdinDocEntityFlag : u64 {
|
||||
@@ -170,6 +171,9 @@ enum OdinDocEntityFlag : u64 {
|
||||
|
||||
OdinDocEntityFlag_Type_Alias = 1ull<<20,
|
||||
|
||||
OdinDocEntityFlag_Builtin_Pkg_Builtin = 1ull<<30,
|
||||
OdinDocEntityFlag_Builtin_Pkg_Intrinsics = 1ull<<31,
|
||||
|
||||
OdinDocEntityFlag_Var_Thread_Local = 1ull<<40,
|
||||
OdinDocEntityFlag_Var_Static = 1ull<<41,
|
||||
|
||||
@@ -185,8 +189,8 @@ struct OdinDocEntity {
|
||||
OdinDocTypeIndex type;
|
||||
OdinDocString init_string;
|
||||
u32 reserved_for_init;
|
||||
OdinDocString comment;
|
||||
OdinDocString docs;
|
||||
OdinDocString comment; // line comment
|
||||
OdinDocString docs; // preceding comment
|
||||
i32 field_group_index;
|
||||
OdinDocEntityIndex foreign_library;
|
||||
OdinDocString link_name;
|
||||
@@ -201,15 +205,21 @@ enum OdinDocPkgFlags : u32 {
|
||||
OdinDocPkgFlag_Init = 1<<2,
|
||||
};
|
||||
|
||||
struct OdinDocScopeEntry {
|
||||
OdinDocString name;
|
||||
OdinDocEntityIndex entity;
|
||||
};
|
||||
|
||||
struct OdinDocPkg {
|
||||
OdinDocString fullpath;
|
||||
OdinDocString name;
|
||||
u32 flags;
|
||||
OdinDocString docs;
|
||||
OdinDocArray<OdinDocFileIndex> files;
|
||||
OdinDocArray<OdinDocEntityIndex> entities;
|
||||
OdinDocArray<OdinDocFileIndex> files;
|
||||
OdinDocArray<OdinDocScopeEntry> entries;
|
||||
};
|
||||
|
||||
|
||||
struct OdinDocHeader {
|
||||
OdinDocHeaderBase base;
|
||||
|
||||
|
||||
+41
-21
@@ -811,8 +811,17 @@ OdinDocEntityIndex odin_doc_add_entity(OdinDocWriter *w, Entity *e) {
|
||||
comment = e->decl_info->comment;
|
||||
docs = e->decl_info->docs;
|
||||
}
|
||||
if (e->kind == Entity_Variable) {
|
||||
if (!comment) { comment = e->Variable.comment; }
|
||||
if (!docs) { docs = e->Variable.docs; }
|
||||
} else if (e->kind == Entity_Constant) {
|
||||
if (!comment) { comment = e->Constant.comment; }
|
||||
if (!docs) { docs = e->Constant.docs; }
|
||||
}
|
||||
|
||||
String name = e->token.string;
|
||||
String link_name = {};
|
||||
TokenPos pos = e->token.pos;
|
||||
|
||||
OdinDocEntityKind kind = OdinDocEntity_Invalid;
|
||||
u64 flags = 0;
|
||||
@@ -827,6 +836,7 @@ OdinDocEntityIndex odin_doc_add_entity(OdinDocWriter *w, Entity *e) {
|
||||
case Entity_ProcGroup: kind = OdinDocEntity_ProcGroup; break;
|
||||
case Entity_ImportName: kind = OdinDocEntity_ImportName; break;
|
||||
case Entity_LibraryName: kind = OdinDocEntity_LibraryName; break;
|
||||
case Entity_Builtin: kind = OdinDocEntity_Builtin; break;
|
||||
}
|
||||
|
||||
switch (e->kind) {
|
||||
@@ -856,6 +866,23 @@ OdinDocEntityIndex odin_doc_add_entity(OdinDocWriter *w, Entity *e) {
|
||||
if (e->Procedure.is_export) { flags |= OdinDocEntityFlag_Export; }
|
||||
link_name = e->Procedure.link_name;
|
||||
break;
|
||||
case Entity_Builtin:
|
||||
{
|
||||
auto bp = builtin_procs[e->Builtin.id];
|
||||
pos = {};
|
||||
name = bp.name;
|
||||
switch (bp.pkg) {
|
||||
case BuiltinProcPkg_builtin:
|
||||
flags |= OdinDocEntityFlag_Builtin_Pkg_Builtin;
|
||||
break;
|
||||
case BuiltinProcPkg_intrinsics:
|
||||
flags |= OdinDocEntityFlag_Builtin_Pkg_Intrinsics;
|
||||
break;
|
||||
default:
|
||||
GB_PANIC("Unhandled BuiltinProcPkg");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (e->flags & EntityFlag_Param) {
|
||||
@@ -891,8 +918,8 @@ OdinDocEntityIndex odin_doc_add_entity(OdinDocWriter *w, Entity *e) {
|
||||
|
||||
doc_entity.kind = kind;
|
||||
doc_entity.flags = flags;
|
||||
doc_entity.pos = odin_doc_token_pos_cast(w, e->token.pos);
|
||||
doc_entity.name = odin_doc_write_string(w, e->token.string);
|
||||
doc_entity.pos = odin_doc_token_pos_cast(w, pos);
|
||||
doc_entity.name = odin_doc_write_string(w, name);
|
||||
doc_entity.type = 0; // Set later
|
||||
doc_entity.init_string = init_string;
|
||||
doc_entity.comment = odin_doc_comment_group_string(w, comment);
|
||||
@@ -969,7 +996,7 @@ void odin_doc_update_entities(OdinDocWriter *w) {
|
||||
|
||||
|
||||
|
||||
OdinDocArray<OdinDocEntityIndex> odin_doc_add_pkg_entities(OdinDocWriter *w, AstPackage *pkg) {
|
||||
OdinDocArray<OdinDocScopeEntry> odin_doc_add_pkg_entries(OdinDocWriter *w, AstPackage *pkg) {
|
||||
if (pkg->scope == nullptr) {
|
||||
return {};
|
||||
}
|
||||
@@ -977,14 +1004,14 @@ OdinDocArray<OdinDocEntityIndex> odin_doc_add_pkg_entities(OdinDocWriter *w, Ast
|
||||
return {};
|
||||
}
|
||||
|
||||
auto entities = array_make<Entity *>(heap_allocator(), 0, pkg->scope->elements.entries.count);
|
||||
defer (array_free(&entities));
|
||||
auto entries = array_make<OdinDocScopeEntry>(heap_allocator(), 0, w->entity_cache.entries.count);
|
||||
defer (array_free(&entries));
|
||||
|
||||
for_array(i, pkg->scope->elements.entries) {
|
||||
String name = pkg->scope->elements.entries[i].key.string;
|
||||
Entity *e = pkg->scope->elements.entries[i].value;
|
||||
switch (e->kind) {
|
||||
case Entity_Invalid:
|
||||
case Entity_Builtin:
|
||||
case Entity_Nil:
|
||||
case Entity_Label:
|
||||
continue;
|
||||
@@ -995,34 +1022,27 @@ OdinDocArray<OdinDocEntityIndex> odin_doc_add_pkg_entities(OdinDocWriter *w, Ast
|
||||
case Entity_ProcGroup:
|
||||
case Entity_ImportName:
|
||||
case Entity_LibraryName:
|
||||
case Entity_Builtin:
|
||||
// Fine
|
||||
break;
|
||||
}
|
||||
array_add(&entities, e);
|
||||
}
|
||||
gb_sort_array(entities.data, entities.count, cmp_entities_for_printing);
|
||||
|
||||
auto entity_indices = array_make<OdinDocEntityIndex>(heap_allocator(), 0, w->entity_cache.entries.count);
|
||||
defer (array_free(&entity_indices));
|
||||
|
||||
for_array(i, entities) {
|
||||
Entity *e = entities[i];
|
||||
if (e->pkg != pkg) {
|
||||
continue;
|
||||
}
|
||||
if (!is_entity_exported(e)) {
|
||||
if (!is_entity_exported(e, true)) {
|
||||
continue;
|
||||
}
|
||||
if (e->token.string.len == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
OdinDocEntityIndex doc_entity_index = 0;
|
||||
doc_entity_index = odin_doc_add_entity(w, e);
|
||||
array_add(&entity_indices, doc_entity_index);
|
||||
OdinDocScopeEntry entry = {};
|
||||
entry.name = odin_doc_write_string(w, name);
|
||||
entry.entity = odin_doc_add_entity(w, e);
|
||||
array_add(&entries, entry);
|
||||
}
|
||||
|
||||
return odin_write_slice(w, entity_indices.data, entity_indices.count);
|
||||
return odin_write_slice(w, entries.data, entries.count);
|
||||
}
|
||||
|
||||
|
||||
@@ -1090,7 +1110,7 @@ void odin_doc_write_docs(OdinDocWriter *w) {
|
||||
}
|
||||
|
||||
doc_pkg.files = odin_write_slice(w, file_indices.data, file_indices.count);
|
||||
doc_pkg.entities = odin_doc_add_pkg_entities(w, pkg);
|
||||
doc_pkg.entries = odin_doc_add_pkg_entries(w, pkg);
|
||||
|
||||
if (dst) {
|
||||
*dst = doc_pkg;
|
||||
|
||||
+5
-1
@@ -161,6 +161,8 @@ struct Entity {
|
||||
ParameterValue param_value;
|
||||
u32 flags;
|
||||
i32 field_group_index;
|
||||
CommentGroup *docs;
|
||||
CommentGroup *comment;
|
||||
} Constant;
|
||||
struct {
|
||||
Ast *init_expr; // only used for some variables within procedure bodies
|
||||
@@ -175,6 +177,8 @@ struct Entity {
|
||||
String link_name;
|
||||
String link_prefix;
|
||||
String link_section;
|
||||
CommentGroup *docs;
|
||||
CommentGroup *comment;
|
||||
bool is_foreign;
|
||||
bool is_export;
|
||||
} Variable;
|
||||
@@ -241,7 +245,7 @@ bool is_entity_exported(Entity *e, bool allow_builtin = false) {
|
||||
if (e->flags & EntityFlag_NotExported) {
|
||||
return false;
|
||||
}
|
||||
if (e->file != nullptr && (e->file->flags & AstFile_IsPrivate) != 0) {
|
||||
if (e->file != nullptr && (e->file->flags & (AstFile_IsPrivatePkg|AstFile_IsPrivateFile)) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,10 @@ void init_global_error_collector(void) {
|
||||
}
|
||||
|
||||
|
||||
// temporary
|
||||
// defined in build_settings.cpp
|
||||
char *token_pos_to_string(TokenPos const &pos);
|
||||
|
||||
bool set_file_path_string(i32 index, String const &path) {
|
||||
bool ok = false;
|
||||
GB_ASSERT(index >= 0);
|
||||
@@ -403,6 +407,7 @@ void compiler_error(char const *fmt, ...) {
|
||||
gb_printf_err("Internal Compiler Error: %s\n",
|
||||
gb_bprintf_va(fmt, va));
|
||||
va_end(va);
|
||||
GB_DEBUG_TRAP();
|
||||
gb_exit(1);
|
||||
}
|
||||
|
||||
|
||||
@@ -232,6 +232,7 @@ struct lbTargetList {
|
||||
|
||||
enum lbProcedureFlag : u32 {
|
||||
lbProcedureFlag_WithoutMemcpyPass = 1<<0,
|
||||
lbProcedureFlag_DebugAllocaCopy = 1<<1,
|
||||
};
|
||||
|
||||
struct lbCopyElisionHint {
|
||||
|
||||
@@ -115,8 +115,8 @@ LLVMValueRef llvm_const_cast(LLVMValueRef val, LLVMTypeRef dst) {
|
||||
|
||||
|
||||
lbValue lb_const_ptr_cast(lbModule *m, lbValue value, Type *t) {
|
||||
GB_ASSERT(is_type_pointer(value.type));
|
||||
GB_ASSERT(is_type_pointer(t));
|
||||
GB_ASSERT(is_type_internally_pointer_like(value.type));
|
||||
GB_ASSERT(is_type_internally_pointer_like(t));
|
||||
GB_ASSERT(lb_is_const(value));
|
||||
|
||||
lbValue res = {};
|
||||
@@ -175,7 +175,7 @@ LLVMValueRef llvm_const_array(LLVMTypeRef elem_type, LLVMValueRef *values, isize
|
||||
}
|
||||
|
||||
LLVMValueRef llvm_const_slice(lbModule *m, lbValue data, lbValue len) {
|
||||
GB_ASSERT(is_type_pointer(data.type));
|
||||
GB_ASSERT(is_type_pointer(data.type) || is_type_multi_pointer(data.type));
|
||||
GB_ASSERT(are_types_identical(len.type, t_int));
|
||||
LLVMValueRef vals[2] = {
|
||||
data.value,
|
||||
@@ -568,7 +568,7 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
|
||||
}
|
||||
|
||||
case ExactValue_Integer:
|
||||
if (is_type_pointer(type)) {
|
||||
if (is_type_pointer(type) || is_type_multi_pointer(type)) {
|
||||
LLVMTypeRef t = lb_type(m, original_type);
|
||||
LLVMValueRef i = lb_big_int_to_llvm(m, t_uintptr, &value.value_integer);
|
||||
res.value = LLVMConstIntToPtr(i, t);
|
||||
|
||||
@@ -965,6 +965,77 @@ void lb_add_debug_local_variable(lbProcedure *p, LLVMValueRef ptr, Type *type, T
|
||||
LLVMDIBuilderInsertDeclareBefore(m->debug_builder, storage, var_info, llvm_expr, llvm_debug_loc, instr);
|
||||
}
|
||||
|
||||
|
||||
void lb_add_debug_param_variable(lbProcedure *p, LLVMValueRef ptr, Type *type, Token const &token, unsigned arg_number) {
|
||||
if (p->debug_info == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (type == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (type == t_invalid) {
|
||||
return;
|
||||
}
|
||||
if (p->body == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
lbModule *m = p->module;
|
||||
String const &name = token.string;
|
||||
if (name == "" || name == "_") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (lb_get_llvm_metadata(m, ptr) != nullptr) {
|
||||
// Already been set
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
AstFile *file = p->body->file();
|
||||
|
||||
LLVMMetadataRef llvm_scope = lb_get_current_debug_scope(p);
|
||||
LLVMMetadataRef llvm_file = lb_get_llvm_metadata(m, file);
|
||||
GB_ASSERT(llvm_scope != nullptr);
|
||||
if (llvm_file == nullptr) {
|
||||
llvm_file = LLVMDIScopeGetFile(llvm_scope);
|
||||
}
|
||||
|
||||
if (llvm_file == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
LLVMDIFlags flags = LLVMDIFlagZero;
|
||||
LLVMBool always_preserve = build_context.optimization_level == 0;
|
||||
|
||||
LLVMMetadataRef debug_type = lb_debug_type(m, type);
|
||||
|
||||
LLVMMetadataRef var_info = LLVMDIBuilderCreateParameterVariable(
|
||||
m->debug_builder, llvm_scope,
|
||||
cast(char const *)name.text, cast(size_t)name.len,
|
||||
arg_number,
|
||||
llvm_file, token.pos.line,
|
||||
debug_type,
|
||||
always_preserve, flags
|
||||
);
|
||||
|
||||
LLVMValueRef storage = ptr;
|
||||
LLVMValueRef instr = ptr;
|
||||
LLVMBasicBlockRef block = p->decl_block->block;
|
||||
LLVMMetadataRef llvm_debug_loc = lb_debug_location_from_token_pos(p, token.pos);
|
||||
LLVMMetadataRef llvm_expr = LLVMDIBuilderCreateExpression(m->debug_builder, nullptr, 0);
|
||||
lb_set_llvm_metadata(m, ptr, llvm_expr);
|
||||
if (LLVMIsAAllocaInst(instr)) {
|
||||
LLVMDIBuilderInsertDeclareBefore(m->debug_builder, storage, var_info, llvm_expr, llvm_debug_loc, instr);
|
||||
} else {
|
||||
// NOTE(bill, 2022-02-01): For parameter values, you must insert them at the end of the decl block
|
||||
// The reason is that if the parameter is at index 0 and a pointer, there is not such things as an
|
||||
// instruction "before" it.
|
||||
LLVMDIBuilderInsertDeclareAtEnd(m->debug_builder, storage, var_info, llvm_expr, llvm_debug_loc, block);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void lb_add_debug_context_variable(lbProcedure *p, lbAddr const &ctx) {
|
||||
if (!p->debug_info || !p->body) {
|
||||
return;
|
||||
|
||||
+77
-35
@@ -580,6 +580,27 @@ LLVMValueRef lb_matrix_to_trimmed_vector(lbProcedure *p, lbValue m) {
|
||||
|
||||
lbValue lb_emit_matrix_tranpose(lbProcedure *p, lbValue m, Type *type) {
|
||||
if (is_type_array(m.type)) {
|
||||
i32 rank = type_math_rank(m.type);
|
||||
if (rank == 2) {
|
||||
lbAddr addr = lb_add_local_generated(p, type, false);
|
||||
lbValue dst = addr.addr;
|
||||
lbValue src = m;
|
||||
i32 n = cast(i32)get_array_type_count(m.type);
|
||||
i32 m = cast(i32)get_array_type_count(type);
|
||||
// m.type == [n][m]T
|
||||
// type == [m][n]T
|
||||
|
||||
for (i32 j = 0; j < m; j++) {
|
||||
lbValue dst_col = lb_emit_struct_ep(p, dst, j);
|
||||
for (i32 i = 0; i < n; i++) {
|
||||
lbValue dst_row = lb_emit_struct_ep(p, dst_col, i);
|
||||
lbValue src_col = lb_emit_struct_ev(p, src, i);
|
||||
lbValue src_row = lb_emit_struct_ev(p, src_col, j);
|
||||
lb_emit_store(p, dst_row, src_row);
|
||||
}
|
||||
}
|
||||
return lb_addr_load(p, addr);
|
||||
}
|
||||
// no-op
|
||||
m.type = type;
|
||||
return m;
|
||||
@@ -1834,6 +1855,15 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
|
||||
return lb_addr_load(p, parent);
|
||||
}
|
||||
}
|
||||
if (dst->Union.variants.count == 1) {
|
||||
Type *vt = dst->Union.variants[0];
|
||||
if (internal_check_is_assignable_to(src, vt)) {
|
||||
value = lb_emit_conv(p, value, vt);
|
||||
lbAddr parent = lb_add_local_generated(p, t, true);
|
||||
lb_emit_store_union_variant(p, parent.addr, value, vt);
|
||||
return lb_addr_load(p, parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE(bill): This has to be done before 'Pointer <-> Pointer' as it's
|
||||
@@ -2768,28 +2798,30 @@ lbValue lb_build_unary_and(lbProcedure *p, Ast *expr) {
|
||||
Type *src_type = type_deref(v.type);
|
||||
Type *dst_type = type;
|
||||
|
||||
lbValue src_tag = {};
|
||||
lbValue dst_tag = {};
|
||||
if (is_type_union_maybe_pointer(src_type)) {
|
||||
src_tag = lb_emit_comp_against_nil(p, Token_NotEq, v);
|
||||
dst_tag = lb_const_bool(p->module, t_bool, true);
|
||||
} else {
|
||||
src_tag = lb_emit_load(p, lb_emit_union_tag_ptr(p, v));
|
||||
dst_tag = lb_const_union_tag(p->module, src_type, dst_type);
|
||||
|
||||
if ((p->state_flags & StateFlag_no_type_assert) == 0) {
|
||||
lbValue src_tag = {};
|
||||
lbValue dst_tag = {};
|
||||
if (is_type_union_maybe_pointer(src_type)) {
|
||||
src_tag = lb_emit_comp_against_nil(p, Token_NotEq, v);
|
||||
dst_tag = lb_const_bool(p->module, t_bool, true);
|
||||
} else {
|
||||
src_tag = lb_emit_load(p, lb_emit_union_tag_ptr(p, v));
|
||||
dst_tag = lb_const_union_tag(p->module, src_type, dst_type);
|
||||
}
|
||||
lbValue ok = lb_emit_comp(p, Token_CmpEq, src_tag, dst_tag);
|
||||
auto args = array_make<lbValue>(permanent_allocator(), 6);
|
||||
args[0] = ok;
|
||||
|
||||
args[1] = lb_find_or_add_entity_string(p->module, get_file_path_string(pos.file_id));
|
||||
args[2] = lb_const_int(p->module, t_i32, pos.line);
|
||||
args[3] = lb_const_int(p->module, t_i32, pos.column);
|
||||
|
||||
args[4] = lb_typeid(p->module, src_type);
|
||||
args[5] = lb_typeid(p->module, dst_type);
|
||||
lb_emit_runtime_call(p, "type_assertion_check", args);
|
||||
}
|
||||
|
||||
lbValue ok = lb_emit_comp(p, Token_CmpEq, src_tag, dst_tag);
|
||||
auto args = array_make<lbValue>(permanent_allocator(), 6);
|
||||
args[0] = ok;
|
||||
|
||||
args[1] = lb_find_or_add_entity_string(p->module, get_file_path_string(pos.file_id));
|
||||
args[2] = lb_const_int(p->module, t_i32, pos.line);
|
||||
args[3] = lb_const_int(p->module, t_i32, pos.column);
|
||||
|
||||
args[4] = lb_typeid(p->module, src_type);
|
||||
args[5] = lb_typeid(p->module, dst_type);
|
||||
lb_emit_runtime_call(p, "type_assertion_check", args);
|
||||
|
||||
lbValue data_ptr = v;
|
||||
return lb_emit_conv(p, data_ptr, tv.type);
|
||||
} else if (is_type_any(t)) {
|
||||
@@ -2797,23 +2829,23 @@ lbValue lb_build_unary_and(lbProcedure *p, Ast *expr) {
|
||||
if (is_type_pointer(v.type)) {
|
||||
v = lb_emit_load(p, v);
|
||||
}
|
||||
|
||||
lbValue data_ptr = lb_emit_struct_ev(p, v, 0);
|
||||
lbValue any_id = lb_emit_struct_ev(p, v, 1);
|
||||
lbValue id = lb_typeid(p->module, type);
|
||||
if ((p->state_flags & StateFlag_no_type_assert) == 0) {
|
||||
lbValue any_id = lb_emit_struct_ev(p, v, 1);
|
||||
|
||||
lbValue id = lb_typeid(p->module, type);
|
||||
lbValue ok = lb_emit_comp(p, Token_CmpEq, any_id, id);
|
||||
auto args = array_make<lbValue>(permanent_allocator(), 6);
|
||||
args[0] = ok;
|
||||
|
||||
lbValue ok = lb_emit_comp(p, Token_CmpEq, any_id, id);
|
||||
auto args = array_make<lbValue>(permanent_allocator(), 6);
|
||||
args[0] = ok;
|
||||
args[1] = lb_find_or_add_entity_string(p->module, get_file_path_string(pos.file_id));
|
||||
args[2] = lb_const_int(p->module, t_i32, pos.line);
|
||||
args[3] = lb_const_int(p->module, t_i32, pos.column);
|
||||
|
||||
args[1] = lb_find_or_add_entity_string(p->module, get_file_path_string(pos.file_id));
|
||||
args[2] = lb_const_int(p->module, t_i32, pos.line);
|
||||
args[3] = lb_const_int(p->module, t_i32, pos.column);
|
||||
|
||||
args[4] = any_id;
|
||||
args[5] = id;
|
||||
lb_emit_runtime_call(p, "type_assertion_check", args);
|
||||
args[4] = any_id;
|
||||
args[5] = id;
|
||||
lb_emit_runtime_call(p, "type_assertion_check", args);
|
||||
}
|
||||
|
||||
return lb_emit_conv(p, data_ptr, tv.type);
|
||||
} else {
|
||||
@@ -2843,6 +2875,14 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
|
||||
out &= ~StateFlag_bounds_check;
|
||||
}
|
||||
|
||||
if (in & StateFlag_type_assert) {
|
||||
out |= StateFlag_type_assert;
|
||||
out &= ~StateFlag_no_type_assert;
|
||||
} else if (in & StateFlag_no_type_assert) {
|
||||
out |= StateFlag_no_type_assert;
|
||||
out &= ~StateFlag_type_assert;
|
||||
}
|
||||
|
||||
p->state_flags = out;
|
||||
}
|
||||
|
||||
@@ -3460,7 +3500,8 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
|
||||
GB_ASSERT_MSG(is_type_indexable(t), "%s %s", type_to_string(t), expr_to_string(expr));
|
||||
|
||||
if (is_type_map(t)) {
|
||||
lbValue map_val = lb_build_addr_ptr(p, ie->expr);
|
||||
lbAddr map_addr = lb_build_addr(p, ie->expr);
|
||||
lbValue map_val = lb_addr_load(p, map_addr);
|
||||
if (deref) {
|
||||
map_val = lb_emit_load(p, map_val);
|
||||
}
|
||||
@@ -3469,7 +3510,8 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
|
||||
key = lb_emit_conv(p, key, t->Map.key);
|
||||
|
||||
Type *result_type = type_of_expr(expr);
|
||||
return lb_addr_map(map_val, key, t, result_type);
|
||||
lbValue map_ptr = lb_address_from_load_or_generate_local(p, map_val);
|
||||
return lb_addr_map(map_ptr, key, t, result_type);
|
||||
}
|
||||
|
||||
switch (t->kind) {
|
||||
|
||||
@@ -271,6 +271,10 @@ lbAddr lb_addr(lbValue addr) {
|
||||
|
||||
|
||||
lbAddr lb_addr_map(lbValue addr, lbValue map_key, Type *map_type, Type *map_result) {
|
||||
GB_ASSERT(is_type_pointer(addr.type));
|
||||
Type *mt = type_deref(addr.type);
|
||||
GB_ASSERT(is_type_map(mt));
|
||||
|
||||
lbAddr v = {lbAddr_Map, addr};
|
||||
v.map.key = map_key;
|
||||
v.map.type = map_type;
|
||||
@@ -1598,8 +1602,9 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
|
||||
return llvm_type;
|
||||
}
|
||||
llvm_type = LLVMStructCreateNamed(ctx, name);
|
||||
LLVMTypeRef found_val = *found;
|
||||
map_set(&m->types, type, llvm_type);
|
||||
lb_clone_struct_type(llvm_type, *found);
|
||||
lb_clone_struct_type(llvm_type, found_val);
|
||||
return llvm_type;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body)
|
||||
GB_ASSERT(entity != nullptr);
|
||||
GB_ASSERT(entity->kind == Entity_Procedure);
|
||||
if (!entity->Procedure.is_foreign) {
|
||||
GB_ASSERT(entity->flags & EntityFlag_ProcBodyChecked);
|
||||
GB_ASSERT_MSG(entity->flags & EntityFlag_ProcBodyChecked, "%.*s :: %s", LIT(entity->token.string), type_to_string(entity->type));
|
||||
}
|
||||
|
||||
String link_name = {};
|
||||
@@ -473,6 +473,8 @@ void lb_begin_procedure_body(lbProcedure *p) {
|
||||
}
|
||||
|
||||
lbArgType *arg_type = &ft->args[param_index];
|
||||
defer (param_index += 1);
|
||||
|
||||
if (arg_type->kind == lbArg_Ignore) {
|
||||
continue;
|
||||
} else if (arg_type->kind == lbArg_Direct) {
|
||||
@@ -487,18 +489,19 @@ void lb_begin_procedure_body(lbProcedure *p) {
|
||||
param.type = e->type;
|
||||
|
||||
lbValue ptr = lb_address_from_load_or_generate_local(p, param);
|
||||
GB_ASSERT(LLVMIsAAllocaInst(ptr.value));
|
||||
lb_add_entity(p->module, e, ptr);
|
||||
lb_add_debug_param_variable(p, ptr.value, e->type, e->token, param_index+1);
|
||||
}
|
||||
} else if (arg_type->kind == lbArg_Indirect) {
|
||||
if (e->token.string.len != 0 && !is_blank_ident(e->token.string)) {
|
||||
lbValue ptr = {};
|
||||
ptr.value = LLVMGetParam(p->value, param_offset+param_index);
|
||||
ptr.type = alloc_type_pointer(e->type);
|
||||
|
||||
lb_add_entity(p->module, e, ptr);
|
||||
lb_add_debug_param_variable(p, ptr.value, e->type, e->token, param_index+1);
|
||||
}
|
||||
}
|
||||
param_index += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1991,6 +1991,13 @@ void lb_build_stmt(lbProcedure *p, Ast *node) {
|
||||
out |= StateFlag_no_bounds_check;
|
||||
out &= ~StateFlag_bounds_check;
|
||||
}
|
||||
if (in & StateFlag_no_type_assert) {
|
||||
out |= StateFlag_no_type_assert;
|
||||
out &= ~StateFlag_type_assert;
|
||||
} else if (in & StateFlag_type_assert) {
|
||||
out |= StateFlag_type_assert;
|
||||
out &= ~StateFlag_no_type_assert;
|
||||
}
|
||||
|
||||
p->state_flags = out;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
isize lb_type_info_index(CheckerInfo *info, Type *type, bool err_on_not_found=true) {
|
||||
isize index = type_info_index(info, type, false);
|
||||
auto *set = &info->minimum_dependency_type_info_set;
|
||||
isize index = type_info_index(info, type, err_on_not_found);
|
||||
if (index >= 0) {
|
||||
auto *set = &info->minimum_dependency_type_info_set;
|
||||
for_array(i, set->entries) {
|
||||
if (set->entries[i].ptr == index) {
|
||||
return i+1;
|
||||
}
|
||||
isize i = ptr_entry_index(set, index);
|
||||
if (i >= 0) {
|
||||
return i+1;
|
||||
}
|
||||
}
|
||||
if (err_on_not_found) {
|
||||
@@ -455,7 +454,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
|
||||
case Type_EnumeratedArray: {
|
||||
tag = lb_const_ptr_cast(m, variant_ptr, t_type_info_enumerated_array_ptr);
|
||||
|
||||
LLVMValueRef vals[6] = {
|
||||
LLVMValueRef vals[7] = {
|
||||
lb_get_type_info_ptr(m, t->EnumeratedArray.elem).value,
|
||||
lb_get_type_info_ptr(m, t->EnumeratedArray.index).value,
|
||||
lb_const_int(m, t_int, type_size_of(t->EnumeratedArray.elem)).value,
|
||||
@@ -464,6 +463,8 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
|
||||
// Unions
|
||||
LLVMConstNull(lb_type(m, t_type_info_enum_value)),
|
||||
LLVMConstNull(lb_type(m, t_type_info_enum_value)),
|
||||
|
||||
lb_const_bool(m, t_bool, t->EnumeratedArray.is_sparse).value,
|
||||
};
|
||||
|
||||
lbValue res = {};
|
||||
|
||||
@@ -626,6 +626,12 @@ lbValue lb_emit_union_cast(lbProcedure *p, lbValue value, Type *type, TokenPos p
|
||||
|
||||
lbValue value_ = lb_address_from_load_or_generate_local(p, value);
|
||||
|
||||
if ((p->state_flags & StateFlag_no_type_assert) != 0 && !is_tuple) {
|
||||
// just do a bit cast of the data at the front
|
||||
lbValue ptr = lb_emit_conv(p, value_, alloc_type_pointer(type));
|
||||
return lb_emit_load(p, ptr);
|
||||
}
|
||||
|
||||
lbValue tag = {};
|
||||
lbValue dst_tag = {};
|
||||
lbValue cond = {};
|
||||
@@ -666,23 +672,22 @@ lbValue lb_emit_union_cast(lbProcedure *p, lbValue value, Type *type, TokenPos p
|
||||
lb_start_block(p, end_block);
|
||||
|
||||
if (!is_tuple) {
|
||||
{
|
||||
// NOTE(bill): Panic on invalid conversion
|
||||
Type *dst_type = tuple->Tuple.variables[0]->type;
|
||||
GB_ASSERT((p->state_flags & StateFlag_no_type_assert) == 0);
|
||||
// NOTE(bill): Panic on invalid conversion
|
||||
Type *dst_type = tuple->Tuple.variables[0]->type;
|
||||
|
||||
lbValue ok = lb_emit_load(p, lb_emit_struct_ep(p, v.addr, 1));
|
||||
auto args = array_make<lbValue>(permanent_allocator(), 7);
|
||||
args[0] = ok;
|
||||
lbValue ok = lb_emit_load(p, lb_emit_struct_ep(p, v.addr, 1));
|
||||
auto args = array_make<lbValue>(permanent_allocator(), 7);
|
||||
args[0] = ok;
|
||||
|
||||
args[1] = lb_const_string(m, get_file_path_string(pos.file_id));
|
||||
args[2] = lb_const_int(m, t_i32, pos.line);
|
||||
args[3] = lb_const_int(m, t_i32, pos.column);
|
||||
args[1] = lb_const_string(m, get_file_path_string(pos.file_id));
|
||||
args[2] = lb_const_int(m, t_i32, pos.line);
|
||||
args[3] = lb_const_int(m, t_i32, pos.column);
|
||||
|
||||
args[4] = lb_typeid(m, src_type);
|
||||
args[5] = lb_typeid(m, dst_type);
|
||||
args[6] = lb_emit_conv(p, value_, t_rawptr);
|
||||
lb_emit_runtime_call(p, "type_assertion_check2", args);
|
||||
}
|
||||
args[4] = lb_typeid(m, src_type);
|
||||
args[5] = lb_typeid(m, dst_type);
|
||||
args[6] = lb_emit_conv(p, value_, t_rawptr);
|
||||
lb_emit_runtime_call(p, "type_assertion_check2", args);
|
||||
|
||||
return lb_emit_load(p, lb_emit_struct_ep(p, v.addr, 0));
|
||||
}
|
||||
@@ -706,6 +711,13 @@ lbAddr lb_emit_any_cast_addr(lbProcedure *p, lbValue value, Type *type, TokenPos
|
||||
}
|
||||
Type *dst_type = tuple->Tuple.variables[0]->type;
|
||||
|
||||
if ((p->state_flags & StateFlag_no_type_assert) != 0 && !is_tuple) {
|
||||
// just do a bit cast of the data at the front
|
||||
lbValue ptr = lb_emit_struct_ev(p, value, 0);
|
||||
ptr = lb_emit_conv(p, ptr, alloc_type_pointer(type));
|
||||
return lb_addr(ptr);
|
||||
}
|
||||
|
||||
lbAddr v = lb_add_local_generated(p, tuple, true);
|
||||
|
||||
lbValue dst_typeid = lb_typeid(m, dst_type);
|
||||
@@ -731,7 +743,6 @@ lbAddr lb_emit_any_cast_addr(lbProcedure *p, lbValue value, Type *type, TokenPos
|
||||
|
||||
if (!is_tuple) {
|
||||
// NOTE(bill): Panic on invalid conversion
|
||||
|
||||
lbValue ok = lb_emit_load(p, lb_emit_struct_ep(p, v.addr, 1));
|
||||
auto args = array_make<lbValue>(permanent_allocator(), 7);
|
||||
args[0] = ok;
|
||||
|
||||
+2
-1
@@ -485,7 +485,7 @@ i32 linker_stage(lbGenerator *gen) {
|
||||
// NOTE: If you change this (although this minimum is as low as you can go with Odin working)
|
||||
// make sure to also change the 'mtriple' param passed to 'opt'
|
||||
#if defined(GB_CPU_ARM)
|
||||
" -mmacosx-version-min=11.0.0 "
|
||||
" -mmacosx-version-min=12.0.0 "
|
||||
#else
|
||||
" -mmacosx-version-min=10.8.0 "
|
||||
#endif
|
||||
@@ -1851,6 +1851,7 @@ void print_show_help(String const arg0, String const &command) {
|
||||
print_usage_line(1, " one must contain the program's entry point, all must be in the same package.");
|
||||
} else if (command == "run") {
|
||||
print_usage_line(1, "run same as 'build', but also then runs the newly compiled executable.");
|
||||
print_usage_line(1, " append an empty flag and then the args, '-- <args>', to specify args for the output.");
|
||||
} else if (command == "check") {
|
||||
print_usage_line(1, "check parse and type check .odin file(s)");
|
||||
} else if (command == "test") {
|
||||
|
||||
+123
-7
@@ -183,6 +183,11 @@ Ast *clone_ast(Ast *node) {
|
||||
n->FieldValue.value = clone_ast(n->FieldValue.value);
|
||||
break;
|
||||
|
||||
case Ast_EnumFieldValue:
|
||||
n->EnumFieldValue.name = clone_ast(n->EnumFieldValue.name);
|
||||
n->EnumFieldValue.value = clone_ast(n->EnumFieldValue.value);
|
||||
break;
|
||||
|
||||
case Ast_TernaryIfExpr:
|
||||
n->TernaryIfExpr.x = clone_ast(n->TernaryIfExpr.x);
|
||||
n->TernaryIfExpr.cond = clone_ast(n->TernaryIfExpr.cond);
|
||||
@@ -693,6 +698,16 @@ Ast *ast_field_value(AstFile *f, Ast *field, Ast *value, Token eq) {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Ast *ast_enum_field_value(AstFile *f, Ast *name, Ast *value, CommentGroup *docs, CommentGroup *comment) {
|
||||
Ast *result = alloc_ast_node(f, Ast_EnumFieldValue);
|
||||
result->EnumFieldValue.name = name;
|
||||
result->EnumFieldValue.value = value;
|
||||
result->EnumFieldValue.docs = docs;
|
||||
result->EnumFieldValue.comment = comment;
|
||||
return result;
|
||||
}
|
||||
|
||||
Ast *ast_compound_lit(AstFile *f, Ast *type, Array<Ast *> const &elems, Token open, Token close) {
|
||||
Ast *result = alloc_ast_node(f, Ast_CompoundLit);
|
||||
result->CompoundLit.type = type;
|
||||
@@ -944,7 +959,7 @@ Ast *ast_field(AstFile *f, Array<Ast *> const &names, Ast *type, Ast *default_va
|
||||
result->Field.default_value = default_value;
|
||||
result->Field.flags = flags;
|
||||
result->Field.tag = tag;
|
||||
result->Field.docs = docs;
|
||||
result->Field.docs = docs;
|
||||
result->Field.comment = comment;
|
||||
return result;
|
||||
}
|
||||
@@ -1234,7 +1249,7 @@ CommentGroup *consume_comment_group(AstFile *f, isize n, isize *end_line_) {
|
||||
return comments;
|
||||
}
|
||||
|
||||
void comsume_comment_groups(AstFile *f, Token prev) {
|
||||
void consume_comment_groups(AstFile *f, Token prev) {
|
||||
if (f->curr_token.kind == Token_Comment) {
|
||||
CommentGroup *comment = nullptr;
|
||||
isize end_line = 0;
|
||||
@@ -1278,7 +1293,7 @@ Token advance_token(AstFile *f) {
|
||||
if (ok) {
|
||||
switch (f->curr_token.kind) {
|
||||
case Token_Comment:
|
||||
comsume_comment_groups(f, prev);
|
||||
consume_comment_groups(f, prev);
|
||||
break;
|
||||
case Token_Semicolon:
|
||||
if (ignore_newlines(f) && f->curr_token.string == "\n") {
|
||||
@@ -1689,6 +1704,46 @@ Array<Ast *> parse_element_list(AstFile *f) {
|
||||
|
||||
return elems;
|
||||
}
|
||||
CommentGroup *consume_line_comment(AstFile *f) {
|
||||
CommentGroup *comment = f->line_comment;
|
||||
if (f->line_comment == f->lead_comment) {
|
||||
f->lead_comment = nullptr;
|
||||
}
|
||||
f->line_comment = nullptr;
|
||||
return comment;
|
||||
|
||||
}
|
||||
|
||||
Array<Ast *> parse_enum_field_list(AstFile *f) {
|
||||
auto elems = array_make<Ast *>(heap_allocator());
|
||||
|
||||
while (f->curr_token.kind != Token_CloseBrace &&
|
||||
f->curr_token.kind != Token_EOF) {
|
||||
CommentGroup *docs = f->lead_comment;
|
||||
CommentGroup *comment = nullptr;
|
||||
Ast *name = parse_value(f);
|
||||
Ast *value = nullptr;
|
||||
if (f->curr_token.kind == Token_Eq) {
|
||||
Token eq = expect_token(f, Token_Eq);
|
||||
value = parse_value(f);
|
||||
}
|
||||
|
||||
comment = consume_line_comment(f);
|
||||
|
||||
Ast *elem = ast_enum_field_value(f, name, value, docs, comment);
|
||||
array_add(&elems, elem);
|
||||
|
||||
if (!allow_token(f, Token_Comma)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!elem->EnumFieldValue.comment) {
|
||||
elem->EnumFieldValue.comment = consume_line_comment(f);
|
||||
}
|
||||
}
|
||||
|
||||
return elems;
|
||||
}
|
||||
|
||||
Ast *parse_literal_value(AstFile *f, Ast *type) {
|
||||
Array<Ast *> elems = {};
|
||||
@@ -1793,6 +1848,8 @@ void parse_proc_tags(AstFile *f, u64 *tags) {
|
||||
ELSE_IF_ADD_TAG(require_results)
|
||||
ELSE_IF_ADD_TAG(bounds_check)
|
||||
ELSE_IF_ADD_TAG(no_bounds_check)
|
||||
ELSE_IF_ADD_TAG(type_assert)
|
||||
ELSE_IF_ADD_TAG(no_type_assert)
|
||||
else {
|
||||
syntax_error(tag_expr, "Unknown procedure type tag #%.*s", LIT(tag_name));
|
||||
}
|
||||
@@ -1803,6 +1860,10 @@ void parse_proc_tags(AstFile *f, u64 *tags) {
|
||||
if ((*tags & ProcTag_bounds_check) && (*tags & ProcTag_no_bounds_check)) {
|
||||
syntax_error(f->curr_token, "You cannot apply both #bounds_check and #no_bounds_check to a procedure");
|
||||
}
|
||||
|
||||
if ((*tags & ProcTag_type_assert) && (*tags & ProcTag_no_type_assert)) {
|
||||
syntax_error(f->curr_token, "You cannot apply both #type_assert and #no_type_assert to a procedure");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1950,11 +2011,23 @@ Ast *parse_check_directive_for_statement(Ast *s, Token const &tag_token, u16 sta
|
||||
syntax_error(tag_token, "#bounds_check and #no_bounds_check cannot be applied together");
|
||||
}
|
||||
break;
|
||||
case StateFlag_type_assert:
|
||||
if ((s->state_flags & StateFlag_no_type_assert) != 0) {
|
||||
syntax_error(tag_token, "#type_assert and #no_type_assert cannot be applied together");
|
||||
}
|
||||
break;
|
||||
case StateFlag_no_type_assert:
|
||||
if ((s->state_flags & StateFlag_type_assert) != 0) {
|
||||
syntax_error(tag_token, "#type_assert and #no_type_assert cannot be applied together");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch (state_flag) {
|
||||
case StateFlag_bounds_check:
|
||||
case StateFlag_no_bounds_check:
|
||||
case StateFlag_type_assert:
|
||||
case StateFlag_no_type_assert:
|
||||
switch (s->kind) {
|
||||
case Ast_BlockStmt:
|
||||
case Ast_IfStmt:
|
||||
@@ -2062,6 +2135,22 @@ Ast *parse_operand(AstFile *f, bool lhs) {
|
||||
}
|
||||
return original_type;
|
||||
} else if (name.string == "partial") {
|
||||
Ast *tag = ast_basic_directive(f, token, name);
|
||||
Ast *original_expr = parse_expr(f, lhs);
|
||||
Ast *expr = unparen_expr(original_expr);
|
||||
switch (expr->kind) {
|
||||
case Ast_ArrayType:
|
||||
syntax_error(expr, "#partial has been replaced with #sparse for non-contiguous enumerated array types");
|
||||
break;
|
||||
case Ast_CompoundLit:
|
||||
expr->CompoundLit.tag = tag;
|
||||
break;
|
||||
default:
|
||||
syntax_error(expr, "Expected a compound literal after #%.*s, got %.*s", LIT(name.string), LIT(ast_strings[expr->kind]));
|
||||
break;
|
||||
}
|
||||
return original_expr;
|
||||
} else if (name.string == "sparse") {
|
||||
Ast *tag = ast_basic_directive(f, token, name);
|
||||
Ast *original_type = parse_type(f);
|
||||
Ast *type = unparen_expr(original_type);
|
||||
@@ -2078,6 +2167,12 @@ Ast *parse_operand(AstFile *f, bool lhs) {
|
||||
} else if (name.string == "no_bounds_check") {
|
||||
Ast *operand = parse_expr(f, lhs);
|
||||
return parse_check_directive_for_statement(operand, name, StateFlag_no_bounds_check);
|
||||
} else if (name.string == "type_assert") {
|
||||
Ast *operand = parse_expr(f, lhs);
|
||||
return parse_check_directive_for_statement(operand, name, StateFlag_type_assert);
|
||||
} else if (name.string == "no_type_assert") {
|
||||
Ast *operand = parse_expr(f, lhs);
|
||||
return parse_check_directive_for_statement(operand, name, StateFlag_no_type_assert);
|
||||
} else if (name.string == "relative") {
|
||||
Ast *tag = ast_basic_directive(f, token, name);
|
||||
tag = parse_call_expr(f, tag);
|
||||
@@ -2174,6 +2269,12 @@ Ast *parse_operand(AstFile *f, bool lhs) {
|
||||
if (tags & ProcTag_bounds_check) {
|
||||
body->state_flags |= StateFlag_bounds_check;
|
||||
}
|
||||
if (tags & ProcTag_no_type_assert) {
|
||||
body->state_flags |= StateFlag_no_type_assert;
|
||||
}
|
||||
if (tags & ProcTag_type_assert) {
|
||||
body->state_flags |= StateFlag_type_assert;
|
||||
}
|
||||
|
||||
return ast_proc_lit(f, type, body, tags, where_token, where_clauses);
|
||||
} else if (allow_token(f, Token_do)) {
|
||||
@@ -2449,7 +2550,7 @@ Ast *parse_operand(AstFile *f, bool lhs) {
|
||||
skip_possible_newline_for_literal(f);
|
||||
Token open = expect_token(f, Token_OpenBrace);
|
||||
|
||||
Array<Ast *> values = parse_element_list(f);
|
||||
Array<Ast *> values = parse_enum_field_list(f);
|
||||
Token close = expect_closing_brace_of_field_list(f);
|
||||
|
||||
return ast_enum_type(f, token, base_type, values);
|
||||
@@ -4561,6 +4662,12 @@ Ast *parse_stmt(AstFile *f) {
|
||||
} else if (tag == "no_bounds_check") {
|
||||
s = parse_stmt(f);
|
||||
return parse_check_directive_for_statement(s, name, StateFlag_no_bounds_check);
|
||||
} else if (tag == "type_assert") {
|
||||
s = parse_stmt(f);
|
||||
return parse_check_directive_for_statement(s, name, StateFlag_type_assert);
|
||||
} else if (tag == "no_type_assert") {
|
||||
s = parse_stmt(f);
|
||||
return parse_check_directive_for_statement(s, name, StateFlag_no_type_assert);
|
||||
} else if (tag == "partial") {
|
||||
s = parse_stmt(f);
|
||||
switch (s->kind) {
|
||||
@@ -5398,7 +5505,7 @@ bool parse_file(Parser *p, AstFile *f) {
|
||||
String filepath = f->tokenizer.fullpath;
|
||||
String base_dir = dir_from_path(filepath);
|
||||
if (f->curr_token.kind == Token_Comment) {
|
||||
comsume_comment_groups(f, f->prev_token);
|
||||
consume_comment_groups(f, f->prev_token);
|
||||
}
|
||||
|
||||
CommentGroup *docs = f->lead_comment;
|
||||
@@ -5444,8 +5551,17 @@ bool parse_file(Parser *p, AstFile *f) {
|
||||
if (!parse_build_tag(tok, lc)) {
|
||||
return false;
|
||||
}
|
||||
} else if (lc == "+private") {
|
||||
f->flags |= AstFile_IsPrivate;
|
||||
} else if (string_starts_with(lc, str_lit("+private"))) {
|
||||
f->flags |= AstFile_IsPrivatePkg;
|
||||
String command = string_trim_starts_with(lc, str_lit("+private "));
|
||||
command = string_trim_whitespace(command);
|
||||
if (lc == "+private") {
|
||||
f->flags |= AstFile_IsPrivatePkg;
|
||||
} else if (command == "package") {
|
||||
f->flags |= AstFile_IsPrivatePkg;
|
||||
} else if (command == "file") {
|
||||
f->flags |= AstFile_IsPrivateFile;
|
||||
}
|
||||
} else if (lc == "+lazy") {
|
||||
if (build_context.ignore_lazy) {
|
||||
// Ignore
|
||||
|
||||
+16
-3
@@ -78,9 +78,11 @@ struct ImportedFile {
|
||||
};
|
||||
|
||||
enum AstFileFlag : u32 {
|
||||
AstFile_IsPrivate = 1<<0,
|
||||
AstFile_IsTest = 1<<1,
|
||||
AstFile_IsLazy = 1<<2,
|
||||
AstFile_IsPrivatePkg = 1<<0,
|
||||
AstFile_IsPrivateFile = 1<<1,
|
||||
|
||||
AstFile_IsTest = 1<<3,
|
||||
AstFile_IsLazy = 1<<4,
|
||||
};
|
||||
|
||||
enum AstDelayQueueKind {
|
||||
@@ -226,6 +228,8 @@ enum ProcInlining {
|
||||
enum ProcTag {
|
||||
ProcTag_bounds_check = 1<<0,
|
||||
ProcTag_no_bounds_check = 1<<1,
|
||||
ProcTag_type_assert = 1<<2,
|
||||
ProcTag_no_type_assert = 1<<3,
|
||||
|
||||
ProcTag_require_results = 1<<4,
|
||||
ProcTag_optional_ok = 1<<5,
|
||||
@@ -258,6 +262,8 @@ ProcCallingConvention default_calling_convention(void) {
|
||||
enum StateFlag : u8 {
|
||||
StateFlag_bounds_check = 1<<0,
|
||||
StateFlag_no_bounds_check = 1<<1,
|
||||
StateFlag_type_assert = 1<<2,
|
||||
StateFlag_no_type_assert = 1<<3,
|
||||
|
||||
StateFlag_BeenHandled = 1<<7,
|
||||
};
|
||||
@@ -344,6 +350,7 @@ char const *inline_asm_dialect_strings[InlineAsmDialect_COUNT] = {
|
||||
Slice<Ast *> elems; \
|
||||
Token open, close; \
|
||||
i64 max_count; \
|
||||
Ast *tag; \
|
||||
}) \
|
||||
AST_KIND(_ExprBegin, "", bool) \
|
||||
AST_KIND(BadExpr, "bad expression", struct { Token begin, end; }) \
|
||||
@@ -383,6 +390,12 @@ AST_KIND(_ExprBegin, "", bool) \
|
||||
void *sce_temp_data; \
|
||||
}) \
|
||||
AST_KIND(FieldValue, "field value", struct { Token eq; Ast *field, *value; }) \
|
||||
AST_KIND(EnumFieldValue, "enum field value", struct { \
|
||||
Ast *name; \
|
||||
Ast *value; \
|
||||
CommentGroup *docs; \
|
||||
CommentGroup *comment; \
|
||||
}) \
|
||||
AST_KIND(TernaryIfExpr, "ternary if expression", struct { Ast *x, *cond, *y; }) \
|
||||
AST_KIND(TernaryWhenExpr, "ternary when expression", struct { Ast *x, *cond, *y; }) \
|
||||
AST_KIND(OrElseExpr, "or_else expression", struct { Ast *x; Token token; Ast *y; }) \
|
||||
|
||||
@@ -39,6 +39,7 @@ Token ast_token(Ast *node) {
|
||||
case Ast_SliceExpr: return node->SliceExpr.open;
|
||||
case Ast_Ellipsis: return node->Ellipsis.token;
|
||||
case Ast_FieldValue: return node->FieldValue.eq;
|
||||
case Ast_EnumFieldValue: return ast_token(node->EnumFieldValue.name);
|
||||
case Ast_DerefExpr: return node->DerefExpr.op;
|
||||
case Ast_TernaryIfExpr: return ast_token(node->TernaryIfExpr.x);
|
||||
case Ast_TernaryWhenExpr: return ast_token(node->TernaryWhenExpr.x);
|
||||
@@ -178,6 +179,11 @@ Token ast_end_token(Ast *node) {
|
||||
}
|
||||
return node->Ellipsis.token;
|
||||
case Ast_FieldValue: return ast_end_token(node->FieldValue.value);
|
||||
case Ast_EnumFieldValue:
|
||||
if (node->EnumFieldValue.value) {
|
||||
return ast_end_token(node->EnumFieldValue.value);
|
||||
}
|
||||
return ast_end_token(node->EnumFieldValue.name);
|
||||
case Ast_DerefExpr: return node->DerefExpr.op;
|
||||
case Ast_TernaryIfExpr: return ast_end_token(node->TernaryIfExpr.y);
|
||||
case Ast_TernaryWhenExpr: return ast_end_token(node->TernaryWhenExpr.y);
|
||||
|
||||
@@ -138,6 +138,15 @@ gb_inline bool ptr_set_exists(PtrSet<T> *s, T ptr) {
|
||||
return index != MAP_SENTINEL;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
gb_inline isize ptr_entry_index(PtrSet<T> *s, T ptr) {
|
||||
isize index = ptr_set__find(s, ptr).entry_index;
|
||||
if (index != MAP_SENTINEL) {
|
||||
return index;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Returns true if it already exists
|
||||
template <typename T>
|
||||
T ptr_set_add(PtrSet<T> *s, T ptr) {
|
||||
|
||||
+10
-2
@@ -195,8 +195,6 @@ template <isize N> bool operator > (String const &a, char const (&b)[N]) { retu
|
||||
template <isize N> bool operator <= (String const &a, char const (&b)[N]) { return str_le(a, make_string(cast(u8 *)b, N-1)); }
|
||||
template <isize N> bool operator >= (String const &a, char const (&b)[N]) { return str_ge(a, make_string(cast(u8 *)b, N-1)); }
|
||||
|
||||
|
||||
|
||||
gb_inline bool string_starts_with(String const &s, String const &prefix) {
|
||||
if (prefix.len > s.len) {
|
||||
return false;
|
||||
@@ -230,6 +228,16 @@ gb_inline bool string_ends_with(String const &s, u8 suffix) {
|
||||
return s[s.len-1] == suffix;
|
||||
}
|
||||
|
||||
|
||||
|
||||
gb_inline String string_trim_starts_with(String const &s, String const &prefix) {
|
||||
if (string_starts_with(s, prefix)) {
|
||||
return substring(s, prefix.len, s.len);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
gb_inline isize string_extension_position(String const &str) {
|
||||
isize dot_pos = -1;
|
||||
isize i = str.len;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user