From 29ca6ee420f36381ee0fba6bd409dc51716ab206 Mon Sep 17 00:00:00 2001 From: CiD- Date: Fri, 17 Dec 2021 10:41:49 -0500 Subject: [PATCH 001/117] add zeroing to new region from realloc --- core/os/os.odin | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/core/os/os.odin b/core/os/os.odin index 83158be80..9230bc22c 100644 --- a/core/os/os.odin +++ b/core/os/os.odin @@ -206,11 +206,20 @@ 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 + when ODIN_OS != "windows" { + // NOTE: realloc 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 { From ebdb3ab43a8cdc49cb715ecb6f5fd38522912aa5 Mon Sep 17 00:00:00 2001 From: CiD- Date: Fri, 17 Dec 2021 12:04:05 -0500 Subject: [PATCH 002/117] added notes about _unix_alloc --- core/os/os_darwin.odin | 2 ++ core/os/os_freebsd.odin | 2 ++ core/os/os_linux.odin | 2 ++ 3 files changed, 6 insertions(+) diff --git a/core/os/os_darwin.odin b/core/os/os_darwin.odin index d40c80aeb..6fa43bf09 100644 --- a/core/os/os_darwin.odin +++ b/core/os/os_darwin.odin @@ -530,6 +530,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) { diff --git a/core/os/os_freebsd.odin b/core/os/os_freebsd.odin index e9314b468..82317532d 100644 --- a/core/os/os_freebsd.odin +++ b/core/os/os_freebsd.odin @@ -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)); } diff --git a/core/os/os_linux.odin b/core/os/os_linux.odin index 260a051ce..116fbdba5 100644 --- a/core/os/os_linux.odin +++ b/core/os/os_linux.odin @@ -543,6 +543,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)) } From e5868e32050fc2fe92a50caa743c8123d3fe59d9 Mon Sep 17 00:00:00 2001 From: CiD- Date: Thu, 20 Jan 2022 10:17:47 -0500 Subject: [PATCH 003/117] add zeroing regardless of ODIN_OS --- core/os/os.odin | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/core/os/os.odin b/core/os/os.odin index 9230bc22c..2ebfebd2e 100644 --- a/core/os/os.odin +++ b/core/os/os.odin @@ -212,12 +212,11 @@ heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, } new_memory = aligned_alloc(new_size, new_alignment, p) or_return - when ODIN_OS != "windows" { - // NOTE: realloc 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) - } + + // 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 } From 0e0638362015665411d1454a1a7292de9fe97fed Mon Sep 17 00:00:00 2001 From: Platin21 Date: Sat, 22 Jan 2022 17:34:43 +0100 Subject: [PATCH 004/117] Changed make file so that it allows for multiple LLVM versions instead of a single one on Darwin --- Makefile | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index a7aecbb2d..6acecccc4 100644 --- a/Makefile +++ b/Makefile @@ -11,19 +11,23 @@ ifeq ($(OS), Darwin) ARCH=$(shell uname -m) LLVM_CONFIG=llvm-config - # LLVM Version Setting - LLVM_VERSION_PATTERN="^11\." - LLVM_VERSION="11" ifeq ($(ARCH), arm64) - LLVM_VERSION="13" - LLVM_VERSION_PATTERN="^13" - endif - - ifneq ($(shell llvm-config --version | grep $(LLVM_VERSION_PATTERN)),) - LLVM_CONFIG=llvm-config + ifneq ($(shell llvm-config --version | grep "^13\."),) + LLVM_CONFIG=llvm-config + else + $(error "Requirement: llvm-config must be version llvm 13 for arm64") + endif else - $(error "Requirement: llvm-config must be version $(LLVM_VERSION)") - endif + ifneq ($(shell llvm-config --version | grep "^11\."),) + LLVM_CONFIG=llvm-config + else ifneq ($(shell llvm-config --version | grep "^12\."),) + LLVM_CONFIG=llvm-config + else ifneq ($(shell llvm-config --version | grep "^13\."),) + LLVM_CONFIG=llvm-config + else + $(error "Requirement: llvm-config must be version llvm 11 or 12 or 13 for amd64/x86") + endif + endif LDFLAGS:=$(LDFLAGS) -liconv CFLAGS:=$(CFLAGS) $(shell $(LLVM_CONFIG) --cxxflags --ldflags) From fe6539fad9e83f20d2e45b377e57353dfb6b3a96 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 22 Jan 2022 17:03:55 +0000 Subject: [PATCH 005/117] Add more to examples/all/all_vendor.odin --- examples/all/all_vendor.odin | 45 ++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/examples/all/all_vendor.odin b/examples/all/all_vendor.odin index 777c184f9..f94e092af 100644 --- a/examples/all/all_vendor.odin +++ b/examples/all/all_vendor.odin @@ -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 \ No newline at end of file +_ :: stb_easy_font +_ :: stbi +_ :: stbrp +_ :: stbtt +_ :: stb_vorbis +_ :: vk \ No newline at end of file From fdcb9deaffed29f8b528cb4a8bf30693a7894b2c Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 22 Jan 2022 17:07:24 +0000 Subject: [PATCH 006/117] Generate core and vendor library collection; add package sidebar for the entire collection --- tools/odin-html-docs/odin_html_docs_main.odin | 262 +++++++++++++----- tools/odin-html-docs/style.css | 27 +- 2 files changed, 221 insertions(+), 68 deletions(-) diff --git a/tools/odin-html-docs/odin_html_docs_main.odin b/tools/odin-html-docs/odin_html_docs_main.odin index 7f2e7b59f..e5d46547a 100644 --- a/tools/odin-html-docs/odin_html_docs_main.odin +++ b/tools/odin-html-docs/odin_html_docs_main.odin @@ -8,10 +8,13 @@ import "core:strings" import "core:path/slashpath" import "core:sort" import "core:slice" +import "core:time" GITHUB_LICENSE_URL :: "https://github.com/odin-lang/Odin/tree/master/LICENSE" GITHUB_CORE_URL :: "https://github.com/odin-lang/Odin/tree/master/core" +GITHUB_VENDOR_URL :: "https://github.com/odin-lang/Odin/tree/master/vendor" BASE_CORE_URL :: "/core" +BASE_VENDOR_URL :: "/vendor" header: ^doc.Header files: []doc.File @@ -19,8 +22,18 @@ pkgs: []doc.Pkg entities: []doc.Entity types: []doc.Type -pkgs_to_use: map[string]^doc.Pkg // trimmed path +core_pkgs_to_use: map[string]^doc.Pkg // trimmed path +vendor_pkgs_to_use: map[string]^doc.Pkg // trimmed path pkg_to_path: map[^doc.Pkg]string // trimmed path +pkg_to_collection: map[^doc.Pkg]^Collection + +Collection :: struct { + name: string, + pkgs_to_use: ^map[string]^doc.Pkg, + github_url: string, + base_url: string, + root: ^Dir_Node, +} array :: proc(a: $A/doc.Array($T)) -> []T { return doc.from_array(header, a) @@ -175,6 +188,21 @@ main :: proc() { entities = array(header.entities) types = array(header.types) + core_collection := &Collection{ + "Core", + &core_pkgs_to_use, + GITHUB_CORE_URL, + BASE_CORE_URL, + nil, + } + vendor_collection := &Collection{ + "Vendor", + &vendor_pkgs_to_use, + GITHUB_VENDOR_URL, + BASE_VENDOR_URL, + nil, + } + { fullpaths: [dynamic]string defer delete(fullpaths) @@ -184,25 +212,38 @@ main :: proc() { } path_prefix := common_prefix(fullpaths[:]) - pkgs_to_use = make(map[string]^doc.Pkg) + core_pkgs_to_use = make(map[string]^doc.Pkg) + vendor_pkgs_to_use = make(map[string]^doc.Pkg) fullpath_loop: for fullpath, i in fullpaths { path := strings.trim_prefix(fullpath, path_prefix) - if !strings.has_prefix(path, "core/") { - continue fullpath_loop - } pkg := &pkgs[i+1] if len(array(pkg.entities)) == 0 { continue fullpath_loop } - trimmed_path := strings.trim_prefix(path, "core/") - if strings.has_prefix(trimmed_path, "sys") { - continue fullpath_loop - } - pkgs_to_use[trimmed_path] = pkg + switch { + case strings.has_prefix(path, "core/"): + trimmed_path := strings.trim_prefix(path, "core/") + if strings.has_prefix(trimmed_path, "sys") { + continue fullpath_loop + } + + core_pkgs_to_use[trimmed_path] = pkg + case strings.has_prefix(path, "vendor/"): + trimmed_path := strings.trim_prefix(path, "vendor/") + if strings.contains(trimmed_path, "/bindings") { + continue fullpath_loop + } + vendor_pkgs_to_use[trimmed_path] = pkg + } } - for path, pkg in pkgs_to_use { + for path, pkg in core_pkgs_to_use { pkg_to_path[pkg] = path + pkg_to_collection[pkg] = core_collection + } + for path, pkg in vendor_pkgs_to_use { + pkg_to_path[pkg] = path + pkg_to_collection[pkg] = vendor_collection } } @@ -218,42 +259,53 @@ main :: proc() { os.write_entire_file("index.html", b.buf[:]) } + core_collection.root = generate_directory_tree(core_pkgs_to_use) + vendor_collection.root = generate_directory_tree(vendor_pkgs_to_use) + + generate_packages(&b, core_collection, "core") + generate_packages(&b, vendor_collection, "vendor") +} + +generate_packages :: proc(b: ^strings.Builder, collection: ^Collection, dir: string) { + w := strings.to_writer(b) + { - strings.reset_builder(&b) - write_html_header(w, "core library - pkg.odin-lang.org") - write_core_directory(w) + strings.reset_builder(b) + write_html_header(w, fmt.tprintf("%s library - pkg.odin-lang.org", dir)) + write_collection_directory(w, collection) write_html_footer(w, true) - os.make_directory("core", 0) - os.write_entire_file("core/index.html", b.buf[:]) + os.make_directory(dir, 0) + os.write_entire_file(fmt.tprintf("%s/index.html", dir), b.buf[:]) } - for path, pkg in pkgs_to_use { - strings.reset_builder(&b) + for path, pkg in collection.pkgs_to_use { + strings.reset_builder(b) write_html_header(w, fmt.tprintf("package %s - pkg.odin-lang.org", path)) - write_pkg(w, path, pkg) + write_pkg(w, path, pkg, collection) write_html_footer(w, false) - recursive_make_directory(path, "core") - os.write_entire_file(fmt.tprintf("core/%s/index.html", path), b.buf[:]) + recursive_make_directory(path, dir) + os.write_entire_file(fmt.tprintf("%s/%s/index.html", dir, path), b.buf[:]) } } + +write_home_sidebar :: proc(w: io.Writer) { + fmt.wprintln(w, ``) + fmt.wprintln(w, `
`) + defer fmt.wprintln(w, `
`) + + fmt.wprintln(w, ``) +} + write_home_page :: proc(w: io.Writer) { fmt.wprintln(w, `
`) defer fmt.wprintln(w, `
`) - { - fmt.wprintln(w, ``) - fmt.wprintln(w, `
`) - defer fmt.wprintln(w, `
`) - - fmt.wprintln(w, ``) - - } - + write_home_sidebar(w) fmt.wprintln(w, `
`) defer fmt.wprintln(w, `
`) @@ -270,9 +322,8 @@ write_home_page :: proc(w: io.Writer) { fmt.wprintln(w, ``) fmt.wprintln(w, `
`) - fmt.wprintln(w, `

Vendor Library Collection

`) + fmt.wprintln(w, `

Vendor Library Collection

`) fmt.wprintln(w, `

Documentation for all the packages part of the vendor library collection.

`) - fmt.wprintln(w, `

Coming Soon.

`) fmt.wprintln(w, `
`) @@ -289,7 +340,7 @@ Dir_Node :: struct { children: [dynamic]^Dir_Node, } -generate_directory_tree :: proc() -> (root: ^Dir_Node) { +generate_directory_tree :: proc(pkgs_to_use: map[string]^doc.Pkg) -> (root: ^Dir_Node) { sort_tree :: proc(node: ^Dir_Node) { slice.sort_by_key(node.children[:], proc(node: ^Dir_Node) -> string {return node.name}) for child in node.children { @@ -342,25 +393,46 @@ generate_directory_tree :: proc() -> (root: ^Dir_Node) { return } -write_core_directory :: proc(w: io.Writer) { - root := generate_directory_tree() +write_collection_directory :: proc(w: io.Writer, collection: ^Collection) { + get_line_doc :: proc(pkg: ^doc.Pkg) -> (line_doc: string, ok: bool) { + if pkg == nil { + return + } + line_doc, _, _ = strings.partition(str(pkg.docs), "\n") + line_doc = strings.trim_space(line_doc) + if line_doc == "" { + return + } + switch { + case strings.has_prefix(line_doc, "*"): + return "", false + case strings.has_prefix(line_doc, "Copyright"): + return "", false + } + return line_doc, true + } + fmt.wprintln(w, `
`) defer fmt.wprintln(w, `
`) + + + write_home_sidebar(w) + + fmt.wprintln(w, `
`) + defer fmt.wprintln(w, `
`) { - fmt.wprintln(w, `
`) + fmt.wprintln(w, `
`) fmt.wprintln(w, `
`) - fmt.wprintln(w, "

Core Library Collection

") + fmt.wprintf(w, "

%s Library Collection

\n", collection.name) fmt.wprintln(w, "
    ") fmt.wprintf(w, "
  • License: BSD-3-Clause
  • \n", GITHUB_LICENSE_URL) - fmt.wprintf(w, "
  • Repository: {0:s}
  • \n", GITHUB_CORE_URL) + fmt.wprintf(w, "
  • Repository: {0:s}
  • \n", collection.github_url) fmt.wprintln(w, "
") fmt.wprintln(w, "
") fmt.wprintln(w, "
") fmt.wprintln(w, `
`) } - fmt.wprintln(w, `
`) - defer fmt.wprintln(w, `
`) fmt.wprintln(w, "
") fmt.wprintln(w, `

Directories

`) @@ -370,7 +442,7 @@ write_core_directory :: proc(w: io.Writer) { fmt.wprintln(w, "\t") fmt.wprintln(w, "\t\t") - for dir in root.children { + for dir in collection.root.children { if len(dir.children) != 0 { fmt.wprint(w, `%s`, BASE_CORE_URL, dir.path, dir.name) + fmt.wprintf(w, `%s`, collection.base_url, dir.path, dir.name) } else { fmt.wprintf(w, "%s", dir.name) } io.write_string(w, ``) io.write_string(w, ``) fmt.wprintf(w, "\n") @@ -405,14 +475,16 @@ write_core_directory :: proc(w: io.Writer) { for child in dir.children { assert(child.pkg != nil) fmt.wprintf(w, ``) line_doc, _, _ := strings.partition(str(child.pkg.docs), "\n") line_doc = strings.trim_space(line_doc) io.write_string(w, ``) @@ -606,6 +678,7 @@ write_type :: proc(using writer: ^Type_Writer, type: doc.Type, flags: Write_Type e := entities[type_entities[0]] name := str(type.name) tn_pkg := files[e.pos.file].pkg + collection: Collection // TODO determine this from package if tn_pkg != pkg { fmt.wprintf(w, `%s.`, str(pkgs[tn_pkg].name)) @@ -613,10 +686,10 @@ write_type :: proc(using writer: ^Type_Writer, type: doc.Type, flags: Write_Type if .Private in e.flags { io.write_string(w, name) } else if n := strings.contains_rune(name, '('); n >= 0 { - fmt.wprintf(w, `{1:s}`, pkg_to_path[&pkgs[tn_pkg]], name[:n], BASE_CORE_URL) + fmt.wprintf(w, `{1:s}`, pkg_to_path[&pkgs[tn_pkg]], name[:n], collection.base_url) io.write_string(w, name[n:]) } else { - fmt.wprintf(w, `{1:s}`, pkg_to_path[&pkgs[tn_pkg]], name, BASE_CORE_URL) + fmt.wprintf(w, `{1:s}`, pkg_to_path[&pkgs[tn_pkg]], name, collection.base_url) } case .Generic: name := str(type.name) @@ -870,6 +943,10 @@ write_doc_line :: proc(w: io.Writer, text: string) { } } +write_doc_sidebar :: proc(w: io.Writer) { + +} + write_docs :: proc(w: io.Writer, pkg: ^doc.Pkg, docs: string) { if docs == "" { return @@ -1002,13 +1079,55 @@ write_docs :: proc(w: io.Writer, pkg: ^doc.Pkg, docs: string) { } } -write_pkg :: proc(w: io.Writer, path: string, pkg: ^doc.Pkg) { +write_pkg_sidebar :: proc(w: io.Writer, curr_pkg: ^doc.Pkg, collection: ^Collection) { + + fmt.wprintln(w, ``) + fmt.wprintln(w, `
`) + defer fmt.wprintln(w, `
`) + + fmt.wprintf(w, "

%s Library

\n", collection.name) + + fmt.wprintln(w, `
    `) + defer fmt.wprintln(w, `
`) + + for dir in collection.root.children { + fmt.wprint(w, ``) + if dir.pkg == curr_pkg { + fmt.wprintf(w, `%s`, collection.base_url, dir.path, dir.name) + } else if dir.pkg != nil { + fmt.wprintf(w, `%s`, collection.base_url, dir.path, dir.name) + } else { + fmt.wprintf(w, "%s", dir.name) + } + if len(dir.children) != 0 { + fmt.wprintln(w, "
    ") + defer fmt.wprintln(w, "
\n") + for child in dir.children { + fmt.wprint(w, `
  • `) + defer fmt.wprintln(w, `
  • `) + if child.pkg == curr_pkg { + fmt.wprintf(w, `%s`, collection.base_url, child.path, child.name) + } else if child.pkg != nil { + fmt.wprintf(w, `%s`, collection.base_url, child.path, child.name) + } else { + fmt.wprintf(w, "%s", child.name) + } + } + } + } +} + +write_pkg :: proc(w: io.Writer, path: string, pkg: ^doc.Pkg, collection: ^Collection) { fmt.wprintln(w, `
    `) defer fmt.wprintln(w, `
    `) - fmt.wprintln(w, `
    `) + write_pkg_sidebar(w, pkg, collection) - { // breadcrumbs + fmt.wprintln(w, `
    `) + + if false { // breadcrumbs fmt.wprintln(w, `
    `) defer fmt.wprintln(w, `
    `) @@ -1017,7 +1136,7 @@ write_pkg :: proc(w: io.Writer, path: string, pkg: ^doc.Pkg) { io.write_string(w, "
      \n") defer io.write_string(w, "
    \n") - fmt.wprintf(w, ``, BASE_CORE_URL) + fmt.wprintf(w, ``, collection.base_url) dirs := strings.split(path, "/") for dir, i in dirs { @@ -1032,8 +1151,8 @@ write_pkg :: proc(w: io.Writer, path: string, pkg: ^doc.Pkg) { io.write_string(w, `
  • %s
  • `, GITHUB_CORE_URL, path, filename, filename) + fmt.wprintf(w, `
  • %s
  • `, collection.github_url, path, filename, filename) fmt.wprintln(w) } if any_hidden { @@ -1313,6 +1436,13 @@ write_pkg :: proc(w: io.Writer, path: string, pkg: ^doc.Pkg) { } fmt.wprintln(w, "") + { + fmt.wprintln(w, `

    Generation Information

    `) + now := time.now() + fmt.wprintf(w, "

    Generated with odin version %s (vendor %q) %s_%s @ %v

    \n", ODIN_VERSION, ODIN_VENDOR, ODIN_OS, ODIN_ARCH, now) + } + + fmt.wprintln(w, `
    `) { @@ -1320,7 +1450,7 @@ write_pkg :: proc(w: io.Writer, path: string, pkg: ^doc.Pkg) { fmt.wprintf(w, `
  • %s`, id, text) } - fmt.wprintln(w, `
  • `) - if dir.pkg != nil { - line_doc, _, _ := strings.partition(str(dir.pkg.docs), "\n") - line_doc = strings.trim_space(line_doc) - if line_doc != "" { - write_doc_line(w, line_doc) - } + if line_doc, ok := get_line_doc(dir.pkg); ok { + write_doc_line(w, line_doc) + } else { + io.write_string(w, ` `) } io.write_string(w, `
    `, str(child.pkg.name)) - fmt.wprintf(w, `%s`, BASE_CORE_URL, child.path, child.name) + fmt.wprintf(w, `%s`, collection.base_url, child.path, child.name) io.write_string(w, ``) - if line_doc != "" { + if line_doc, ok := get_line_doc(dir.pkg); ok { write_doc_line(w, line_doc) + } else { + io.write_string(w, ` `) } io.write_string(w, ``) - if line_doc, ok := get_line_doc(dir.pkg); ok { + if line_doc, ok := get_line_doc(child.pkg); ok { write_doc_line(w, line_doc) } else { io.write_string(w, ` `) From 8516e2e7e35ee68e7dab9b03f54be7e906bdb251 Mon Sep 17 00:00:00 2001 From: Platin21 Date: Sat, 22 Jan 2022 20:50:05 +0100 Subject: [PATCH 013/117] Changed match to be arbitrary width (cant do exact match as we never know how much subversion's llvm does) --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 86762af6c..d3d3c6a2d 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ ifeq ($(OS), Darwin) 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_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)))" From a5e16937748afea8682dfd4cf8089d8a34f71fc4 Mon Sep 17 00:00:00 2001 From: Dale Weiler Date: Sun, 23 Jan 2022 03:12:59 -0500 Subject: [PATCH 014/117] Fix fread definition --- core/c/libc/stdio.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/c/libc/stdio.odin b/core/c/libc/stdio.odin index 4a39c22e9..c5c936d16 100644 --- a/core/c/libc/stdio.odin +++ b/core/c/libc/stdio.odin @@ -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 From 0711d4e5fec13a2bf364604eed91f59a3b1f37d1 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 23 Jan 2022 09:53:50 +0000 Subject: [PATCH 015/117] Correct bit_set printing --- tools/odin-html-docs/odin_html_docs_main.odin | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/odin-html-docs/odin_html_docs_main.odin b/tools/odin-html-docs/odin_html_docs_main.odin index ec5103363..cc7f35008 100644 --- a/tools/odin-html-docs/odin_html_docs_main.odin +++ b/tools/odin-html-docs/odin_html_docs_main.odin @@ -886,6 +886,7 @@ write_type :: proc(using writer: ^Type_Writer, type: doc.Type, flags: Write_Type write_type(writer, types[type_types[0]], flags) } if .Underlying_Type in type_flags { + io.write_string(w, "; ") write_type(writer, types[type_types[1]], flags) } io.write_string(w, "]") From 56b4e0a3c393dd0d820b4d82467c33e0e72298a6 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 23 Jan 2022 15:40:46 +0000 Subject: [PATCH 016/117] Fix #1267 --- src/check_expr.cpp | 3 ++- src/checker.cpp | 24 ++++++++++++++++++------ src/error.cpp | 1 + src/llvm_backend_type.cpp | 11 +++++------ src/ptr_set.cpp | 9 +++++++++ 5 files changed, 35 insertions(+), 13 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 8667d8734..99d351753 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -6085,7 +6085,8 @@ CallArgumentError check_polymorphic_record_type(CheckerContext *c, Operand *oper } // NOTE(bill): Add type info the parameters - add_type_info_type(c, o->type); + // TODO(bill, 2022-01-23): why was this line added in the first place? I'm commenting it out for the time being + // add_type_info_type(c, o->type); } { diff --git a/src/checker.cpp b/src/checker.cpp index 63a697072..55a3892e5 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -688,12 +688,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) { @@ -1589,7 +1594,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) { @@ -1613,6 +1618,9 @@ void add_type_info_type_internal(CheckerContext *c, Type *t) { // NOTE(bill): map entries grow linearly and in order ti_index = c->info->type_info_types.count; array_add(&c->info->type_info_types, t); + if (t->kind == Type_Named && t->Named.name == "A") { + gb_printf_err("HERE!\n"); + } } map_set(&c->checker->info.type_info_map, t, ti_index); @@ -1718,6 +1726,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]); } @@ -1741,6 +1750,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); @@ -1934,6 +1944,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]); } @@ -1957,6 +1968,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); @@ -5473,9 +5485,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); @@ -5486,6 +5495,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; diff --git a/src/error.cpp b/src/error.cpp index 1496b4775..b08ff99df 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -403,6 +403,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); } diff --git a/src/llvm_backend_type.cpp b/src/llvm_backend_type.cpp index decb57702..e1332c6f3 100644 --- a/src/llvm_backend_type.cpp +++ b/src/llvm_backend_type.cpp @@ -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) { diff --git a/src/ptr_set.cpp b/src/ptr_set.cpp index ca7df3b53..b45997916 100644 --- a/src/ptr_set.cpp +++ b/src/ptr_set.cpp @@ -138,6 +138,15 @@ gb_inline bool ptr_set_exists(PtrSet *s, T ptr) { return index != MAP_SENTINEL; } +template +gb_inline isize ptr_entry_index(PtrSet *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 T ptr_set_add(PtrSet *s, T ptr) { From 10b97a1b3909161b1c287a9279a9c6d3ee4434bf Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 23 Jan 2022 16:36:37 +0000 Subject: [PATCH 017/117] Update style.css --- tools/odin-html-docs/style.css | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tools/odin-html-docs/style.css b/tools/odin-html-docs/style.css index 13db2f3c2..1b94d54ec 100644 --- a/tools/odin-html-docs/style.css +++ b/tools/odin-html-docs/style.css @@ -144,6 +144,15 @@ details.code-example > summary { } } +#pkg-sidebar { + overflow-x: hidden; +} + +#pkg-sidebar > div { + overflow-x: auto; +} + + #pkg-sidebar ul { list-style-type: none; padding: 0; @@ -160,4 +169,12 @@ details.code-example > summary { #pkg-sidebar a.active { font-style: italic; +} + +#TableOfContents { + overflow-x: hidden; +} + +#TableOfContents > ul { + overflow-x: auto; } \ No newline at end of file From 6ad262c2df2c1a6896e111263b7d2a59307968b2 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 23 Jan 2022 16:52:08 +0000 Subject: [PATCH 018/117] Migrate odin-html-docs to pkg.odin-lang.org repo --- tools/odin-html-docs/footer.txt.html | 45 - tools/odin-html-docs/header-lower.txt.html | 36 - tools/odin-html-docs/header.txt.html | 6 - tools/odin-html-docs/odin_html_docs_main.odin | 1475 ----------------- tools/odin-html-docs/style.css | 180 -- 5 files changed, 1742 deletions(-) delete mode 100644 tools/odin-html-docs/footer.txt.html delete mode 100644 tools/odin-html-docs/header-lower.txt.html delete mode 100644 tools/odin-html-docs/header.txt.html delete mode 100644 tools/odin-html-docs/odin_html_docs_main.odin delete mode 100644 tools/odin-html-docs/style.css diff --git a/tools/odin-html-docs/footer.txt.html b/tools/odin-html-docs/footer.txt.html deleted file mode 100644 index ad73d2834..000000000 --- a/tools/odin-html-docs/footer.txt.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - diff --git a/tools/odin-html-docs/header-lower.txt.html b/tools/odin-html-docs/header-lower.txt.html deleted file mode 100644 index ae5dec861..000000000 --- a/tools/odin-html-docs/header-lower.txt.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - -
    - -
    -
    -
    \ No newline at end of file diff --git a/tools/odin-html-docs/header.txt.html b/tools/odin-html-docs/header.txt.html deleted file mode 100644 index 4bb9036e2..000000000 --- a/tools/odin-html-docs/header.txt.html +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - {0:s} \ No newline at end of file diff --git a/tools/odin-html-docs/odin_html_docs_main.odin b/tools/odin-html-docs/odin_html_docs_main.odin deleted file mode 100644 index cc7f35008..000000000 --- a/tools/odin-html-docs/odin_html_docs_main.odin +++ /dev/null @@ -1,1475 +0,0 @@ -package odin_html_docs - -import doc "core:odin/doc-format" -import "core:fmt" -import "core:io" -import "core:os" -import "core:strings" -import "core:path/slashpath" -import "core:sort" -import "core:slice" -import "core:time" - -GITHUB_LICENSE_URL :: "https://github.com/odin-lang/Odin/tree/master/LICENSE" -GITHUB_CORE_URL :: "https://github.com/odin-lang/Odin/tree/master/core" -GITHUB_VENDOR_URL :: "https://github.com/odin-lang/Odin/tree/master/vendor" -BASE_CORE_URL :: "/core" -BASE_VENDOR_URL :: "/vendor" - -header: ^doc.Header -files: []doc.File -pkgs: []doc.Pkg -entities: []doc.Entity -types: []doc.Type - -core_pkgs_to_use: map[string]^doc.Pkg // trimmed path -vendor_pkgs_to_use: map[string]^doc.Pkg // trimmed path -pkg_to_path: map[^doc.Pkg]string // trimmed path -pkg_to_collection: map[^doc.Pkg]^Collection - -Collection :: struct { - name: string, - pkgs_to_use: ^map[string]^doc.Pkg, - github_url: string, - base_url: string, - root: ^Dir_Node, -} - -array :: proc(a: $A/doc.Array($T)) -> []T { - return doc.from_array(header, a) -} -str :: proc(s: $A/doc.String) -> string { - return doc.from_string(header, s) -} - -errorf :: proc(format: string, args: ..any) -> ! { - fmt.eprintf("%s ", os.args[0]) - fmt.eprintf(format, ..args) - fmt.eprintln() - os.exit(1) -} - -base_type :: proc(t: doc.Type) -> doc.Type { - t := t - for { - if t.kind != .Named { - break - } - t = types[array(t.types)[0]] - } - return t -} - -is_type_untyped :: proc(type: doc.Type) -> bool { - if type.kind == .Basic { - flags := transmute(doc.Type_Flags_Basic)type.flags - return .Untyped in flags - } - return false -} - -common_prefix :: proc(strs: []string) -> string { - if len(strs) == 0 { - return "" - } - n := max(int) - for str in strs { - n = min(n, len(str)) - } - - prefix := strs[0][:n] - for str in strs[1:] { - for len(prefix) != 0 && str[:len(prefix)] != prefix { - prefix = prefix[:len(prefix)-1] - } - if len(prefix) == 0 { - break - } - } - return prefix -} - -recursive_make_directory :: proc(path: string, prefix := "") { - head, _, tail := strings.partition(path, "/") - path_to_make := head - if prefix != "" { - path_to_make = fmt.tprintf("%s/%s", prefix, head) - } - os.make_directory(path_to_make, 0) - if tail != "" { - recursive_make_directory(tail, path_to_make) - } -} - - -write_html_header :: proc(w: io.Writer, title: string) { - fmt.wprintf(w, string(#load("header.txt.html")), title) - io.write(w, #load("header-lower.txt.html")) -} - -write_html_footer :: proc(w: io.Writer, include_directory_js: bool) { - fmt.wprintf(w, "\n") - - io.write(w, #load("footer.txt.html")) - - if false && include_directory_js { - io.write_string(w, ` -`) - } - - fmt.wprintf(w, "\n\n") -} - -main :: proc() { - if len(os.args) != 2 { - errorf("expected 1 .odin-doc file") - } - data, ok := os.read_entire_file(os.args[1]) - if !ok { - errorf("unable to read file:", os.args[1]) - } - err: doc.Reader_Error - header, err = doc.read_from_bytes(data) - switch err { - case .None: - case .Header_Too_Small: - errorf("file is too small for the file format") - case .Invalid_Magic: - errorf("invalid magic for the file format") - case .Data_Too_Small: - errorf("data is too small for the file format") - case .Invalid_Version: - errorf("invalid file format version") - } - files = array(header.files) - pkgs = array(header.pkgs) - entities = array(header.entities) - types = array(header.types) - - core_collection := &Collection{ - "Core", - &core_pkgs_to_use, - GITHUB_CORE_URL, - BASE_CORE_URL, - nil, - } - vendor_collection := &Collection{ - "Vendor", - &vendor_pkgs_to_use, - GITHUB_VENDOR_URL, - BASE_VENDOR_URL, - nil, - } - - { - fullpaths: [dynamic]string - defer delete(fullpaths) - - for pkg in pkgs[1:] { - append(&fullpaths, str(pkg.fullpath)) - } - path_prefix := common_prefix(fullpaths[:]) - - core_pkgs_to_use = make(map[string]^doc.Pkg) - vendor_pkgs_to_use = make(map[string]^doc.Pkg) - fullpath_loop: for fullpath, i in fullpaths { - path := strings.trim_prefix(fullpath, path_prefix) - pkg := &pkgs[i+1] - if len(array(pkg.entities)) == 0 { - continue fullpath_loop - } - - switch { - case strings.has_prefix(path, "core/"): - trimmed_path := strings.trim_prefix(path, "core/") - if strings.has_prefix(trimmed_path, "sys") { - continue fullpath_loop - } - - core_pkgs_to_use[trimmed_path] = pkg - case strings.has_prefix(path, "vendor/"): - trimmed_path := strings.trim_prefix(path, "vendor/") - if strings.contains(trimmed_path, "/bindings") { - continue fullpath_loop - } - vendor_pkgs_to_use[trimmed_path] = pkg - } - } - for path, pkg in core_pkgs_to_use { - pkg_to_path[pkg] = path - pkg_to_collection[pkg] = core_collection - } - for path, pkg in vendor_pkgs_to_use { - pkg_to_path[pkg] = path - pkg_to_collection[pkg] = vendor_collection - } - } - - b := strings.make_builder() - defer strings.destroy_builder(&b) - w := strings.to_writer(&b) - - { - strings.reset_builder(&b) - write_html_header(w, "Packages - pkg.odin-lang.org") - write_home_page(w) - write_html_footer(w, true) - os.write_entire_file("index.html", b.buf[:]) - } - - core_collection.root = generate_directory_tree(core_pkgs_to_use) - vendor_collection.root = generate_directory_tree(vendor_pkgs_to_use) - - generate_packages(&b, core_collection, "core") - generate_packages(&b, vendor_collection, "vendor") -} - -generate_packages :: proc(b: ^strings.Builder, collection: ^Collection, dir: string) { - w := strings.to_writer(b) - - { - strings.reset_builder(b) - write_html_header(w, fmt.tprintf("%s library - pkg.odin-lang.org", dir)) - write_collection_directory(w, collection) - write_html_footer(w, true) - os.make_directory(dir, 0) - os.write_entire_file(fmt.tprintf("%s/index.html", dir), b.buf[:]) - } - - for path, pkg in collection.pkgs_to_use { - strings.reset_builder(b) - write_html_header(w, fmt.tprintf("package %s - pkg.odin-lang.org", path)) - write_pkg(w, path, pkg, collection) - write_html_footer(w, false) - recursive_make_directory(path, dir) - os.write_entire_file(fmt.tprintf("%s/%s/index.html", dir, path), b.buf[:]) - } -} - - -write_home_sidebar :: proc(w: io.Writer) { - fmt.wprintln(w, ``) - fmt.wprintln(w, `
    `) - defer fmt.wprintln(w, `
    `) - - fmt.wprintln(w, ``) -} - -write_home_page :: proc(w: io.Writer) { - fmt.wprintln(w, `
    `) - defer fmt.wprintln(w, `
    `) - - write_home_sidebar(w) - - fmt.wprintln(w, `
    `) - defer fmt.wprintln(w, `
    `) - - fmt.wprintln(w, "
    ") - fmt.wprintln(w, "

    Odin Packages

    ") - fmt.wprintln(w, "
    ") - fmt.wprintln(w, "
    ") - defer fmt.wprintln(w, "
    ") - - fmt.wprintln(w, `
    `) - fmt.wprintln(w, `

    Core Library Collection

    `) - fmt.wprintln(w, `

    Documentation for all the packages part of the core library collection.

    `) - fmt.wprintln(w, `
    `) - - fmt.wprintln(w, `
    `) - fmt.wprintln(w, `

    Vendor Library Collection

    `) - fmt.wprintln(w, `

    Documentation for all the packages part of the vendor library collection.

    `) - fmt.wprintln(w, `
    `) - - - -} - - - -Dir_Node :: struct { - dir: string, - path: string, - name: string, - pkg: ^doc.Pkg, - children: [dynamic]^Dir_Node, -} - -generate_directory_tree :: proc(pkgs_to_use: map[string]^doc.Pkg) -> (root: ^Dir_Node) { - sort_tree :: proc(node: ^Dir_Node) { - slice.sort_by_key(node.children[:], proc(node: ^Dir_Node) -> string {return node.name}) - for child in node.children { - sort_tree(child) - } - } - root = new(Dir_Node) - root.children = make([dynamic]^Dir_Node) - children := make([dynamic]^Dir_Node) - for path, pkg in pkgs_to_use { - dir, _, inner := strings.partition(path, "/") - if inner == "" { - node := new_clone(Dir_Node{ - dir = dir, - name = dir, - path = path, - pkg = pkg, - }) - append(&root.children, node) - } else { - node := new_clone(Dir_Node{ - dir = dir, - name = inner, - path = path, - pkg = pkg, - }) - append(&children, node) - } - } - child_loop: for child in children { - dir, _, inner := strings.partition(child.path, "/") - for node in root.children { - if node.dir == dir { - append(&node.children, child) - continue child_loop - } - } - parent := new_clone(Dir_Node{ - dir = dir, - name = dir, - path = dir, - pkg = nil, - }) - append(&root.children, parent) - append(&parent.children, child) - } - - sort_tree(root) - - return -} - -write_collection_directory :: proc(w: io.Writer, collection: ^Collection) { - get_line_doc :: proc(pkg: ^doc.Pkg) -> (line_doc: string, ok: bool) { - if pkg == nil { - return - } - line_doc, _, _ = strings.partition(str(pkg.docs), "\n") - line_doc = strings.trim_space(line_doc) - if line_doc == "" { - return - } - switch { - case strings.has_prefix(line_doc, "*"): - return "", false - case strings.has_prefix(line_doc, "Copyright"): - return "", false - } - return line_doc, true - } - - - fmt.wprintln(w, `
    `) - defer fmt.wprintln(w, `
    `) - - - write_home_sidebar(w) - - fmt.wprintln(w, `
    `) - defer fmt.wprintln(w, `
    `) - { - fmt.wprintln(w, `
    `) - fmt.wprintln(w, `
    `) - fmt.wprintf(w, "

    %s Library Collection

    \n", collection.name) - fmt.wprintln(w, "
      ") - fmt.wprintf(w, "
    • License: BSD-3-Clause
    • \n", GITHUB_LICENSE_URL) - fmt.wprintf(w, "
    • Repository: {0:s}
    • \n", collection.github_url) - fmt.wprintln(w, "
    ") - fmt.wprintln(w, "
    ") - fmt.wprintln(w, "
    ") - fmt.wprintln(w, `
    `) - } - - fmt.wprintln(w, "
    ") - fmt.wprintln(w, `

    Directories

    `) - fmt.wprintln(w, "
    ") - - fmt.wprintln(w, "
    ") - fmt.wprintln(w, "\t") - fmt.wprintln(w, "\t\t") - - for dir in collection.root.children { - if len(dir.children) != 0 { - fmt.wprint(w, ``) - io.write_string(w, ``) - fmt.wprintf(w, "\n") - - for child in dir.children { - assert(child.pkg != nil) - fmt.wprintf(w, ``) - - line_doc, _, _ := strings.partition(str(child.pkg.docs), "\n") - line_doc = strings.trim_space(line_doc) - io.write_string(w, ``) - - fmt.wprintf(w, "") - fmt.wprintf(w, "\n") - } - } - - fmt.wprintln(w, "\t\t") - fmt.wprintln(w, "\t
    `, dir.dir) - } else { - fmt.wprintf(w, `
    `, dir.dir) - } - - if dir.pkg != nil { - fmt.wprintf(w, `%s`, collection.base_url, dir.path, dir.name) - } else { - fmt.wprintf(w, "%s", dir.name) - } - io.write_string(w, ``) - if line_doc, ok := get_line_doc(dir.pkg); ok { - write_doc_line(w, line_doc) - } else { - io.write_string(w, ` `) - } - io.write_string(w, `
    `, str(child.pkg.name)) - fmt.wprintf(w, `%s`, collection.base_url, child.path, child.name) - io.write_string(w, ``) - if line_doc, ok := get_line_doc(child.pkg); ok { - write_doc_line(w, line_doc) - } else { - io.write_string(w, ` `) - } - io.write_string(w, `
    ") - fmt.wprintln(w, "
    ") -} - -is_entity_blank :: proc(e: doc.Entity_Index) -> bool { - name := str(entities[e].name) - return name == "" -} - -write_where_clauses :: proc(w: io.Writer, where_clauses: []doc.String) { - if len(where_clauses) != 0 { - io.write_string(w, " where ") - for clause, i in where_clauses { - if i > 0 { - io.write_string(w, ", ") - } - io.write_string(w, str(clause)) - } - } -} - - -Write_Type_Flag :: enum { - Is_Results, - Variadic, - Allow_Indent, - Poly_Names, -} -Write_Type_Flags :: distinct bit_set[Write_Type_Flag] -Type_Writer :: struct { - w: io.Writer, - pkg: doc.Pkg_Index, - indent: int, - generic_scope: map[string]bool, -} - -write_type :: proc(using writer: ^Type_Writer, type: doc.Type, flags: Write_Type_Flags) { - write_param_entity :: proc(using writer: ^Type_Writer, e, next_entity: ^doc.Entity, flags: Write_Type_Flags, name_width := 0) { - name := str(e.name) - - write_padding :: proc(w: io.Writer, name: string, name_width: int) { - for _ in 0..`, BASE_CORE_URL) - io.write_string(w, init_string) - io.write_string(w, ``) - case strings.has_prefix(init_string, "context."): - io.write_string(w, name) - io.write_string(w, " := ") - fmt.wprintf(w, ``, BASE_CORE_URL) - io.write_string(w, init_string) - io.write_string(w, ``) - case: - the_type := types[e.type] - type_flags := flags - {.Is_Results} - if .Param_Ellipsis in e.flags { - type_flags += {.Variadic} - } - - #partial switch e.kind { - case .Constant: - assert(name != "") - io.write_byte(w, '$') - io.write_string(w, name) - if name != "" && init_string == "" && next_entity != nil && e.field_group_index >= 0 { - if e.field_group_index == next_entity.field_group_index && e.type == next_entity.type { - return - } - } - - generic_scope[name] = true - if !is_type_untyped(the_type) { - io.write_string(w, ": ") - write_padding(w, name, name_width) - write_type(writer, the_type, type_flags) - io.write_string(w, " = ") - io.write_string(w, init_string) - } else { - io.write_string(w, " := ") - io.write_string(w, init_string) - } - return - - case .Variable: - if name != "" && init_string == "" && next_entity != nil && e.field_group_index >= 0 { - if e.field_group_index == next_entity.field_group_index && e.type == next_entity.type { - io.write_string(w, name) - return - } - } - - if name != "" { - io.write_string(w, name) - io.write_string(w, ": ") - write_padding(w, name, name_width) - } - write_type(writer, the_type, type_flags) - case .Type_Name: - io.write_byte(w, '$') - io.write_string(w, name) - generic_scope[name] = true - io.write_string(w, ": ") - write_padding(w, name, name_width) - if the_type.kind == .Generic { - io.write_string(w, "typeid") - if ts := array(the_type.types); len(ts) == 1 { - io.write_byte(w, '/') - write_type(writer, types[ts[0]], type_flags) - } - } else { - write_type(writer, the_type, type_flags) - } - } - - if init_string != "" { - io.write_string(w, " = ") - io.write_string(w, init_string) - } - } - } - write_poly_params :: proc(using writer: ^Type_Writer, type: doc.Type, flags: Write_Type_Flags) { - if type.polymorphic_params != 0 { - io.write_byte(w, '(') - write_type(writer, types[type.polymorphic_params], flags+{.Poly_Names}) - io.write_byte(w, ')') - } - - write_where_clauses(w, array(type.where_clauses)) - } - do_indent :: proc(using writer: ^Type_Writer, flags: Write_Type_Flags) { - if .Allow_Indent not_in flags { - return - } - for _ in 0.. (name_width: int) { - for entity_index in type_entities { - e := &entities[entity_index] - name := str(e.name) - name_width = max(len(name), name_width) - } - return - } - - - type_entities := array(type.entities) - type_types := array(type.types) - switch type.kind { - case .Invalid: - // ignore - case .Basic: - type_flags := transmute(doc.Type_Flags_Basic)type.flags - if is_type_untyped(type) { - io.write_string(w, str(type.name)) - } else { - fmt.wprintf(w, `%s`, str(type.name)) - } - case .Named: - e := entities[type_entities[0]] - name := str(type.name) - tn_pkg := files[e.pos.file].pkg - collection: Collection // TODO determine this from package - - if tn_pkg != pkg { - fmt.wprintf(w, `%s.`, str(pkgs[tn_pkg].name)) - } - if .Private in e.flags { - io.write_string(w, name) - } else if n := strings.contains_rune(name, '('); n >= 0 { - fmt.wprintf(w, `{1:s}`, pkg_to_path[&pkgs[tn_pkg]], name[:n], collection.base_url) - io.write_string(w, name[n:]) - } else { - fmt.wprintf(w, `{1:s}`, pkg_to_path[&pkgs[tn_pkg]], name, collection.base_url) - } - case .Generic: - name := str(type.name) - if name not_in generic_scope { - io.write_byte(w, '$') - } - io.write_string(w, name) - if name not_in generic_scope && len(array(type.types)) == 1 { - io.write_byte(w, '/') - write_type(writer, types[type_types[0]], flags) - } - case .Pointer: - io.write_byte(w, '^') - write_type(writer, types[type_types[0]], flags) - case .Array: - assert(type.elem_count_len == 1) - io.write_byte(w, '[') - io.write_uint(w, uint(type.elem_counts[0])) - io.write_byte(w, ']') - write_type(writer, types[type_types[0]], flags) - case .Enumerated_Array: - io.write_byte(w, '[') - write_type(writer, types[type_types[0]], flags) - io.write_byte(w, ']') - write_type(writer, types[type_types[1]], flags) - case .Slice: - if .Variadic in flags { - io.write_string(w, "..") - } else { - io.write_string(w, "[]") - } - write_type(writer, types[type_types[0]], flags - {.Variadic}) - case .Dynamic_Array: - io.write_string(w, "[dynamic]") - write_type(writer, types[type_types[0]], flags) - case .Map: - io.write_string(w, "map[") - write_type(writer, types[type_types[0]], flags) - io.write_byte(w, ']') - write_type(writer, types[type_types[1]], flags) - case .Struct: - type_flags := transmute(doc.Type_Flags_Struct)type.flags - io.write_string(w, "struct") - write_poly_params(writer, type, flags) - if .Packed in type_flags { io.write_string(w, " #packed") } - if .Raw_Union in type_flags { io.write_string(w, " #raw_union") } - if custom_align := str(type.custom_align); custom_align != "" { - io.write_string(w, " #align") - io.write_string(w, custom_align) - } - io.write_string(w, " {") - - tags := array(type.tags) - - if len(type_entities) != 0 { - do_newline(writer, flags) - indent += 1 - name_width := calc_name_width(type_entities) - - for entity_index, i in type_entities { - e := &entities[entity_index] - next_entity: ^doc.Entity = nil - if i+1 < len(type_entities) { - next_entity = &entities[type_entities[i+1]] - } - do_indent(writer, flags) - write_param_entity(writer, e, next_entity, flags, name_width) - - if tag := str(tags[i]); tag != "" { - io.write_byte(w, ' ') - io.write_quoted_string(w, tag) - } - - io.write_byte(w, ',') - do_newline(writer, flags) - } - indent -= 1 - do_indent(writer, flags) - } - io.write_string(w, "}") - case .Union: - type_flags := transmute(doc.Type_Flags_Union)type.flags - io.write_string(w, "union") - write_poly_params(writer, type, flags) - if .No_Nil in type_flags { io.write_string(w, " #no_nil") } - if .Maybe in type_flags { io.write_string(w, " #maybe") } - if custom_align := str(type.custom_align); custom_align != "" { - io.write_string(w, " #align") - io.write_string(w, custom_align) - } - io.write_string(w, " {") - if len(type_types) > 1 { - do_newline(writer, flags) - indent += 1 - for type_index in type_types { - do_indent(writer, flags) - write_type(writer, types[type_index], flags) - io.write_string(w, ", ") - do_newline(writer, flags) - } - indent -= 1 - do_indent(writer, flags) - } - io.write_string(w, "}") - case .Enum: - io.write_string(w, "enum") - if len(type_types) != 0 { - io.write_byte(w, ' ') - write_type(writer, types[type_types[0]], flags) - } - io.write_string(w, " {") - do_newline(writer, flags) - indent += 1 - - name_width := calc_name_width(type_entities) - - for entity_index in type_entities { - e := &entities[entity_index] - - name := str(e.name) - do_indent(writer, flags) - io.write_string(w, name) - - if init_string := str(e.init_string); init_string != "" { - for _ in 0.. 1 || !is_entity_blank(type_entities[0])) - if require_parens { io.write_byte(w, '(') } - for entity_index, i in type_entities { - if i > 0 { - io.write_string(w, ", ") - } - e := &entities[entity_index] - next_entity: ^doc.Entity = nil - if i+1 < len(type_entities) { - next_entity = &entities[type_entities[i+1]] - } - write_param_entity(writer, e, next_entity, flags) - } - if require_parens { io.write_byte(w, ')') } - - case .Proc: - type_flags := transmute(doc.Type_Flags_Proc)type.flags - io.write_string(w, "proc") - cc := str(type.calling_convention) - if cc != "" { - io.write_byte(w, ' ') - io.write_quoted_string(w, cc) - io.write_byte(w, ' ') - } - params := array(type.types)[0] - results := array(type.types)[1] - io.write_byte(w, '(') - write_type(writer, types[params], flags) - io.write_byte(w, ')') - if results != 0 { - assert(.Diverging not_in type_flags) - io.write_string(w, " -> ") - write_type(writer, types[results], flags+{.Is_Results}) - } - if .Diverging in type_flags { - io.write_string(w, " -> !") - } - if .Optional_Ok in type_flags { - io.write_string(w, " #optional_ok") - } - - case .Bit_Set: - type_flags := transmute(doc.Type_Flags_Bit_Set)type.flags - io.write_string(w, "bit_set[") - if .Op_Lt in type_flags { - io.write_uint(w, uint(type.elem_counts[0])) - io.write_string(w, "..<") - io.write_uint(w, uint(type.elem_counts[1])) - } else if .Op_Lt_Eq in type_flags { - io.write_uint(w, uint(type.elem_counts[0])) - io.write_string(w, "..=") - io.write_uint(w, uint(type.elem_counts[1])) - } else { - write_type(writer, types[type_types[0]], flags) - } - if .Underlying_Type in type_flags { - io.write_string(w, "; ") - write_type(writer, types[type_types[1]], flags) - } - io.write_string(w, "]") - case .Simd_Vector: - io.write_string(w, "#simd[") - io.write_uint(w, uint(type.elem_counts[0])) - io.write_byte(w, ']') - case .SOA_Struct_Fixed: - io.write_string(w, "#soa[") - io.write_uint(w, uint(type.elem_counts[0])) - io.write_byte(w, ']') - case .SOA_Struct_Slice: - io.write_string(w, "#soa[]") - case .SOA_Struct_Dynamic: - io.write_string(w, "#soa[dynamic]") - case .Relative_Pointer: - io.write_string(w, "#relative(") - write_type(writer, types[type_types[1]], flags) - io.write_string(w, ") ") - write_type(writer, types[type_types[0]], flags) - case .Relative_Slice: - io.write_string(w, "#relative(") - write_type(writer, types[type_types[1]], flags) - io.write_string(w, ") ") - write_type(writer, types[type_types[0]], flags) - case .Multi_Pointer: - io.write_string(w, "[^]") - write_type(writer, types[type_types[0]], flags) - case .Matrix: - io.write_string(w, "matrix[") - io.write_uint(w, uint(type.elem_counts[0])) - io.write_string(w, ", ") - io.write_uint(w, uint(type.elem_counts[1])) - io.write_string(w, "]") - write_type(writer, types[type_types[0]], flags) - } -} - -write_doc_line :: proc(w: io.Writer, text: string) { - text := text - for len(text) != 0 { - if strings.count(text, "`") >= 2 { - n := strings.index_byte(text, '`') - io.write_string(w, text[:n]) - io.write_string(w, "") - remaining := text[n+1:] - m := strings.index_byte(remaining, '`') - io.write_string(w, remaining[:m]) - io.write_string(w, "") - text = remaining[m+1:] - } else { - io.write_string(w, text) - return - } - } -} - -write_doc_sidebar :: proc(w: io.Writer) { - -} - -write_docs :: proc(w: io.Writer, pkg: ^doc.Pkg, docs: string) { - if docs == "" { - return - } - Block_Kind :: enum { - Paragraph, - Code, - } - Block :: struct { - kind: Block_Kind, - lines: []string, - } - - lines: [dynamic]string - it := docs - for line_ in strings.split_iterator(&it, "\n") { - line := strings.trim_right_space(line_) - append(&lines, line) - } - - curr_block_kind := Block_Kind.Paragraph - start := 0 - blocks: [dynamic]Block - - for line, i in lines { - text := strings.trim_space(line) - switch curr_block_kind { - case .Paragraph: - if strings.has_prefix(line, "\t") { - if i-start > 0 { - append(&blocks, Block{curr_block_kind, lines[start:i]}) - } - curr_block_kind, start = .Code, i - } else if text == "" { - if i-start > 0 { - append(&blocks, Block{curr_block_kind, lines[start:i]}) - } - start = i - } - case .Code: - if text == "" || strings.has_prefix(line, "\t") { - continue - } - - if i-start > 0 { - append(&blocks, Block{curr_block_kind, lines[start:i]}) - } - curr_block_kind, start = .Paragraph, i - } - } - if start < len(lines) { - if len(lines)-start > 0 { - append(&blocks, Block{curr_block_kind, lines[start:]}) - } - } - - for block in &blocks { - trim_amount := 0 - for trim_amount = 0; trim_amount < len(block.lines); trim_amount += 1 { - line := block.lines[trim_amount] - if strings.trim_space(line) != "" { - break - } - } - block.lines = block.lines[trim_amount:] - } - - for block, i in blocks { - if len(block.lines) == 0 { - continue - } - prev_line := "" - if i > 0 { - prev_lines := blocks[i-1].lines - if len(prev_lines) > 0 { - prev_line = prev_lines[len(prev_lines)-1] - } - } - prev_line = strings.trim_space(prev_line) - - lines := block.lines[:] - - end_line := block.lines[len(lines)-1] - if block.kind == .Paragraph && i+1 < len(blocks) { - if strings.has_prefix(end_line, "Example:") && blocks[i+1].kind == .Code { - lines = lines[:len(lines)-1] - } - } - - switch block.kind { - case .Paragraph: - io.write_string(w, "

    ") - for line, line_idx in lines { - if line_idx > 0 { - io.write_string(w, "\n") - } - io.write_string(w, line) - } - io.write_string(w, "

    \n") - case .Code: - all_blank := len(lines) > 0 - for line in lines { - if strings.trim_space(line) != "" { - all_blank = false - } - } - if all_blank { - continue - } - - if strings.has_prefix(prev_line, "Example:") { - io.write_string(w, "
    \n") - defer io.write_string(w, "
    \n") - io.write_string(w, "Example:\n") - io.write_string(w, `
    `)
    -				for line in lines {
    -					io.write_string(w, strings.trim_prefix(line, "\t"))
    -					io.write_string(w, "\n")
    -				}
    -				io.write_string(w, "
    \n") - } else { - io.write_string(w, "
    ")
    -				for line in lines {
    -					io.write_string(w, strings.trim_prefix(line, "\t"))
    -					io.write_string(w, "\n")
    -				}
    -				io.write_string(w, "
    \n") - } - } - } -} - -write_pkg_sidebar :: proc(w: io.Writer, curr_pkg: ^doc.Pkg, collection: ^Collection) { - - fmt.wprintln(w, ``) - fmt.wprintln(w, `
    `) - defer fmt.wprintln(w, `
    `) - - fmt.wprintf(w, "

    %s Library

    \n", collection.name) - - fmt.wprintln(w, `
      `) - defer fmt.wprintln(w, `
    `) - - for dir in collection.root.children { - fmt.wprint(w, ``) - if dir.pkg == curr_pkg { - fmt.wprintf(w, `%s`, collection.base_url, dir.path, dir.name) - } else if dir.pkg != nil { - fmt.wprintf(w, `%s`, collection.base_url, dir.path, dir.name) - } else { - fmt.wprintf(w, "%s", dir.name) - } - if len(dir.children) != 0 { - fmt.wprintln(w, "
      ") - defer fmt.wprintln(w, "
    \n") - for child in dir.children { - fmt.wprint(w, `
  • `) - defer fmt.wprintln(w, `
  • `) - if child.pkg == curr_pkg { - fmt.wprintf(w, `%s`, collection.base_url, child.path, child.name) - } else if child.pkg != nil { - fmt.wprintf(w, `%s`, collection.base_url, child.path, child.name) - } else { - fmt.wprintf(w, "%s", child.name) - } - } - } - } -} - -write_pkg :: proc(w: io.Writer, path: string, pkg: ^doc.Pkg, collection: ^Collection) { - fmt.wprintln(w, `
    `) - defer fmt.wprintln(w, `
    `) - - write_pkg_sidebar(w, pkg, collection) - - fmt.wprintln(w, `
    `) - - if false { // breadcrumbs - fmt.wprintln(w, `
    `) - defer fmt.wprintln(w, `
    `) - - fmt.wprintln(w, ``) - io.write_string(w, "
      \n") - defer io.write_string(w, "
    \n") - - fmt.wprintf(w, ``, collection.base_url) - - dirs := strings.split(path, "/") - for dir, i in dirs { - url := strings.join(dirs[:i+1], "/") - short_path := strings.join(dirs[1:i+1], "/") - - a_class := "breadcrumb-link" - is_curr := i+1 == len(dirs) - if is_curr { - io.write_string(w, `\n") - } - } - - - fmt.wprintf(w, "

    package core:%s

    \n", path) - overview_docs := strings.trim_space(str(pkg.docs)) - if overview_docs != "" { - fmt.wprintln(w, "

    Overview

    ") - fmt.wprintln(w, "
    ") - defer fmt.wprintln(w, "
    ") - - write_docs(w, pkg, overview_docs) - } - - fmt.wprintln(w, `

    Index

    `) - fmt.wprintln(w, `
    `) - pkg_procs: [dynamic]^doc.Entity - pkg_proc_groups: [dynamic]^doc.Entity - pkg_types: [dynamic]^doc.Entity - pkg_vars: [dynamic]^doc.Entity - pkg_consts: [dynamic]^doc.Entity - - for entity_index in array(pkg.entities) { - e := &entities[entity_index] - name := str(e.name) - if name == "" || name[0] == '_' { - continue - } - switch e.kind { - case .Invalid, .Import_Name, .Library_Name: - // ignore - case .Constant: append(&pkg_consts, e) - case .Variable: append(&pkg_vars, e) - case .Type_Name: append(&pkg_types, e) - case .Procedure: append(&pkg_procs, e) - case .Proc_Group: append(&pkg_proc_groups, e) - } - } - - entity_key :: proc(e: ^doc.Entity) -> string { - return str(e.name) - } - - slice.sort_by_key(pkg_procs[:], entity_key) - slice.sort_by_key(pkg_proc_groups[:], entity_key) - slice.sort_by_key(pkg_types[:], entity_key) - slice.sort_by_key(pkg_vars[:], entity_key) - slice.sort_by_key(pkg_consts[:], entity_key) - - write_index :: proc(w: io.Writer, name: string, entities: []^doc.Entity) { - fmt.wprintln(w, `
    `) - defer fmt.wprintln(w, `
    `) - - - fmt.wprintf(w, `
    `+"\n", name) - fmt.wprintf(w, ``+"\n", name) - io.write_string(w, name) - fmt.wprintln(w, ``) - defer fmt.wprintln(w, `
    `) - - if len(entities) == 0 { - io.write_string(w, "

    This section is empty.

    \n") - } else { - fmt.wprintln(w, "
      ") - for e in entities { - name := str(e.name) - fmt.wprintf(w, "
    • {0:s}
    • \n", name) - } - fmt.wprintln(w, "
    ") - } - } - - entity_ordering := [?]struct{name: string, entities: []^doc.Entity} { - {"Types", pkg_types[:]}, - {"Constants", pkg_consts[:]}, - {"Variables", pkg_vars[:]}, - {"Procedures", pkg_procs[:]}, - {"Procedure Groups", pkg_proc_groups[:]}, - } - - - for eo in entity_ordering { - write_index(w, eo.name, eo.entities) - } - - fmt.wprintln(w, "
    ") - - - write_entity :: proc(w: io.Writer, e: ^doc.Entity) { - write_attributes :: proc(w: io.Writer, e: ^doc.Entity) { - for attr in array(e.attributes) { - io.write_string(w, "@(") - name := str(attr.name) - value := str(attr.value) - io.write_string(w, name) - if value != "" { - io.write_string(w, "=") - io.write_string(w, value) - } - io.write_string(w, ")\n") - } - } - - pkg_index := files[e.pos.file].pkg - pkg := &pkgs[pkg_index] - writer := &Type_Writer{ - w = w, - pkg = pkg_index, - } - defer delete(writer.generic_scope) - collection := pkg_to_collection[pkg] - github_url := collection.github_url if collection != nil else GITHUB_CORE_URL - - name := str(e.name) - path := pkg_to_path[pkg] - filename := slashpath.base(str(files[e.pos.file].name)) - fmt.wprintf(w, "

    {0:s}", name) - fmt.wprintf(w, " ¶") - if e.pos.file != 0 && e.pos.line > 0 { - src_url := fmt.tprintf("%s/%s/%s#L%d", github_url, path, filename, e.pos.line) - fmt.wprintf(w, "", src_url) - } - fmt.wprintf(w, "

    \n") - fmt.wprintln(w, `
    `) - - switch e.kind { - case .Invalid, .Import_Name, .Library_Name: - // ignore - case .Constant: - fmt.wprint(w, `
    `)
    -			the_type := types[e.type]
    -
    -			init_string := str(e.init_string)
    -			assert(init_string != "")
    -
    -			ignore_type := true
    -			if the_type.kind == .Basic && is_type_untyped(the_type) {
    -			} else {
    -				ignore_type = false
    -				type_name := str(the_type.name)
    -				if type_name != "" && strings.has_prefix(init_string, type_name) {
    -					ignore_type = true
    -				}
    -			}
    -
    -			if ignore_type {
    -				fmt.wprintf(w, "%s :: ", name)
    -			} else {
    -				fmt.wprintf(w, "%s: ", name)
    -				write_type(writer, the_type, {.Allow_Indent})
    -				fmt.wprintf(w, " : ")
    -			}
    -
    -
    -			io.write_string(w, init_string)
    -			fmt.wprintln(w, "
    ") - case .Variable: - fmt.wprint(w, `
    `)
    -			write_attributes(w, e)
    -			fmt.wprintf(w, "%s: ", name)
    -			write_type(writer, types[e.type], {.Allow_Indent})
    -			init_string := str(e.init_string)
    -			if init_string != "" {
    -				io.write_string(w, " = ")
    -				io.write_string(w, "…")
    -			}
    -			fmt.wprintln(w, "
    ") - - case .Type_Name: - fmt.wprint(w, `
    `)
    -			fmt.wprintf(w, "%s :: ", name)
    -			the_type := types[e.type]
    -			type_to_print := the_type
    -			if the_type.kind == .Named && .Type_Alias not_in e.flags {
    -				if e.pos == entities[array(the_type.entities)[0]].pos {
    -					bt := base_type(the_type)
    -					#partial switch bt.kind {
    -					case .Struct, .Union, .Proc, .Enum:
    -						// Okay
    -					case:
    -						io.write_string(w, "distinct ")
    -					}
    -					type_to_print = bt
    -				}
    -			}
    -			write_type(writer, type_to_print, {.Allow_Indent})
    -			fmt.wprintln(w, "
    ") - case .Procedure: - fmt.wprint(w, `
    `)
    -			fmt.wprintf(w, "%s :: ", name)
    -			write_type(writer, types[e.type], nil)
    -			write_where_clauses(w, array(e.where_clauses))
    -			fmt.wprint(w, " {…}")
    -			fmt.wprintln(w, "
    ") - case .Proc_Group: - fmt.wprint(w, `
    `)
    -			fmt.wprintf(w, "%s :: proc{{\n", name)
    -			for entity_index in array(e.grouped_entities) {
    -				this_proc := &entities[entity_index]
    -				this_pkg := files[this_proc.pos.file].pkg
    -				io.write_byte(w, '\t')
    -				if this_pkg != pkg_index {
    -					fmt.wprintf(w, "%s.", str(pkgs[this_pkg].name))
    -				}
    -				pkg := &pkgs[this_pkg]
    -				collection := pkg_to_collection[pkg]
    -				name := str(this_proc.name)
    -				fmt.wprintf(w, ``, pkg_to_path[pkg], name, collection.base_url)
    -				io.write_string(w, name)
    -				io.write_string(w, ``)
    -				io.write_byte(w, ',')
    -				io.write_byte(w, '\n')
    -			}
    -			fmt.wprintln(w, "}")
    -			fmt.wprintln(w, "
    ") - - } - fmt.wprintln(w, `
    `) - - the_docs := strings.trim_space(str(e.docs)) - if the_docs != "" { - fmt.wprintln(w, `
    `) - fmt.wprintln(w, ` `) - write_docs(w, pkg, the_docs) - fmt.wprintln(w, `
    `) - } - } - write_entities :: proc(w: io.Writer, title: string, entities: []^doc.Entity) { - fmt.wprintf(w, "

    {0:s}

    \n", title) - fmt.wprintln(w, `
    `) - if len(entities) == 0 { - io.write_string(w, "

    This section is empty.

    \n") - } else { - for e in entities { - fmt.wprintln(w, `
    `) - write_entity(w, e) - fmt.wprintln(w, `
    `) - } - } - fmt.wprintln(w, "
    ") - } - - for eo in entity_ordering { - write_entities(w, eo.name, eo.entities) - } - - fmt.wprintln(w, `

    Source Files

    `) - fmt.wprintln(w, "
      ") - any_hidden := false - source_file_loop: for file_index in array(pkg.files) { - file := files[file_index] - filename := slashpath.base(str(file.name)) - switch { - case - strings.has_suffix(filename, "_windows.odin"), - strings.has_suffix(filename, "_darwin.odin"), - strings.has_suffix(filename, "_essence.odin"), - strings.has_suffix(filename, "_freebsd.odin"), - strings.has_suffix(filename, "_wasi.odin"), - strings.has_suffix(filename, "_js.odin"), - strings.has_suffix(filename, "_freestanding.odin"), - - strings.has_suffix(filename, "_amd64.odin"), - strings.has_suffix(filename, "_i386.odin"), - strings.has_suffix(filename, "_arch64.odin"), - strings.has_suffix(filename, "_wasm32.odin"), - strings.has_suffix(filename, "_wasm64.odin"), - false: - any_hidden = true - continue source_file_loop - } - fmt.wprintf(w, `
    • %s
    • `, collection.github_url, path, filename, filename) - fmt.wprintln(w) - } - if any_hidden { - fmt.wprintln(w, "
    • (hidden platform specific files)
    • ") - } - fmt.wprintln(w, "
    ") - - { - fmt.wprintln(w, `

    Generation Information

    `) - now := time.now() - fmt.wprintf(w, "

    Generated with odin version %s (vendor %q) %s_%s @ %v

    \n", ODIN_VERSION, ODIN_VENDOR, ODIN_OS, ODIN_ARCH, now) - } - - - - fmt.wprintln(w, `
    `) - { - write_link :: proc(w: io.Writer, id, text: string) { - fmt.wprintf(w, `
  • %s`, id, text) - } - - fmt.wprintln(w, ``) - } - -} \ No newline at end of file diff --git a/tools/odin-html-docs/style.css b/tools/odin-html-docs/style.css deleted file mode 100644 index 1b94d54ec..000000000 --- a/tools/odin-html-docs/style.css +++ /dev/null @@ -1,180 +0,0 @@ -/* doc directories */ - -table.directory { - /*border: 1px solid #ccc!important;*/ - table-layout: fixed; - border-collapse: collapse; -} - -header.collection-header ul { - margin-top: 1em; - margin-bottom: 0; - padding-left: 0.5em; - list-style-type: none; -} - -hr.collection-hr { - margin: 0; - padding: 0; -} - - -.doc-directory tr { - padding-left: 1em!important; - border-top: 1px solid #ccc!important; - border-bottom: 1px solid #ccc!important; -} - -.doc-directory td { - padding: 0.25em 0.5em; -} -.directory-child td { - padding-left: 2em!important; -} - -.directory-child td+td { - position: relative; - left: -1.5em!important; - padding-right: 0; -} - -.doc-directory tr[aria-expanded=true] td.pkg-name:before { - content: "\2193"; -} -.doc-directory tr[aria-expanded=false] td.pkg-name:before { - content: "\2192"!important; -} - -.doc-directory tr[aria-hidden=true] { - display: none; -} - - -/* doc page */ - -pre.doc-code { - white-space: pre-wrap; - word-break: keep-all; - word-wrap: break-word; - tab-size: 8; - background-color: #f8f8f8; - color: #202224; - border: 1px solid #c6c8ca; - border-radius: 0.25rem; - padding: 0.625rem; -} -pre.doc-code a { - font-family: Consolas,Liberation Mono,Menlo,monospace!important; - text-decoration: none; - color: #2179d8; - font-weight: 800; -} - -pre.doc-code a.code-procedure { - color: #047919; -} - -.pkg-line-doc { - color: #444; - width: 100%; -} - - -.doc-source { - display: inline; - float: right; -} - -.doc-source a { - text-decoration: none; - color: #666666; - font-size: 0.75em; -} -.doc-source a:hover { - text-decoration: underline; -} - -a > .a-hidden { - opacity: 0; -} -a:hover > .a-hidden { - opacity: 100; -} -section.documentation h3 { - font-size: calc(1.1rem + .2vw); -} - -.pkg-index h3 { - margin-top: 0 !important; - padding-top: 0 !important; -} - - -.documentation .pkg-entity { - padding-bottom: 0.75rem; - border-bottom: 1px solid #d0d0d0; -} - -details.doc-index > summary { - font-size: 1.75rem; -} -details.doc-index ul { - list-style-type: none; -} - -details.odin-doc-toggle > summary.hideme span:before { - content: "Expand description"; -} -details.odin-doc-toggle[open] > summary.hideme span:before { - content: "Close description"; - opacity: 0.8; -} - -details.odin-doc-toggle[open] > summary.hideme { - margin-bottom: 0.5em; -} - -details.code-example > summary { - font-weight: 700; -} - -@media only screen and (max-width: 991px) { - #pkg-sidebar { - display: none; - } -} - -#pkg-sidebar { - overflow-x: hidden; -} - -#pkg-sidebar > div { - overflow-x: auto; -} - - -#pkg-sidebar ul { - list-style-type: none; - padding: 0; -} - -#pkg-sidebar li:not(:last-child) { - margin-bottom: 0.25rem; -} - - -#pkg-sidebar li > ul { - padding-left: 1.25rem; -} - -#pkg-sidebar a.active { - font-style: italic; -} - -#TableOfContents { - overflow-x: hidden; -} - -#TableOfContents > ul { - overflow-x: auto; -} \ No newline at end of file From 18e639f59b411a39c52339f67974a8dd76b33a6e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 23 Jan 2022 21:35:03 +0000 Subject: [PATCH 019/117] Add `strings.split_lines*` procedures --- core/strings/strings.odin | 70 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/core/strings/strings.odin b/core/strings/strings.odin index b93c5bcc0..67046c669 100644 --- a/core/strings/strings.odin +++ b/core/strings/strings.odin @@ -353,6 +353,76 @@ split_after_n_iterator :: proc(s: ^string, sep: string, n: int) -> (string, bool } +@(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, -1) or_return + return _trim_cr(line), true +} + +split_lines_n_iterator :: proc(s: ^string, n: int) -> (line: string, ok: bool) { + sep :: "\n" + line = _split_iterator(s, sep, 0, n) 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), -1) or_return + return _trim_cr(line), true +} + +split_lines_after_n_iterator :: proc(s: ^string, n: int) -> (line: string, ok: bool) { + sep :: "\n" + line = _split_iterator(s, sep, len(sep), n) or_return + return _trim_cr(line), true +} From d269dbcd40d5b81f060a17ed4ca89d97dafcc49c Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 23 Jan 2022 22:01:54 +0000 Subject: [PATCH 020/117] Add comment for the internals of `assert` --- core/runtime/core_builtin.odin | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/runtime/core_builtin.odin b/core/runtime/core_builtin.odin index 44da894c1..3bafc0b1d 100644 --- a/core/runtime/core_builtin.odin +++ b/core/runtime/core_builtin.odin @@ -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 { From 849fe01e702073bc50789b8fa904aac0d166e030 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 24 Jan 2022 14:13:24 +0000 Subject: [PATCH 021/117] Add `lb_add_debug_local_variable` call to procedure arguments --- src/llvm_backend_proc.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 2a6eb6bb3..2d5924608 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -488,6 +488,7 @@ void lb_begin_procedure_body(lbProcedure *p) { lbValue ptr = lb_address_from_load_or_generate_local(p, param); lb_add_entity(p->module, e, ptr); + lb_add_debug_local_variable(p, ptr.value, e->type, e->token); } } else if (arg_type->kind == lbArg_Indirect) { if (e->token.string.len != 0 && !is_blank_ident(e->token.string)) { @@ -496,6 +497,7 @@ void lb_begin_procedure_body(lbProcedure *p) { ptr.type = alloc_type_pointer(e->type); lb_add_entity(p->module, e, ptr); + lb_add_debug_local_variable(p, ptr.value, e->type, e->token); } } param_index += 1; From 49872e40dcd88f6b011a79baccdadf509f062795 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 24 Jan 2022 14:46:56 +0000 Subject: [PATCH 022/117] Comment out calls --- src/llvm_backend_proc.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 2d5924608..b35c6c304 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -488,7 +488,7 @@ void lb_begin_procedure_body(lbProcedure *p) { lbValue ptr = lb_address_from_load_or_generate_local(p, param); lb_add_entity(p->module, e, ptr); - lb_add_debug_local_variable(p, ptr.value, e->type, e->token); + // lb_add_debug_local_variable(p, ptr.value, e->type, e->token); } } else if (arg_type->kind == lbArg_Indirect) { if (e->token.string.len != 0 && !is_blank_ident(e->token.string)) { @@ -497,7 +497,7 @@ void lb_begin_procedure_body(lbProcedure *p) { ptr.type = alloc_type_pointer(e->type); lb_add_entity(p->module, e, ptr); - lb_add_debug_local_variable(p, ptr.value, e->type, e->token); + // lb_add_debug_local_variable(p, ptr.value, e->type, e->token); } } param_index += 1; From 2554c72bb219286825ee8d47a2c6c748416acb0e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 24 Jan 2022 14:47:33 +0000 Subject: [PATCH 023/117] Update CommentGroup parsing for struct types --- src/check_type.cpp | 10 ++++++++++ src/docs_format.cpp | 4 ++-- src/docs_writer.cpp | 6 ++++++ src/entity.cpp | 2 ++ src/parser.cpp | 2 +- 5 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/check_type.cpp b/src/check_type.cpp index a5a757f3e..2a7479d68 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -120,6 +120,8 @@ void check_struct_fields(CheckerContext *ctx, Ast *node, Slice *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 *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] == '`')) { diff --git a/src/docs_format.cpp b/src/docs_format.cpp index f47fd0945..39f2e307c 100644 --- a/src/docs_format.cpp +++ b/src/docs_format.cpp @@ -185,8 +185,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; diff --git a/src/docs_writer.cpp b/src/docs_writer.cpp index 0a990cc37..825ca113f 100644 --- a/src/docs_writer.cpp +++ b/src/docs_writer.cpp @@ -811,6 +811,12 @@ OdinDocEntityIndex odin_doc_add_entity(OdinDocWriter *w, Entity *e) { comment = e->decl_info->comment; docs = e->decl_info->docs; } + if (!comment && e->kind == Entity_Variable) { + comment = e->Variable.comment; + } + if (!docs && e->kind == Entity_Variable) { + docs = e->Variable.docs; + } String link_name = {}; diff --git a/src/entity.cpp b/src/entity.cpp index 05ee9a33e..0f8bfa456 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -175,6 +175,8 @@ struct Entity { String link_name; String link_prefix; String link_section; + CommentGroup *docs; + CommentGroup *comment; bool is_foreign; bool is_export; } Variable; diff --git a/src/parser.cpp b/src/parser.cpp index 7e7146244..076c698ff 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -944,7 +944,7 @@ Ast *ast_field(AstFile *f, Array 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; } From dcc9e61362a04ecbd01cf3088766e013db6253bc Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 24 Jan 2022 14:52:43 +0000 Subject: [PATCH 024/117] Correct string_append_token --- src/check_expr.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 99d351753..81f69055a 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -9115,18 +9115,7 @@ gbString string_append_string(gbString str, String string) { gbString string_append_token(gbString str, Token token) { - if (token.kind == Token_String) { - str = gb_string_append_rune(str, '"'); - } else if (token.kind == Token_Rune) { - str = gb_string_append_rune(str, '\''); - } str = string_append_string(str, token.string); - if (token.kind == Token_String) { - str = gb_string_append_rune(str, '"'); - } else if (token.kind == Token_Rune) { - str = gb_string_append_rune(str, '\''); - } - return str; } From 42ab882db4a6d5765c68021ade010b468ff4531e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 24 Jan 2022 15:56:26 +0000 Subject: [PATCH 025/117] Remove debug code --- src/check_expr.cpp | 1 - src/checker.cpp | 3 --- 2 files changed, 4 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 81f69055a..1742ef2d8 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -3419,7 +3419,6 @@ void convert_untyped_error(CheckerContext *c, Operand *operand, Type *target_typ if (operand->value.kind == ExactValue_String) { String key = operand->value.value_string; if (is_type_string(operand->type) && is_type_enum(target_type)) { - gb_printf_err("HERE!\n"); Type *et = base_type(target_type); check_did_you_mean_type(key, et->Enum.fields, "."); } diff --git a/src/checker.cpp b/src/checker.cpp index 55a3892e5..b81d9987b 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1618,9 +1618,6 @@ void add_type_info_type_internal(CheckerContext *c, Type *t) { // NOTE(bill): map entries grow linearly and in order ti_index = c->info->type_info_types.count; array_add(&c->info->type_info_types, t); - if (t->kind == Type_Named && t->Named.name == "A") { - gb_printf_err("HERE!\n"); - } } map_set(&c->checker->info.type_info_map, t, ti_index); From f20105ddfee6d9a2aa02452e459c42c7f0310e76 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 24 Jan 2022 23:07:06 +0000 Subject: [PATCH 026/117] Update docs for packages fmt and io --- core/fmt/fmt.odin | 33 +++++++++++++++++++++++++++------ core/fmt/fmt_js.odin | 7 ++++++- core/fmt/fmt_os.odin | 10 +++++++++- core/io/io.odin | 41 +++++++++++++++++++++++++++++++++++++++-- 4 files changed, 81 insertions(+), 10 deletions(-) diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index 2cc192c12..932fc0bb8 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -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 diff --git a/core/fmt/fmt_js.odin b/core/fmt/fmt_js.odin index bcd9688a1..7a9876127 100644 --- a/core/fmt/fmt_js.odin +++ b/core/fmt/fmt_js.odin @@ -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) } diff --git a/core/fmt/fmt_os.odin b/core/fmt/fmt_os.odin index 7434d939d..f5c8d75bd 100644 --- a/core/fmt/fmt_os.odin +++ b/core/fmt/fmt_os.odin @@ -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) } diff --git a/core/io/io.odin b/core/io/io.odin index b4757f8e5..e9d839efb 100644 --- a/core/io/io.odin +++ b/core/io/io.odin @@ -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 From fe0b5bf4e27912c49f6c5eab817cbf514b0b22e4 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 24 Jan 2022 23:28:59 +0000 Subject: [PATCH 027/117] Parse comments on enums fields --- src/check_expr.cpp | 7 +++++++ src/check_type.cpp | 23 ++++++++++++----------- src/docs_writer.cpp | 11 ++++++----- src/entity.cpp | 2 ++ src/parser.cpp | 42 +++++++++++++++++++++++++++++++++++++++++- src/parser.hpp | 6 ++++++ 6 files changed, 74 insertions(+), 17 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 1742ef2d8..725b57f33 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -9341,6 +9341,13 @@ gbString write_expr_to_string(gbString str, Ast *node, bool shorthand) { str = gb_string_appendc(str, " = "); str = write_expr_to_string(str, fv->value, shorthand); case_end; + case_ast_node(fv, EnumFieldValue, node); + str = write_expr_to_string(str, fv->name, shorthand); + if (fv->value) { + str = gb_string_appendc(str, " = "); + str = write_expr_to_string(str, fv->value, shorthand); + } + case_end; case_ast_node(ht, HelperType, node); str = gb_string_appendc(str, "#type "); diff --git a/src/check_type.cpp b/src/check_type.cpp index 2a7479d68..a6d82c86e 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -732,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) { @@ -803,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)); diff --git a/src/docs_writer.cpp b/src/docs_writer.cpp index 825ca113f..b1b9450df 100644 --- a/src/docs_writer.cpp +++ b/src/docs_writer.cpp @@ -811,11 +811,12 @@ OdinDocEntityIndex odin_doc_add_entity(OdinDocWriter *w, Entity *e) { comment = e->decl_info->comment; docs = e->decl_info->docs; } - if (!comment && e->kind == Entity_Variable) { - comment = e->Variable.comment; - } - if (!docs && e->kind == Entity_Variable) { - docs = e->Variable.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 link_name = {}; diff --git a/src/entity.cpp b/src/entity.cpp index 0f8bfa456..a0438a9f4 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -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 diff --git a/src/parser.cpp b/src/parser.cpp index 076c698ff..ebe65cee1 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -693,6 +693,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 const &elems, Token open, Token close) { Ast *result = alloc_ast_node(f, Ast_CompoundLit); result->CompoundLit.type = type; @@ -1689,6 +1699,36 @@ Array parse_element_list(AstFile *f) { return elems; } +Array parse_enum_field_list(AstFile *f) { + auto elems = array_make(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 = f->line_comment; + + 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 = f->line_comment; + } + } + + return elems; +} Ast *parse_literal_value(AstFile *f, Ast *type) { Array elems = {}; @@ -2449,7 +2489,7 @@ Ast *parse_operand(AstFile *f, bool lhs) { skip_possible_newline_for_literal(f); Token open = expect_token(f, Token_OpenBrace); - Array values = parse_element_list(f); + Array values = parse_enum_field_list(f); Token close = expect_closing_brace_of_field_list(f); return ast_enum_type(f, token, base_type, values); diff --git a/src/parser.hpp b/src/parser.hpp index b83822cbf..b005a4465 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -383,6 +383,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; }) \ From c0479f1564119603f022f5f3d22dd8dc3a1e5983 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 24 Jan 2022 23:42:04 +0000 Subject: [PATCH 028/117] Handle line comment better --- src/parser.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/parser.cpp b/src/parser.cpp index ebe65cee1..108411cd0 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1244,7 +1244,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; @@ -1288,7 +1288,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") { @@ -1699,6 +1699,16 @@ Array 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 parse_enum_field_list(AstFile *f) { auto elems = array_make(heap_allocator()); @@ -1713,7 +1723,7 @@ Array parse_enum_field_list(AstFile *f) { value = parse_value(f); } - comment = f->line_comment; + comment = consume_line_comment(f); Ast *elem = ast_enum_field_value(f, name, value, docs, comment); array_add(&elems, elem); @@ -1723,7 +1733,7 @@ Array parse_enum_field_list(AstFile *f) { } if (!elem->EnumFieldValue.comment) { - elem->EnumFieldValue.comment = f->line_comment; + elem->EnumFieldValue.comment = consume_line_comment(f); } } @@ -5438,7 +5448,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; From 65f8722afc0680b7b7fa47fd7060fd434243ae3c Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Tue, 25 Jan 2022 12:18:10 +0100 Subject: [PATCH 029/117] zlib: update Huffman builder. --- core/compress/zlib/zlib.odin | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/core/compress/zlib/zlib.odin b/core/compress/zlib/zlib.odin index 9ae980042..4d575c7e6 100644 --- a/core/compress/zlib/zlib.odin +++ b/core/compress/zlib/zlib.odin @@ -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.. Date: Tue, 25 Jan 2022 12:39:06 +0000 Subject: [PATCH 030/117] Disable early return from `check_proc_info` --- src/checker.cpp | 13 +++++++------ src/llvm_backend_proc.cpp | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/checker.cpp b/src/checker.cpp index b81d9987b..9be64e369 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -4855,12 +4855,13 @@ bool check_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *untyped, Proc return false; } - if (pt->is_polymorphic && pt->is_poly_specialized) { - if ((e->flags & EntityFlag_Used) == 0) { - // NOTE(bill, 2019-08-31): It was never used, don't check - return false; - } - } + // NOTE(bill, 2022-01-25): Appears to be not needed any more + // if (pt->is_polymorphic && pt->is_poly_specialized) { + // if ((e->flags & EntityFlag_Used) == 0) { + // // NOTE(bill, 2019-08-31): It was never used, don't check + // return false; + // } + // } bool bounds_check = (pi->tags & ProcTag_bounds_check) != 0; bool no_bounds_check = (pi->tags & ProcTag_no_bounds_check) != 0; diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index b35c6c304..9f9fe7c7a 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -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 = {}; From a3e7b2baa1ede7ba328a9ec6b249051347ef4cae Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 25 Jan 2022 12:42:45 +0000 Subject: [PATCH 031/117] Revert change --- src/checker.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/checker.cpp b/src/checker.cpp index 9be64e369..b81d9987b 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -4855,13 +4855,12 @@ bool check_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *untyped, Proc return false; } - // NOTE(bill, 2022-01-25): Appears to be not needed any more - // if (pt->is_polymorphic && pt->is_poly_specialized) { - // if ((e->flags & EntityFlag_Used) == 0) { - // // NOTE(bill, 2019-08-31): It was never used, don't check - // return false; - // } - // } + if (pt->is_polymorphic && pt->is_poly_specialized) { + if ((e->flags & EntityFlag_Used) == 0) { + // NOTE(bill, 2019-08-31): It was never used, don't check + return false; + } + } bool bounds_check = (pi->tags & ProcTag_bounds_check) != 0; bool no_bounds_check = (pi->tags & ProcTag_no_bounds_check) != 0; From f16f1d932ef36c67dab0b7c8cd6898f9811d6f75 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 25 Jan 2022 14:24:15 +0000 Subject: [PATCH 032/117] Fix #1448 --- src/check_expr.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 725b57f33..276e9d0bb 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -5755,8 +5755,12 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type ctx.curr_proc_sig = e->type; GB_ASSERT(decl->proc_lit->kind == Ast_ProcLit); - evaluate_where_clauses(&ctx, call, decl->scope, &decl->proc_lit->ProcLit.where_clauses, true); + bool ok = evaluate_where_clauses(&ctx, call, decl->scope, &decl->proc_lit->ProcLit.where_clauses, true); decl->where_clauses_evaluated = true; + + if (ok && (data.gen_entity->flags & EntityFlag_ProcBodyChecked) == 0) { + check_procedure_later(c, e->file, e->token, decl, e->type, decl->proc_lit->ProcLit.body, decl->proc_lit->ProcLit.tags); + } } return data; } @@ -5769,6 +5773,7 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type Entity *e = entity_of_node(ident); + CallArgumentData data = {}; CallArgumentError err = call_checker(c, call, proc_type, e, operands, CallArgumentMode_ShowErrors, &data); gb_unused(err); @@ -5777,7 +5782,6 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type if (entity_to_use != nullptr) { update_untyped_expr_type(c, operand->expr, entity_to_use->type, true); } - if (data.gen_entity != nullptr) { Entity *e = data.gen_entity; DeclInfo *decl = data.gen_entity->decl_info; @@ -5789,8 +5793,12 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type ctx.curr_proc_sig = e->type; GB_ASSERT(decl->proc_lit->kind == Ast_ProcLit); - evaluate_where_clauses(&ctx, call, decl->scope, &decl->proc_lit->ProcLit.where_clauses, true); + bool ok = evaluate_where_clauses(&ctx, call, decl->scope, &decl->proc_lit->ProcLit.where_clauses, true); decl->where_clauses_evaluated = true; + + if (ok && (data.gen_entity->flags & EntityFlag_ProcBodyChecked) == 0) { + check_procedure_later(c, e->file, e->token, decl, e->type, decl->proc_lit->ProcLit.body, decl->proc_lit->ProcLit.tags); + } } return data; } From dd3322ac1fb139b639306831849d0264dcd13d6c Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 25 Jan 2022 14:34:48 +0000 Subject: [PATCH 033/117] Update all_main.odin to include all the crypto packages --- examples/all/all_main.odin | 81 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/examples/all/all_main.odin b/examples/all/all_main.odin index c24238602..199f406f7 100644 --- a/examples/all/all_main.odin +++ b/examples/all/all_main.odin @@ -5,25 +5,66 @@ 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/queue" + +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 +73,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 +97,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" @@ -68,6 +117,37 @@ _ :: 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 @@ -107,6 +187,7 @@ _ :: strconv _ :: strings _ :: sync _ :: sync2 +_ :: testing _ :: scanner _ :: thread _ :: time From 515fd2a228835afa71cefec645b906729cda399e Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Tue, 25 Jan 2022 17:08:32 +0100 Subject: [PATCH 034/117] bit_array: Fix initial size. --- core/container/bit_array/bit_array.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/container/bit_array/bit_array.odin b/core/container/bit_array/bit_array.odin index 61f6f86e8..0fa80c623 100644 --- a/core/container/bit_array/bit_array.odin +++ b/core/container/bit_array/bit_array.odin @@ -88,7 +88,7 @@ create :: proc(max_index: int, min_index := 0, allocator := context.allocator) - res = Bit_Array{ bias = min_index, } - return res, resize_if_needed(&res, size_in_bits) + return res, resize_if_needed(&res, legs) } /* From 1bf8328606ba83f943eb2568c89dab38b0b1dd94 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 25 Jan 2022 16:40:25 +0000 Subject: [PATCH 035/117] Strip unneeded semicolons --- core/crypto/blake/blake.odin | 8 ++++---- core/crypto/blake2b/blake2b.odin | 2 +- core/crypto/blake2s/blake2s.odin | 2 +- core/crypto/gost/gost.odin | 2 +- core/crypto/groestl/groestl.odin | 8 ++++---- core/crypto/haval/haval.odin | 30 ++++++++++++++-------------- core/crypto/jh/jh.odin | 8 ++++---- core/crypto/keccak/keccak.odin | 8 ++++---- core/crypto/md2/md2.odin | 2 +- core/crypto/md4/md4.odin | 2 +- core/crypto/md5/md5.odin | 2 +- core/crypto/ripemd/ripemd.odin | 8 ++++---- core/crypto/sha1/sha1.odin | 2 +- core/crypto/sha2/sha2.odin | 8 ++++---- core/crypto/sha3/sha3.odin | 8 ++++---- core/crypto/shake/shake.odin | 4 ++-- core/crypto/sm3/sm3.odin | 2 +- core/crypto/streebog/streebog.odin | 4 ++-- core/crypto/tiger/tiger.odin | 6 +++--- core/crypto/tiger2/tiger2.odin | 6 +++--- core/crypto/whirlpool/whirlpool.odin | 2 +- 21 files changed, 62 insertions(+), 62 deletions(-) diff --git a/core/crypto/blake/blake.odin b/core/crypto/blake/blake.odin index 81924ab1e..5fc0a02b9 100644 --- a/core/crypto/blake/blake.odin +++ b/core/crypto/blake/blake.odin @@ -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 diff --git a/core/crypto/blake2b/blake2b.odin b/core/crypto/blake2b/blake2b.odin index 6d4689b88..e75d74197 100644 --- a/core/crypto/blake2b/blake2b.odin +++ b/core/crypto/blake2b/blake2b.odin @@ -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 diff --git a/core/crypto/blake2s/blake2s.odin b/core/crypto/blake2s/blake2s.odin index ad2e800fd..831335081 100644 --- a/core/crypto/blake2s/blake2s.odin +++ b/core/crypto/blake2s/blake2s.odin @@ -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 diff --git a/core/crypto/gost/gost.odin b/core/crypto/gost/gost.odin index eed684f72..1d0274fae 100644 --- a/core/crypto/gost/gost.odin +++ b/core/crypto/gost/gost.odin @@ -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 diff --git a/core/crypto/groestl/groestl.odin b/core/crypto/groestl/groestl.odin index 5434e31e0..8e5a2440d 100644 --- a/core/crypto/groestl/groestl.odin +++ b/core/crypto/groestl/groestl.odin @@ -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 diff --git a/core/crypto/haval/haval.odin b/core/crypto/haval/haval.odin index 442a348e9..811ecf95d 100644 --- a/core/crypto/haval/haval.odin +++ b/core/crypto/haval/haval.odin @@ -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 diff --git a/core/crypto/jh/jh.odin b/core/crypto/jh/jh.odin index 4ebc0e5cb..42c2d1d34 100644 --- a/core/crypto/jh/jh.odin +++ b/core/crypto/jh/jh.odin @@ -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 diff --git a/core/crypto/keccak/keccak.odin b/core/crypto/keccak/keccak.odin index f5d4826b1..aeb5aac52 100644 --- a/core/crypto/keccak/keccak.odin +++ b/core/crypto/keccak/keccak.odin @@ -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 diff --git a/core/crypto/md2/md2.odin b/core/crypto/md2/md2.odin index 102c1b8b4..711e6e9f6 100644 --- a/core/crypto/md2/md2.odin +++ b/core/crypto/md2/md2.odin @@ -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 diff --git a/core/crypto/md4/md4.odin b/core/crypto/md4/md4.odin index d944daa1d..b2651225b 100644 --- a/core/crypto/md4/md4.odin +++ b/core/crypto/md4/md4.odin @@ -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 diff --git a/core/crypto/md5/md5.odin b/core/crypto/md5/md5.odin index 9129e6384..30a556102 100644 --- a/core/crypto/md5/md5.odin +++ b/core/crypto/md5/md5.odin @@ -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 diff --git a/core/crypto/ripemd/ripemd.odin b/core/crypto/ripemd/ripemd.odin index c475c4803..702d29037 100644 --- a/core/crypto/ripemd/ripemd.odin +++ b/core/crypto/ripemd/ripemd.odin @@ -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 diff --git a/core/crypto/sha1/sha1.odin b/core/crypto/sha1/sha1.odin index e8df3c7f6..b0dbd7dc8 100644 --- a/core/crypto/sha1/sha1.odin +++ b/core/crypto/sha1/sha1.odin @@ -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 diff --git a/core/crypto/sha2/sha2.odin b/core/crypto/sha2/sha2.odin index 2178b70b5..7c7b2da81 100644 --- a/core/crypto/sha2/sha2.odin +++ b/core/crypto/sha2/sha2.odin @@ -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 diff --git a/core/crypto/sha3/sha3.odin b/core/crypto/sha3/sha3.odin index 2eceeaff6..1202f8b23 100644 --- a/core/crypto/sha3/sha3.odin +++ b/core/crypto/sha3/sha3.odin @@ -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 diff --git a/core/crypto/shake/shake.odin b/core/crypto/shake/shake.odin index 9fdc3ebf1..525dcfbd3 100644 --- a/core/crypto/shake/shake.odin +++ b/core/crypto/shake/shake.odin @@ -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 diff --git a/core/crypto/sm3/sm3.odin b/core/crypto/sm3/sm3.odin index e72973e33..74c9f22e2 100644 --- a/core/crypto/sm3/sm3.odin +++ b/core/crypto/sm3/sm3.odin @@ -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 diff --git a/core/crypto/streebog/streebog.odin b/core/crypto/streebog/streebog.odin index deb71120d..f85977cba 100644 --- a/core/crypto/streebog/streebog.odin +++ b/core/crypto/streebog/streebog.odin @@ -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 diff --git a/core/crypto/tiger/tiger.odin b/core/crypto/tiger/tiger.odin index 4ea80c66c..cf6159fad 100644 --- a/core/crypto/tiger/tiger.odin +++ b/core/crypto/tiger/tiger.odin @@ -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 diff --git a/core/crypto/tiger2/tiger2.odin b/core/crypto/tiger2/tiger2.odin index 84333f344..e8f2c4edb 100644 --- a/core/crypto/tiger2/tiger2.odin +++ b/core/crypto/tiger2/tiger2.odin @@ -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 diff --git a/core/crypto/whirlpool/whirlpool.odin b/core/crypto/whirlpool/whirlpool.odin index 255f57bc2..0cfef7c6b 100644 --- a/core/crypto/whirlpool/whirlpool.odin +++ b/core/crypto/whirlpool/whirlpool.odin @@ -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 From fb86c23dbd4c6e9dc82fcc72deb1ad59af5e07f0 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 25 Jan 2022 16:41:31 +0000 Subject: [PATCH 036/117] Keep -vet happy --- core/container/queue/queue.odin | 1 + 1 file changed, 1 insertion(+) diff --git a/core/container/queue/queue.odin b/core/container/queue/queue.odin index feca6934c..8ca3a85ac 100644 --- a/core/container/queue/queue.odin +++ b/core/container/queue/queue.odin @@ -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) { From 081a5a52a621f3577255b30a4fa35c9b458d5689 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Jan 2022 16:09:22 +0000 Subject: [PATCH 037/117] Add ODIN_ERROR_POS_STYLE environment variable Allowing for two different error message styles: default or odin path(line:column) message unix path:line:column: message --- src/build_settings.cpp | 51 +++++++++++++++++++++++++++++++++++++++++- src/error.cpp | 4 ++++ src/tokenizer.cpp | 8 ------- 3 files changed, 54 insertions(+), 9 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index b4a934ec8..d7253f865 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -165,6 +165,11 @@ enum TimingsExportFormat : i32 { TimingsExportCSV = 2, }; +enum ErrorPosStyle { + ErrorPosStyle_Default, // path(line:column) msg + ErrorPosStyle_Unix, // path:line:column: msg +}; + // This stores the information for the specify architecture of this build struct BuildContext { // Constants @@ -175,7 +180,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 +261,7 @@ bool ODIN_DEFAULT_TO_NIL_ALLOCATOR; // Whether the default allocator is a "nil isize thread_count; PtrMap defined_values; + }; @@ -843,6 +851,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 +879,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; diff --git a/src/error.cpp b/src/error.cpp index b08ff99df..faf4d11fb 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -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); diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 20815fd16..40bc5c220 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -201,14 +201,6 @@ struct TokenPos { i32 column; // starting at 1 }; -// 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); - s = gb_string_append_fmt(s, "%.*s(%d:%d)", LIT(file), pos.line, pos.column); - return s; -} - i32 token_pos_cmp(TokenPos const &a, TokenPos const &b) { if (a.offset != b.offset) { return (a.offset < b.offset) ? -1 : +1; From b190404b217f59b9bed65bdf588a4e0369f60a95 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Jan 2022 16:37:16 +0000 Subject: [PATCH 038/117] Fix double map dereference indexing --- src/llvm_backend_expr.cpp | 6 ++++-- src/llvm_backend_general.cpp | 4 ++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 1f0ed6434..9b2e26434 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -3460,7 +3460,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 +3470,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) { diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 17eeb0bea..998dce88f 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -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; From 74174eb4ae796d6c161839d91c301229a1884713 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Jan 2022 16:38:12 +0000 Subject: [PATCH 039/117] Remove spurious `)` --- src/build_settings.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index d7253f865..96339be29 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -894,9 +894,9 @@ void init_build_context(TargetMetrics *cross_target) { 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\tpath(line:column) message\n"); gb_printf_err("\t\"unix\"\n"); - gb_printf_err("\t\tpath:line:column: message)\n"); + gb_printf_err("\t\tpath:line:column: message\n"); gb_exit(1); } From 070b4507686570335cb3624ef1ede6f442bd4866 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Jan 2022 17:34:39 +0000 Subject: [PATCH 040/117] Add `ODIN_ERROR_POS_STYLE` constant and change `runtime.print_caller_location` based on that constant --- core/runtime/print.odin | 20 +++++++++++++++----- src/build_settings.cpp | 2 ++ src/checker.cpp | 10 ++++++++++ 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/core/runtime/print.odin b/core/runtime/print.odin index 8a14eba08..8c0b65864 100644 --- a/core/runtime/print.odin +++ b/core/runtime/print.odin @@ -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 { diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 96339be29..610e4f847 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -168,6 +168,8 @@ enum TimingsExportFormat : i32 { 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 diff --git a/src/checker.cpp b/src/checker.cpp index b81d9987b..e0c756bb8 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -893,6 +893,16 @@ void init_universal(void) { add_global_enum_constant(fields, "ODIN_ENDIAN", 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); From 498f68c06b64b9e5bd6a8bd2aef2fb71ecabe5fc Mon Sep 17 00:00:00 2001 From: CiD- Date: Wed, 26 Jan 2022 14:37:15 -0500 Subject: [PATCH 041/117] avoid segfault on map resize --- src/llvm_backend_general.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 998dce88f..2fc21b534 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -1602,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; } } From 7e11f3cc4bd888ab57beedd94952a5ead8888d2e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Jan 2022 23:31:47 +0000 Subject: [PATCH 042/117] Update doc format to allow for aliases --- src/docs_format.cpp | 13 +++++++++++-- src/docs_writer.cpp | 33 ++++++++++++++------------------- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/src/docs_format.cpp b/src/docs_format.cpp index 39f2e307c..01320e2b9 100644 --- a/src/docs_format.cpp +++ b/src/docs_format.cpp @@ -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,8 @@ enum OdinDocEntityFlag : u64 { OdinDocEntityFlag_Type_Alias = 1ull<<20, + OdinDocEntityFlag_Builtin_Procedure = 1ull<<30, + OdinDocEntityFlag_Var_Thread_Local = 1ull<<40, OdinDocEntityFlag_Var_Static = 1ull<<41, @@ -201,15 +204,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 files; - OdinDocArray entities; + OdinDocArray files; + OdinDocArray entries; }; + struct OdinDocHeader { OdinDocHeaderBase base; diff --git a/src/docs_writer.cpp b/src/docs_writer.cpp index b1b9450df..290153ea3 100644 --- a/src/docs_writer.cpp +++ b/src/docs_writer.cpp @@ -819,6 +819,7 @@ OdinDocEntityIndex odin_doc_add_entity(OdinDocWriter *w, Entity *e) { if (!docs) { docs = e->Constant.docs; } } + String name = e->token.string; String link_name = {}; OdinDocEntityKind kind = OdinDocEntity_Invalid; @@ -834,6 +835,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) { @@ -899,7 +901,7 @@ 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.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); @@ -976,7 +978,7 @@ void odin_doc_update_entities(OdinDocWriter *w) { -OdinDocArray odin_doc_add_pkg_entities(OdinDocWriter *w, AstPackage *pkg) { +OdinDocArray odin_doc_add_pkg_entries(OdinDocWriter *w, AstPackage *pkg) { if (pkg->scope == nullptr) { return {}; } @@ -984,14 +986,14 @@ OdinDocArray odin_doc_add_pkg_entities(OdinDocWriter *w, Ast return {}; } - auto entities = array_make(heap_allocator(), 0, pkg->scope->elements.entries.count); - defer (array_free(&entities)); + auto entries = array_make(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; @@ -1002,18 +1004,10 @@ OdinDocArray 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(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; } @@ -1024,12 +1018,13 @@ OdinDocArray odin_doc_add_pkg_entities(OdinDocWriter *w, Ast 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); } @@ -1097,7 +1092,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; From 32b37f3429c18d9514091f4bde0a842eb2e70da7 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 27 Jan 2022 00:08:05 +0000 Subject: [PATCH 043/117] Support built-in procedures for doc format --- src/docs_format.cpp | 5 +++-- src/docs_writer.cpp | 23 +++++++++++++++++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/docs_format.cpp b/src/docs_format.cpp index 01320e2b9..7ce93d2bf 100644 --- a/src/docs_format.cpp +++ b/src/docs_format.cpp @@ -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]; @@ -171,7 +171,8 @@ enum OdinDocEntityFlag : u64 { OdinDocEntityFlag_Type_Alias = 1ull<<20, - OdinDocEntityFlag_Builtin_Procedure = 1ull<<30, + OdinDocEntityFlag_Builtin_Pkg_Builtin = 1ull<<30, + OdinDocEntityFlag_Builtin_Pkg_Intrinsics = 1ull<<31, OdinDocEntityFlag_Var_Thread_Local = 1ull<<40, OdinDocEntityFlag_Var_Static = 1ull<<41, diff --git a/src/docs_writer.cpp b/src/docs_writer.cpp index 290153ea3..8b752ab71 100644 --- a/src/docs_writer.cpp +++ b/src/docs_writer.cpp @@ -821,6 +821,7 @@ OdinDocEntityIndex odin_doc_add_entity(OdinDocWriter *w, Entity *e) { String name = e->token.string; String link_name = {}; + TokenPos pos = e->token.pos; OdinDocEntityKind kind = OdinDocEntity_Invalid; u64 flags = 0; @@ -865,6 +866,24 @@ 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"); + } + GB_PANIC("HERE"); + } + break; } if (e->flags & EntityFlag_Param) { @@ -900,7 +919,7 @@ 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.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; @@ -1011,7 +1030,7 @@ OdinDocArray odin_doc_add_pkg_entries(OdinDocWriter *w, AstPa if (e->pkg != pkg) { continue; } - if (!is_entity_exported(e)) { + if (!is_entity_exported(e, true)) { continue; } if (e->token.string.len == 0) { From 16786aac78e343fb11a5bd6c971ebb17ccd36f5c Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 27 Jan 2022 12:33:34 +0000 Subject: [PATCH 044/117] Correct int31_max etc --- core/math/rand/rand.odin | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/math/rand/rand.odin b/core/math/rand/rand.odin index 9bd30c216..04e2c6414 100644 --- a/core/math/rand/rand.odin +++ b/core/math/rand/rand.odin @@ -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) From 4dc29d141f5423c6b0f8d963b60d18eee988a8ab Mon Sep 17 00:00:00 2001 From: Daniel Gavin Date: Thu, 27 Jan 2022 14:24:33 +0100 Subject: [PATCH 045/117] Fix `core:odin/parser` not setting the inline flag correctly. --- core/odin/parser/parser.odin | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/odin/parser/parser.odin b/core/odin/parser/parser.odin index e8c2c848d..56e1708e4 100644 --- a/core/odin/parser/parser.odin +++ b/core/odin/parser/parser.odin @@ -2168,7 +2168,7 @@ parse_inlining_operand :: proc(p: ^Parser, lhs: bool, tok: tokenizer.Token) -> ^ } switch e in &ast.unparen_expr(expr).derived { - case ast.Proc_Lit: + case ast.Proc_Lit: if e.inlining != .None && e.inlining != pi { error(p, expr.pos, "both 'inline' and 'no_inline' cannot be applied to a procedure literal") } @@ -2319,7 +2319,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) From ff5e03677366141516b86783f4f3031c6f5e83ab Mon Sep 17 00:00:00 2001 From: Daniel Gavin Date: Thu, 27 Jan 2022 14:27:26 +0100 Subject: [PATCH 046/117] Trim whitespaces --- core/odin/parser/parser.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/odin/parser/parser.odin b/core/odin/parser/parser.odin index 56e1708e4..0ebabfd70 100644 --- a/core/odin/parser/parser.odin +++ b/core/odin/parser/parser.odin @@ -2168,7 +2168,7 @@ parse_inlining_operand :: proc(p: ^Parser, lhs: bool, tok: tokenizer.Token) -> ^ } switch e in &ast.unparen_expr(expr).derived { - case ast.Proc_Lit: + case ast.Proc_Lit: if e.inlining != .None && e.inlining != pi { error(p, expr.pos, "both 'inline' and 'no_inline' cannot be applied to a procedure literal") } From 28bc274449e77569d997b0dc327c097098daf80d Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Thu, 27 Jan 2022 14:58:45 +0100 Subject: [PATCH 047/117] Fix DEFLATE stored block handling. --- core/compress/zlib/zlib.odin | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/core/compress/zlib/zlib.odin b/core/compress/zlib/zlib.odin index 4d575c7e6..d4c0f332c 100644 --- a/core/compress/zlib/zlib.odin +++ b/core/compress/zlib/zlib.odin @@ -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 From 24e7356825a473cba0a1e9962470be73d60ad248 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 27 Jan 2022 16:08:47 +0000 Subject: [PATCH 048/117] Add `#no_type_assert` and `#type_assert` to disable implicit type assertions with `x.(T)` --- src/check_expr.cpp | 8 ++++ src/check_stmt.cpp | 8 ++++ src/checker.cpp | 12 ++++++ src/llvm_backend_expr.cpp | 76 ++++++++++++++++++++---------------- src/llvm_backend_stmt.cpp | 7 ++++ src/llvm_backend_utility.cpp | 41 ++++++++++++------- src/parser.cpp | 36 +++++++++++++++++ src/parser.hpp | 4 ++ 8 files changed, 144 insertions(+), 48 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 276e9d0bb..fb5a90f5a 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -6883,6 +6883,14 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type 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; + } + c->state_flags = out; } diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 94b7561c7..f9e55ab37 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -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; } diff --git a/src/checker.cpp b/src/checker.cpp index e0c756bb8..038709056 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -4875,6 +4875,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; @@ -4882,6 +4885,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); } diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 9b2e26434..ea031ee56 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -2768,28 +2768,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(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(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 +2799,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(permanent_allocator(), 6); + args[0] = ok; - lbValue ok = lb_emit_comp(p, Token_CmpEq, any_id, id); - auto args = array_make(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 +2845,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; } diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 3375ceda9..916c0433e 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -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; } diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index 5b1b11b44..7e2bd7daa 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -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(permanent_allocator(), 7); - args[0] = ok; + lbValue ok = lb_emit_load(p, lb_emit_struct_ep(p, v.addr, 1)); + auto args = array_make(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(permanent_allocator(), 7); args[0] = ok; diff --git a/src/parser.cpp b/src/parser.cpp index 108411cd0..9cc9adfc9 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1843,6 +1843,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)); } @@ -1853,6 +1855,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"); + } } @@ -2000,11 +2006,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: @@ -2128,6 +2146,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); @@ -2224,6 +2248,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)) { @@ -4611,6 +4641,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) { diff --git a/src/parser.hpp b/src/parser.hpp index b005a4465..656f709e8 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -226,6 +226,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 +260,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, }; From 2aa783179e8ea968e6f093ed9b63ae2f8bd8be43 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 27 Jan 2022 16:08:58 +0000 Subject: [PATCH 049/117] Update doc_format.odin --- core/odin/doc-format/doc_format.odin | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/core/odin/doc-format/doc_format.odin b/core/odin/doc-format/doc_format.odin index 59eafdc09..62682004d 100644 --- a/core/odin/doc-format/doc_format.odin +++ b/core/odin/doc-format/doc_format.odin @@ -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, From 5eea23cf76037bac4576959c306f82ad0aeded96 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 27 Jan 2022 16:09:05 +0000 Subject: [PATCH 050/117] Fix typo --- core/builtin/builtin.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/builtin/builtin.odin b/core/builtin/builtin.odin index 74283720f..259fdef37 100644 --- a/core/builtin/builtin.odin +++ b/core/builtin/builtin.odin @@ -2,7 +2,7 @@ package builtin nil :: nil; -false :: 0!==0; +false :: 0!=0; true :: 0==0; ODIN_OS :: ODIN_OS; From 3165b7cf95ad3b0773dd1ee36561dbdcea51f047 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 27 Jan 2022 16:09:33 +0000 Subject: [PATCH 051/117] Add `rand.exp_float64` --- core/math/rand/exp.odin | 214 +++++++++++++++++++++++++++++++++++++ core/math/rand/normal.odin | 14 ++- 2 files changed, 220 insertions(+), 8 deletions(-) create mode 100644 core/math/rand/exp.odin diff --git a/core/math/rand/exp.odin b/core/math/rand/exp.odin new file mode 100644 index 000000000..c0f92e99c --- /dev/null +++ b/core/math/rand/exp.odin @@ -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 + } + } +} \ No newline at end of file diff --git a/core/math/rand/normal.odin b/core/math/rand/normal.odin index 4a77543ba..a9edd0f19 100644 --- a/core/math/rand/normal.odin +++ b/core/math/rand/normal.odin @@ -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, From 38249372957db6a84151d14def3f50c02fe585b5 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 27 Jan 2022 16:30:22 +0000 Subject: [PATCH 052/117] Remove debug code --- src/docs_writer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/docs_writer.cpp b/src/docs_writer.cpp index 8b752ab71..0474ce8ff 100644 --- a/src/docs_writer.cpp +++ b/src/docs_writer.cpp @@ -881,7 +881,6 @@ OdinDocEntityIndex odin_doc_add_entity(OdinDocWriter *w, Entity *e) { default: GB_PANIC("Unhandled BuiltinProcPkg"); } - GB_PANIC("HERE"); } break; } From 2f3c5336d95be028fac795fe75b70fc271b15800 Mon Sep 17 00:00:00 2001 From: powerc9000 Date: Thu, 9 Dec 2021 13:03:27 -0700 Subject: [PATCH 053/117] Fix mutex and conditions trying to be destroyed twice in unix --- core/thread/thread_unix.odin | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/thread/thread_unix.odin b/core/thread/thread_unix.odin index cee278c7a..6cb91df86 100644 --- a/core/thread/thread_unix.odin +++ b/core/thread/thread_unix.odin @@ -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) } From 62cc752066ee3e07ca5523932aa4a6cdd839475b Mon Sep 17 00:00:00 2001 From: Jesse Stiller Date: Sun, 30 Jan 2022 13:57:01 +1000 Subject: [PATCH 054/117] Added round to HLSL and GLSL, and isinf/isfinite + isnan to HLSL --- core/math/linalg/glsl/linalg_glsl.odin | 19 +++++ core/math/linalg/hlsl/linalg_hlsl.odin | 80 +++++++++++++++++++++ core/math/linalg/hlsl/linalg_hlsl_math.odin | 5 ++ 3 files changed, 104 insertions(+) diff --git a/core/math/linalg/glsl/linalg_glsl.odin b/core/math/linalg/glsl/linalg_glsl.odin index 7bc68b964..74753f66f 100644 --- a/core/math/linalg/glsl/linalg_glsl.odin +++ b/core/math/linalg/glsl/linalg_glsl.odin @@ -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, diff --git a/core/math/linalg/hlsl/linalg_hlsl.odin b/core/math/linalg/hlsl/linalg_hlsl.odin index 4391975ba..3f73dcd1f 100644 --- a/core/math/linalg/hlsl/linalg_hlsl.odin +++ b/core/math/linalg/hlsl/linalg_hlsl.odin @@ -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, diff --git a/core/math/linalg/hlsl/linalg_hlsl_math.odin b/core/math/linalg/hlsl/linalg_hlsl_math.odin index d884c3d31..91c542b59 100644 --- a/core/math/linalg/hlsl/linalg_hlsl_math.odin +++ b/core/math/linalg/hlsl/linalg_hlsl_math.odin @@ -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 { From ebb8ca7c264c9b5b98e1388fcb2c6ef8bdc28d59 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 30 Jan 2022 21:35:05 +0000 Subject: [PATCH 055/117] Add `round` to linalg_glsl_math.odin --- core/math/linalg/glsl/linalg_glsl_math.odin | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/math/linalg/glsl/linalg_glsl_math.odin b/core/math/linalg/glsl/linalg_glsl_math.odin index 68f43a2f7..968a3fa5e 100644 --- a/core/math/linalg/glsl/linalg_glsl_math.odin +++ b/core/math/linalg/glsl/linalg_glsl_math.odin @@ -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 { From 35a826a0fdab5320462e9574f2a2f791bd913980 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 30 Jan 2022 21:38:34 +0000 Subject: [PATCH 056/117] Update CI to do `odin check examples/all` --- .github/workflows/ci.yml | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6742b56f3..575d2406d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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/local + run: ./odin check examples/all 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/local + run: ./odin check examples/all timeout-minutes: 10 - name: Core library tests run: | @@ -91,19 +97,24 @@ 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/local + run: | + call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat + odin check examples/all timeout-minutes: 10 - name: Core library tests shell: cmd From 1502066303fdb448ce83350419bb4b74fa9d6289 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 30 Jan 2022 21:43:42 +0000 Subject: [PATCH 057/117] Correct CI --- .github/workflows/ci.yml | 7 ++++--- examples/all/all_main.odin | 2 -- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 575d2406d..fcb909a14 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,7 +25,7 @@ jobs: - name: Odin run -debug run: ./odin run examples/demo -debug timeout-minutes: 10 - - name: Odin check examples/local + - name: Odin check examples/all run: ./odin check examples/all timeout-minutes: 10 - name: Core library tests @@ -65,7 +65,7 @@ jobs: - name: Odin run -debug run: ./odin run examples/demo -debug timeout-minutes: 10 - - name: Odin check examples/local + - name: Odin check examples/all run: ./odin check examples/all timeout-minutes: 10 - name: Core library tests @@ -111,7 +111,8 @@ jobs: call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat odin run examples/demo -debug timeout-minutes: 10 - - name: Odin check examples/local + - 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 diff --git a/examples/all/all_main.odin b/examples/all/all_main.odin index 199f406f7..b520faf4d 100644 --- a/examples/all/all_main.odin +++ b/examples/all/all_main.odin @@ -13,7 +13,6 @@ 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" @@ -49,7 +48,6 @@ 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" From 44ec95a983facb42ee815e12cf3355ae68406757 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 30 Jan 2022 21:55:55 +0000 Subject: [PATCH 058/117] Fix all_main.odin --- examples/all/all_main.odin | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/all/all_main.odin b/examples/all/all_main.odin index b520faf4d..1f4d4357c 100644 --- a/examples/all/all_main.odin +++ b/examples/all/all_main.odin @@ -114,7 +114,6 @@ _ :: libc _ :: compress _ :: gzip _ :: zlib -_ :: container _ :: bit_array _ :: priority_queue _ :: queue @@ -147,7 +146,6 @@ _ :: crypto_util _ :: whirlpool _ :: x25519 _ :: dynlib -_ :: encoding _ :: base32 _ :: base64 _ :: csv From da1edac56debf698d493b87a09cfd65f504bb51a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 31 Jan 2022 11:29:05 +0000 Subject: [PATCH 059/117] Enforce `-strict-style` in CI --- .github/workflows/ci.yml | 6 +++--- core/os/os_darwin.odin | 6 +++--- core/testing/runner_other.odin | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fcb909a14..a1f96d20b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: run: ./odin run examples/demo -debug timeout-minutes: 10 - name: Odin check examples/all - run: ./odin check examples/all + run: ./odin check examples/all -strict-style timeout-minutes: 10 - name: Core library tests run: | @@ -66,7 +66,7 @@ jobs: run: ./odin run examples/demo -debug timeout-minutes: 10 - name: Odin check examples/all - run: ./odin check examples/all + run: ./odin check examples/all -strict-style timeout-minutes: 10 - name: Core library tests run: | @@ -115,7 +115,7 @@ jobs: shell: cmd run: | call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat - odin check examples/all + odin check examples/all -strict-style timeout-minutes: 10 - name: Core library tests shell: cmd diff --git a/core/os/os_darwin.odin b/core/os/os_darwin.odin index b32453a5d..ef1d6185a 100644 --- a/core/os/os_darwin.odin +++ b/core/os/os_darwin.odin @@ -296,7 +296,7 @@ foreign libc { @(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="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,7 +307,7 @@ 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) -> ! --- } @@ -324,7 +324,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) { diff --git a/core/testing/runner_other.odin b/core/testing/runner_other.odin index 3978a3c83..f3271d209 100644 --- a/core/testing/runner_other.odin +++ b/core/testing/runner_other.odin @@ -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) { From 1a9ec776cbd183d74a6d62cc4b4ef8c0fa8f085d Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 31 Jan 2022 12:43:20 +0000 Subject: [PATCH 060/117] Unify logic for `slice.sort*` related procedures --- core/slice/sort.odin | 493 +---------------------------------- core/slice/sort_private.odin | 177 +++++++++++++ 2 files changed, 182 insertions(+), 488 deletions(-) create mode 100644 core/slice/sort_private.odin diff --git a/core/slice/sort.odin b/core/slice/sort.odin index d9755ad0e..24bce79af 100644 --- a/core/slice/sort.odin +++ b/core/slice/sort.odin @@ -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,7 @@ sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) { sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) { when size_of(E) != 0 { if n := len(data); n > 1 { - _quick_sort_cmp(data, 0, n, _max_depth(n), cmp) + _quick_sort_general(data, 0, n, _max_depth(n), cmp, .Cmp) } } } @@ -79,6 +74,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 +136,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.. 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.. bool) #no_bounds_check { - for i in a+1.. 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.. Ordering) #no_bounds_check { - for i in a+1.. 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) - } -} - - - diff --git a/core/slice/sort_private.odin b/core/slice/sort_private.odin new file mode 100644 index 000000000..3b990c1e7 --- /dev/null +++ b/core/slice/sort_private.odin @@ -0,0 +1,177 @@ +//+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.. 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.. Date: Mon, 31 Jan 2022 15:55:52 +0000 Subject: [PATCH 061/117] Add `slice.stable_sort*` procedures --- core/slice/slice.odin | 24 ++++++++++++------------ core/slice/sort.odin | 26 ++++++++++++++++++++++++++ core/slice/sort_private.odin | 23 +++++++++++++++++++++++ 3 files changed, 61 insertions(+), 12 deletions(-) diff --git a/core/slice/slice.odin b/core/slice/slice.odin index 426829a22..5fecc76b1 100644 --- a/core/slice/slice.odin +++ b/core/slice/slice.odin @@ -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 } diff --git a/core/slice/sort.odin b/core/slice/sort.odin index 24bce79af..8a2dec039 100644 --- a/core/slice/sort.odin +++ b/core/slice/sort.odin @@ -56,6 +56,32 @@ sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) { } } +// 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) + } + } +} + is_sorted :: proc(array: $T/[]$E) -> bool where ORD(E) { for i := len(array)-1; i > 0; i -= 1 { if array[i] < array[i-1] { diff --git a/core/slice/sort_private.odin b/core/slice/sort_private.odin index 3b990c1e7..05e4d5eed 100644 --- a/core/slice/sort_private.odin +++ b/core/slice/sort_private.odin @@ -175,3 +175,26 @@ _quick_sort_general :: proc(data: $T/[]$E, a, b, max_depth: int, call: $P, $KIND 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.. 0 && less(data[j], data[j-1], call); j -= 1 { + swap(data, j, j-1) + } + } +} From 2f1aeaf757bce1ebc37bd5e63dfcdfe22685deaf Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 31 Jan 2022 15:56:40 +0000 Subject: [PATCH 062/117] Remove the unneeded `$` --- core/slice/sort_private.odin | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/slice/sort_private.odin b/core/slice/sort_private.odin index 05e4d5eed..7abd2f1ce 100644 --- a/core/slice/sort_private.odin +++ b/core/slice/sort_private.odin @@ -13,7 +13,7 @@ Sort_Kind :: enum { } _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 { + less :: #force_inline proc(a, b: E, call: P) -> bool { when KIND == .Ordered { return a < b } else when KIND == .Less { @@ -179,7 +179,7 @@ _quick_sort_general :: proc(data: $T/[]$E, a, b, max_depth: int, call: $P, $KIND // 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 { + less :: #force_inline proc(a, b: E, call: P) -> bool { when KIND == .Ordered { return a < b } else when KIND == .Less { From 67ba05cb7cfee60daaf257230ddbc4f1e0a9f8ac Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 31 Jan 2022 19:33:02 +0000 Subject: [PATCH 063/117] Correct false positive check in `check_unique_package_names` --- src/checker.cpp | 10 ++++++++-- src/parser.cpp | 5 +++++ src/parser_pos.cpp | 6 ++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/checker.cpp b/src/checker.cpp index 038709056..d9a1af0d1 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -5307,12 +5307,18 @@ void check_unique_package_names(Checker *c) { string_map_set(&pkgs, key, pkg); continue; } + auto *this = pkg->files[0]->pkg_decl; + auto *other = (*found)->files[0]->pkg_decl; + if (this == other) { + // NOTE(bill): A false positive was found, ignore it + continue; + } - error(pkg->files[0]->pkg_decl, "Duplicate declaration of 'package %.*s'", LIT(name)); + error(this, "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(other, "found at previous location"); } } diff --git a/src/parser.cpp b/src/parser.cpp index 9cc9adfc9..7a858e520 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -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); diff --git a/src/parser_pos.cpp b/src/parser_pos.cpp index 6ef0db215..54c3ec1f1 100644 --- a/src/parser_pos.cpp +++ b/src/parser_pos.cpp @@ -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); From 85706d559d06998895b27710f5e4f4643443b032 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 31 Jan 2022 20:19:46 +0000 Subject: [PATCH 064/117] Fix typo --- src/checker.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/checker.cpp b/src/checker.cpp index d9a1af0d1..d50d4d176 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -5307,18 +5307,18 @@ void check_unique_package_names(Checker *c) { string_map_set(&pkgs, key, pkg); continue; } - auto *this = pkg->files[0]->pkg_decl; - auto *other = (*found)->files[0]->pkg_decl; - if (this == other) { + 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(this, "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(other, "found at previous location"); + error(prev, "found at previous location"); } } From eac74631ecb74689dbe6bb1e1d07cd15f1fc677a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 1 Feb 2022 14:11:19 +0000 Subject: [PATCH 065/117] Correct debug information logic for procedure parameters --- src/llvm_backend.hpp | 1 + src/llvm_backend_debug.cpp | 71 ++++++++++++++++++++++++++++++++++++++ src/llvm_backend_proc.cpp | 9 ++--- 3 files changed, 77 insertions(+), 4 deletions(-) diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 49f675a49..d7093bc63 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -232,6 +232,7 @@ struct lbTargetList { enum lbProcedureFlag : u32 { lbProcedureFlag_WithoutMemcpyPass = 1<<0, + lbProcedureFlag_DebugAllocaCopy = 1<<1, }; struct lbCopyElisionHint { diff --git a/src/llvm_backend_debug.cpp b/src/llvm_backend_debug.cpp index 7a2b00fe9..f60096aad 100644 --- a/src/llvm_backend_debug.cpp +++ b/src/llvm_backend_debug.cpp @@ -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; diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 9f9fe7c7a..7a6fac603 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -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,20 +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_local_variable(p, ptr.value, e->type, e->token); + 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_local_variable(p, ptr.value, e->type, e->token); + lb_add_debug_param_variable(p, ptr.value, e->type, e->token, param_index+1); } } - param_index += 1; } } From 8c9505505a0bf335a990b5ca05650aa6dcd08c30 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 1 Feb 2022 15:23:49 +0000 Subject: [PATCH 066/117] Add allocator parameter to `rand.perm` --- core/math/rand/rand.odin | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/math/rand/rand.odin b/core/math/rand/rand.odin index 04e2c6414..29254d8f4 100644 --- a/core/math/rand/rand.odin +++ b/core/math/rand/rand.odin @@ -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] From a04d849e30da1252e56d29ee18e2a51a5b6cb0d5 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 1 Feb 2022 15:24:37 +0000 Subject: [PATCH 067/117] `core:container/lru` --- core/container/lru/lru_cache.odin | 183 ++++++++++++++++++++++++++++++ examples/all/all_main.odin | 3 +- 2 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 core/container/lru/lru_cache.odin diff --git a/core/container/lru/lru_cache.odin b/core/container/lru/lru_cache.odin new file mode 100644 index 000000000..02bb20da0 --- /dev/null +++ b/core/container/lru/lru_cache.odin @@ -0,0 +1,183 @@ +package container_lru + +import "core:intrinsics" +import "core:mem" +_ :: intrinsics +_ :: mem + +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: mem.Allocator, + + on_remove: proc(key: Key, value: Value, user_data: rawptr), + on_remove_user_data: rawptr, + call_on_remove_on_destroy: bool, +} + +// 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 Cache +destroy :: proc(c: ^$C/Cache($Key, $Value)) { + for _, node in c.entries { + if c.call_on_remove_on_destroy && c.on_remove != nil { + c.on_remove(node.key, node.value, c.on_remove_user_data) + } + free(node, c.node_allocator) + } + clear(&c.entries) + delete(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) -> mem.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) + + if c.on_remove != nil { + c.on_remove(node.key, node.value, c.on_remove_user_data) + } + + free(node, c.node_allocator) + +} + +@(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 +} \ No newline at end of file diff --git a/examples/all/all_main.odin b/examples/all/all_main.odin index 1f4d4357c..e38dd5150 100644 --- a/examples/all/all_main.odin +++ b/examples/all/all_main.odin @@ -16,7 +16,8 @@ import zlib "core:compress/zlib" import bit_array "core:container/bit_array" import priority_queue "core:container/priority_queue" import queue "core:container/queue" -import small_array "core:container/queue" +import small_array "core:container/small_array" +import lru "core:container/lru" import crypto "core:crypto" import blake "core:crypto/blake" From 78815778ee399b4df1c5f7c44522c792b9dc3e23 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 2 Feb 2022 15:28:49 +0000 Subject: [PATCH 068/117] Add `//+private file` to complement `//+private` (`//+private package`) --- src/checker.cpp | 9 ++++++--- src/entity.cpp | 2 +- src/parser.cpp | 12 ++++++++++-- src/parser.hpp | 8 +++++--- src/string.cpp | 12 ++++++++++-- 5 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/checker.cpp b/src/checker.cpp index d50d4d176..4dcb5120f 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -3467,9 +3467,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_IsPrivatePkg) { + entity_visibility_kind = EntityVisiblity_PrivateToPackage; + } else if (c->scope->file->flags & AstFile_IsPrivateFile) { + entity_visibility_kind = EntityVisiblity_PrivateToFile; + } } if (entity_visibility_kind != EntityVisiblity_Public && !(c->scope->flags&ScopeFlag_File)) { diff --git a/src/entity.cpp b/src/entity.cpp index a0438a9f4..8327a517e 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -245,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; } diff --git a/src/parser.cpp b/src/parser.cpp index 7a858e520..bf8c909c2 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -5535,8 +5535,16 @@ 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 ")); + 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 diff --git a/src/parser.hpp b/src/parser.hpp index 656f709e8..0712e83cb 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -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 { diff --git a/src/string.cpp b/src/string.cpp index 800378689..eb6058f78 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -195,8 +195,6 @@ template bool operator > (String const &a, char const (&b)[N]) { retu template bool operator <= (String const &a, char const (&b)[N]) { return str_le(a, make_string(cast(u8 *)b, N-1)); } template 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; From 5db603ded27b8cb6dac444fa660009fd7ecc5184 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 2 Feb 2022 15:39:41 +0000 Subject: [PATCH 069/117] Minor sanity clean up --- src/parser.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/parser.cpp b/src/parser.cpp index bf8c909c2..6db71bc4a 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -5538,6 +5538,7 @@ bool parse_file(Parser *p, AstFile *f) { } 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") { From e190c024fd374aff56f8cd0cf81a16ef4b4b0542 Mon Sep 17 00:00:00 2001 From: Andrea Piseri Date: Wed, 2 Feb 2022 20:07:38 +0100 Subject: [PATCH 070/117] Fix logic in `is_nil` procedure: a non_nil slice means there is data to check. --- core/reflect/reflect.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/reflect/reflect.odin b/core/reflect/reflect.odin index 7f64d0974..05b3a5da0 100644 --- a/core/reflect/reflect.odin +++ b/core/reflect/reflect.odin @@ -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 { From 35533a7baab4cbea175e5585f7e661abddb7a44d Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 2 Feb 2022 23:38:32 +0000 Subject: [PATCH 071/117] Update `core:container/lru` to support `clear` and take a boolean to indicate whether or not to call the `on_remove` procedure on `clear` or `destroy` --- core/container/lru/lru_cache.odin | 37 +++++++++++++++++++------------ 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/core/container/lru/lru_cache.odin b/core/container/lru/lru_cache.odin index 02bb20da0..f8e6f7b46 100644 --- a/core/container/lru/lru_cache.odin +++ b/core/container/lru/lru_cache.odin @@ -1,9 +1,9 @@ package container_lru +import "core:runtime" import "core:intrinsics" -import "core:mem" +_ :: runtime _ :: intrinsics -_ :: mem Node :: struct($Key, $Value: typeid) where intrinsics.type_is_valid_map_key(Key) { prev, next: ^Node(Key, Value), @@ -23,11 +23,10 @@ Cache :: struct($Key, $Value: typeid) where intrinsics.type_is_valid_map_key(Key count: int, capacity: int, - node_allocator: mem.Allocator, + node_allocator: runtime.Allocator, on_remove: proc(key: Key, value: Value, user_data: rawptr), on_remove_user_data: rawptr, - call_on_remove_on_destroy: bool, } // init initializes a Cache @@ -37,23 +36,28 @@ init :: proc(c: ^$C/Cache($Key, $Value), capacity: int, entries_allocator := con c.capacity = capacity } -// destroy deinitializes a Cache -destroy :: proc(c: ^$C/Cache($Key, $Value)) { +// 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 c.call_on_remove_on_destroy && c.on_remove != nil { - c.on_remove(node.key, node.value, c.on_remove_user_data) + if call_on_remove { + _call_on_remove(c, node) } free(node, c.node_allocator) } - clear(&c.entries) - delete(c.entries) + 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) -> mem.Allocator_Error { +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 @@ -143,14 +147,19 @@ _remove_node :: proc(c: ^$C/Cache($Key, $Value), node: ^Node(Key, Value)) { delete_key(&c.entries, node.key) - if c.on_remove != nil { - c.on_remove(node.key, node.value, c.on_remove_user_data) - } + _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 { From df8bdac33f9c8333db64516f27b3c2b727ff7d2b Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 3 Feb 2022 00:31:36 +0000 Subject: [PATCH 072/117] Initialize the `global_rand` with the `intrinsics.read_cycle_counter()` value --- core/math/rand/rand.odin | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/math/rand/rand.odin b/core/math/rand/rand.odin index 29254d8f4..19e475835 100644 --- a/core/math/rand/rand.odin +++ b/core/math/rand/rand.odin @@ -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) From 35c90fe12413335962cad02d77a4894079b00a5d Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 3 Feb 2022 13:34:31 +0000 Subject: [PATCH 073/117] Fix type alias declaration evaluation problem (#854 #1439) --- src/check_decl.cpp | 39 +++++++++++++++- src/check_expr.cpp | 113 +++++++++++++++++++++++++++++++++++++++------ src/checker.cpp | 3 -- 3 files changed, 137 insertions(+), 18 deletions(-) diff --git a/src/check_decl.cpp b/src/check_decl.cpp index f9bc17ba4..193c28aea 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -385,7 +385,44 @@ 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); + if (entity != nullptr && entity->kind == Entity_TypeName) { + // 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) { diff --git a/src/check_expr.cpp b/src/check_expr.cpp index fb5a90f5a..88296611b 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -1286,7 +1286,6 @@ bool check_cycle(CheckerContext *c, Entity *curr, bool report) { return false; } - Entity *check_ident(CheckerContext *c, Operand *o, Ast *n, Type *named_type, Type *type_hint, bool allow_import_name) { GB_ASSERT(n->kind == Ast_Ident); o->mode = Addressing_Invalid; @@ -1422,8 +1421,12 @@ Entity *check_ident(CheckerContext *c, Operand *o, Ast *n, Type *named_type, Typ case Entity_TypeName: o->mode = Addressing_Type; if (check_cycle(c, e, true)) { - type = t_invalid; + o->type = t_invalid; } + if (o->type != nullptr && type->kind == Type_Named && o->type->Named.type_name->TypeName.is_type_alias) { + o->type = base_type(o->type); + } + break; case Entity_ImportName: @@ -4064,6 +4067,98 @@ Type *determine_swizzle_array_type(Type *original_type, Type *type_hint, isize n } +bool is_entity_declared_for_selector(Entity *entity, Scope *import_scope, bool *allow_builtin) { + bool is_declared = entity != nullptr; + if (is_declared) { + if (entity->kind == Entity_Builtin) { + // NOTE(bill): Builtin's are in the universal scope which is part of every scopes hierarchy + // This means that we should just ignore the found result through it + *allow_builtin = entity->scope == import_scope || entity->scope != builtin_pkg->scope; + } else if ((entity->scope->flags&ScopeFlag_Global) == ScopeFlag_Global && (import_scope->flags&ScopeFlag_Global) == 0) { + is_declared = false; + } + } + return is_declared; +} + +// NOTE(bill, 2022-02-03): see `check_const_decl` for why it exists reasoning +Entity *check_entity_from_ident_or_selector(CheckerContext *c, Ast *node) { + if (node->kind == Ast_Ident) { + String name = node->Ident.token.string; + return scope_lookup(c->scope, name); + } else if (node->kind == Ast_SelectorExpr) { + ast_node(se, SelectorExpr, node); + if (!c->allow_arrow_right_selector_expr && se->token.kind == Token_ArrowRight) { + return nullptr; + } + + Ast *op_expr = se->expr; + Ast *selector = unparen_expr(se->selector); + if (selector == nullptr) { + return nullptr; + } + if (selector->kind != Ast_Ident) { + return nullptr; + } + + Entity *entity = nullptr; + Entity *expr_entity = nullptr; + bool check_op_expr = true; + + if (op_expr->kind == Ast_Ident) { + String op_name = op_expr->Ident.token.string; + Entity *e = scope_lookup(c->scope, op_name); + add_entity_use(c, op_expr, e); + expr_entity = e; + + if (e != nullptr && e->kind == Entity_ImportName && selector->kind == Ast_Ident) { + // IMPORTANT NOTE(bill): This is very sloppy code but it's also very fragile + // It pretty much needs to be in this order and this way + // If you can clean this up, please do but be really careful + String import_name = op_name; + Scope *import_scope = e->ImportName.scope; + String entity_name = selector->Ident.token.string; + + check_op_expr = false; + entity = scope_lookup_current(import_scope, entity_name); + bool allow_builtin = false; + if (!is_entity_declared_for_selector(entity, import_scope, &allow_builtin)) { + return nullptr; + } + + check_entity_decl(c, entity, nullptr, nullptr); + if (entity->kind == Entity_ProcGroup) { + return entity; + } + GB_ASSERT_MSG(entity->type != nullptr, "%.*s (%.*s)", LIT(entity->token.string), LIT(entity_strings[entity->kind])); + } + } + + Operand operand = {}; + if (check_op_expr) { + check_expr_base(c, &operand, op_expr, nullptr); + if (operand.mode == Addressing_Invalid) { + return nullptr; + } + } + + if (entity == nullptr && selector->kind == Ast_Ident) { + String field_name = selector->Ident.token.string; + if (is_type_dynamic_array(type_deref(operand.type))) { + init_mem_allocator(c->checker); + } + auto sel = lookup_field(operand.type, field_name, operand.mode == Addressing_Type); + entity = sel.entity; + } + + if (entity != nullptr) { + return entity; + } + } + return nullptr; +} + + Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *type_hint) { ast_node(se, SelectorExpr, node); @@ -4112,18 +4207,8 @@ Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *typ check_op_expr = false; entity = scope_lookup_current(import_scope, entity_name); - bool is_declared = entity != nullptr; bool allow_builtin = false; - if (is_declared) { - if (entity->kind == Entity_Builtin) { - // NOTE(bill): Builtin's are in the universal scope which is part of every scopes hierarchy - // This means that we should just ignore the found result through it - allow_builtin = entity->scope == import_scope || entity->scope != builtin_pkg->scope; - } else if ((entity->scope->flags&ScopeFlag_Global) == ScopeFlag_Global && (import_scope->flags&ScopeFlag_Global) == 0) { - is_declared = false; - } - } - if (!is_declared) { + if (!is_entity_declared_for_selector(entity, import_scope, &allow_builtin)) { error(op_expr, "'%.*s' is not declared by '%.*s'", LIT(entity_name), LIT(import_name)); operand->mode = Addressing_Invalid; operand->expr = node; @@ -4213,7 +4298,7 @@ Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *typ } } - if (entity == nullptr && selector->kind == Ast_Ident && is_type_array(type_deref(operand->type))) { + if (entity == nullptr && selector->kind == Ast_Ident && is_type_array(type_deref(operand->type))) { // TODO(bill): Simd_Vector swizzling String field_name = selector->Ident.token.string; diff --git a/src/checker.cpp b/src/checker.cpp index 4dcb5120f..c4423b2bc 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -3563,9 +3563,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"); From cf9f3d5e2d33a9004a322db980de307de13dc3a0 Mon Sep 17 00:00:00 2001 From: Andrea Piseri Date: Thu, 3 Feb 2022 15:50:39 +0100 Subject: [PATCH 074/117] fix logic in bswap_128 --- core/runtime/internal.odin | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/core/runtime/internal.odin b/core/runtime/internal.odin index 7b283a132..c07bcc60d 100644 --- a/core/runtime/internal.odin +++ b/core/runtime/internal.odin @@ -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 } From 76edfae0e0a1da7435f8f0e30a53ae4a70c74ba7 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 4 Feb 2022 12:08:20 +0000 Subject: [PATCH 075/117] `core:container/topological_sort` --- .../topological_sort/topological_sort.odin | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 core/container/topological_sort/topological_sort.odin diff --git a/core/container/topological_sort/topological_sort.odin b/core/container/topological_sort/topological_sort.odin new file mode 100644 index 000000000..4b69930d5 --- /dev/null +++ b/core/container/topological_sort/topological_sort.odin @@ -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 +} \ No newline at end of file From 48af78e46981540b9071b382052777060ba83c23 Mon Sep 17 00:00:00 2001 From: Andrea Piseri Date: Fri, 4 Feb 2022 22:12:07 +0100 Subject: [PATCH 076/117] add `iterator` to `core:container/bit_array` --- core/container/bit_array/bit_array.odin | 43 ++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/core/container/bit_array/bit_array.odin b/core/container/bit_array/bit_array.odin index 0fa80c623..f06cf74e7 100644 --- a/core/container/bit_array/bit_array.odin +++ b/core/container/bit_array/bit_array.odin @@ -11,11 +11,52 @@ INDEX_SHIFT :: 6 @(private="file") INDEX_MASK :: 63 +@(private="file") +NUM_BITS :: 64 + Bit_Array :: struct { bits: [dynamic]u64, bias: int, } +Bit_Array_Iterator :: struct { + array: ^Bit_Array, + current_word: uint, + current_bit: uint, +} + +/* + 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 +*/ +iterator :: proc (it: ^Bit_Array_Iterator) -> (int, bool) { + words := it.array.bits + // if the word is empty or we have already gone over all the bits in it, + // b.current_bit is greater than the index of any set bit in the word, + // meaning that word >> b.current_bit == 0. + for it.current_word < len(words) && (words[it.current_word] >> it.current_bit == 0) { + it.current_word += 1 + it.current_bit = 0 + } + + if it.current_word >= len(words) { return 0, false } + + // since we exited the loop and didn't return, this word has some bits higher than + // or equal to `it.current_bit` set. + offset := intrinsics.count_trailing_zeros(words[it.current_word] >> it.current_bit) + // skip over the bit, if the resulting it.current_bit is over 63, + // it is handled by the initial for loop in the next iteration. + it.current_bit += uint(offset) + defer it.current_bit += 1 + return int(it.current_word * NUM_BITS + it.current_bit) + it.array.bias, true +} + + /* In: - ba: ^Bit_Array - a pointer to the Bit Array @@ -121,4 +162,4 @@ resize_if_needed :: proc(ba: ^Bit_Array, legs: int, allocator := context.allocat resize(&ba.bits, legs + 1) } return len(ba.bits) > legs -} \ No newline at end of file +} From b54fc96b1e36ff83922d7af9d8126e3fff0d8078 Mon Sep 17 00:00:00 2001 From: ap29600 <66381278+ap29600@users.noreply.github.com> Date: Fri, 4 Feb 2022 22:39:47 +0100 Subject: [PATCH 077/117] rename `iterator` proc to `next`, add named return values --- core/container/bit_array/bit_array.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/container/bit_array/bit_array.odin b/core/container/bit_array/bit_array.odin index f06cf74e7..bf2ae3a40 100644 --- a/core/container/bit_array/bit_array.odin +++ b/core/container/bit_array/bit_array.odin @@ -34,7 +34,7 @@ Bit_Array_Iterator :: struct { - ok: bool - `true` if the iterator returned a valid index, `false` if there were no more bits set */ -iterator :: proc (it: ^Bit_Array_Iterator) -> (int, bool) { +next :: proc (it: ^Bit_Array_Iterator) -> (index: int, ok: bool) { words := it.array.bits // if the word is empty or we have already gone over all the bits in it, // b.current_bit is greater than the index of any set bit in the word, From 3a81f2ab898d537bba51b9ea81e047652112574e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 4 Feb 2022 22:40:15 +0000 Subject: [PATCH 078/117] Correct the type aliasing problem, caused by aliases (of aliases)+ --- src/check_decl.cpp | 1 + src/check_expr.cpp | 5 +++- src/checker.cpp | 66 +++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 70 insertions(+), 2 deletions(-) diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 193c28aea..2454feb33 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -387,6 +387,7 @@ void check_const_decl(CheckerContext *ctx, Entity *e, Ast *type_expr, Ast *init, if (init != nullptr) { Entity *entity = check_entity_from_ident_or_selector(ctx, init); 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 // diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 88296611b..e1c9bde84 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -4088,7 +4088,7 @@ Entity *check_entity_from_ident_or_selector(CheckerContext *c, Ast *node) { return scope_lookup(c->scope, name); } else if (node->kind == Ast_SelectorExpr) { ast_node(se, SelectorExpr, node); - if (!c->allow_arrow_right_selector_expr && se->token.kind == Token_ArrowRight) { + if (se->token.kind == Token_ArrowRight) { return nullptr; } @@ -4108,6 +4108,9 @@ Entity *check_entity_from_ident_or_selector(CheckerContext *c, Ast *node) { if (op_expr->kind == Ast_Ident) { String op_name = op_expr->Ident.token.string; Entity *e = scope_lookup(c->scope, op_name); + if (e == nullptr) { + return nullptr; + } add_entity_use(c, op_expr, e); expr_entity = e; diff --git a/src/checker.cpp b/src/checker.cpp index c4423b2bc..c90f357dd 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -3665,6 +3665,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); + 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 const &nodes) { AstFile *curr_file = nullptr; @@ -3736,6 +3789,7 @@ void check_collect_entities(CheckerContext *c, Slice 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 @@ -4381,10 +4435,11 @@ bool collect_file_decls(CheckerContext *ctx, Slice 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; } @@ -4654,6 +4709,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); From d5384c5aa4d823fbd527fb82e9eb5559b4266dfd Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 4 Feb 2022 22:45:13 +0000 Subject: [PATCH 079/117] Only check idents in the alias (of alias)+ problem --- src/check_decl.cpp | 2 +- src/check_expr.cpp | 4 ++-- src/checker.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 2454feb33..63fc777c0 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -385,7 +385,7 @@ void check_const_decl(CheckerContext *ctx, Entity *e, Ast *type_expr, Ast *init, Operand operand = {}; if (init != nullptr) { - Entity *entity = check_entity_from_ident_or_selector(ctx, init); + 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 diff --git a/src/check_expr.cpp b/src/check_expr.cpp index e1c9bde84..d51444b4d 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -4082,11 +4082,11 @@ bool is_entity_declared_for_selector(Entity *entity, Scope *import_scope, bool * } // NOTE(bill, 2022-02-03): see `check_const_decl` for why it exists reasoning -Entity *check_entity_from_ident_or_selector(CheckerContext *c, Ast *node) { +Entity *check_entity_from_ident_or_selector(CheckerContext *c, Ast *node, bool ident_only) { if (node->kind == Ast_Ident) { String name = node->Ident.token.string; return scope_lookup(c->scope, name); - } else if (node->kind == Ast_SelectorExpr) { + } else if (!ident_only) if (node->kind == Ast_SelectorExpr) { ast_node(se, SelectorExpr, node); if (se->token.kind == Token_ArrowRight) { return nullptr; diff --git a/src/checker.cpp b/src/checker.cpp index c90f357dd..188d68502 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -3670,7 +3670,7 @@ bool correct_single_type_alias(CheckerContext *c, Entity *e) { 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); + 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; From 1553137c2365c3980488a6455fd83f0fcb9e28ca Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 5 Feb 2022 00:04:02 +0000 Subject: [PATCH 080/117] Change behaviour of `A :: distinct Enum_Type` to be more intuitive --- src/check_decl.cpp | 51 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 63fc777c0..f6dade812 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -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(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'"); From 97be86710306702a672309b23fbe8d38f1e6eeec Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 5 Feb 2022 13:01:15 +0000 Subject: [PATCH 081/117] Rename `#partial[Enum]Type` to `#sparse[Enum]Type` for non-contiguous enum fields --- core/reflect/types.odin | 3 +++ core/runtime/core.odin | 1 + core/runtime/print.odin | 3 +++ src/check_type.cpp | 13 +++++++------ src/llvm_backend_type.cpp | 4 +++- src/parser.cpp | 2 +- src/types.cpp | 4 ++++ 7 files changed, 22 insertions(+), 8 deletions(-) diff --git a/core/reflect/types.odin b/core/reflect/types.odin index 74778013a..a9a4a8d48 100644 --- a/core/reflect/types.odin +++ b/core/reflect/types.odin @@ -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 diff --git a/core/runtime/core.odin b/core/runtime/core.odin index 424650828..35144473b 100644 --- a/core/runtime/core.odin +++ b/core/runtime/core.odin @@ -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} diff --git a/core/runtime/print.odin b/core/runtime/print.odin index 8c0b65864..06740bc75 100644 --- a/core/runtime/print.odin +++ b/core/runtime/print.odin @@ -260,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(']') diff --git a/src/check_type.cpp b/src/check_type.cpp index a6d82c86e..6d3e32466 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -2713,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; diff --git a/src/llvm_backend_type.cpp b/src/llvm_backend_type.cpp index e1332c6f3..1d6297164 100644 --- a/src/llvm_backend_type.cpp +++ b/src/llvm_backend_type.cpp @@ -454,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, @@ -463,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 = {}; diff --git a/src/parser.cpp b/src/parser.cpp index 6db71bc4a..7302b18a9 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -2134,7 +2134,7 @@ Ast *parse_operand(AstFile *f, bool lhs) { break; } return original_type; - } else if (name.string == "partial") { + } 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); diff --git a/src/types.cpp b/src/types.cpp index 07951196a..e0d35a12c 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -221,6 +221,7 @@ struct TypeProc { ExactValue *max_value; \ i64 count; \ TokenKind op; \ + bool is_sparse; \ }) \ TYPE_KIND(Slice, struct { Type *elem; }) \ TYPE_KIND(DynamicArray, struct { Type *elem; }) \ @@ -3830,6 +3831,9 @@ gbString write_type_to_string(gbString str, Type *type) { break; case Type_EnumeratedArray: + if (type->EnumeratedArray.is_sparse) { + str = gb_string_appendc(str, "#sparse"); + } str = gb_string_append_rune(str, '['); str = write_type_to_string(str, type->EnumeratedArray.index); str = gb_string_append_rune(str, ']'); From 6418ec3b21de26bac4b291a2ad8e58c011c21c38 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 5 Feb 2022 13:09:16 +0000 Subject: [PATCH 082/117] Correct `#sparse` usage and error messages --- core/math/big/common.odin | 2 +- examples/demo/demo.odin | 14 +++++++------- src/parser.cpp | 16 ++++++++++++++++ src/parser.hpp | 1 + 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/core/math/big/common.odin b/core/math/big/common.odin index 2b34a9163..e1198c352 100644 --- a/core/math/big/common.odin +++ b/core/math/big/common.odin @@ -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", diff --git a/examples/demo/demo.odin b/examples/demo/demo.odin index 3e34e3d49..8c6ea0fa4 100644 --- a/examples/demo/demo.odin +++ b/examples/demo/demo.odin @@ -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("-------") diff --git a/src/parser.cpp b/src/parser.cpp index 7302b18a9..0914c77ca 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -2134,6 +2134,22 @@ Ast *parse_operand(AstFile *f, bool lhs) { break; } 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); diff --git a/src/parser.hpp b/src/parser.hpp index 0712e83cb..ff0df0382 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -350,6 +350,7 @@ char const *inline_asm_dialect_strings[InlineAsmDialect_COUNT] = { Slice elems; \ Token open, close; \ i64 max_count; \ + Ast *tag; \ }) \ AST_KIND(_ExprBegin, "", bool) \ AST_KIND(BadExpr, "bad expression", struct { Token begin, end; }) \ From e870041fe6171b7e88cde672a3e5478d3786b3c9 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 5 Feb 2022 13:11:41 +0000 Subject: [PATCH 083/117] Fix `#sparse` usage --- core/compress/gzip/gzip.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/compress/gzip/gzip.odin b/core/compress/gzip/gzip.odin index 1a72500bf..0ed805ef8 100644 --- a/core/compress/gzip/gzip.odin +++ b/core/compress/gzip/gzip.odin @@ -66,7 +66,7 @@ OS :: enum u8 { _Unknown = 14, Unknown = 255, } -OS_Name :: #partial [OS]string{ +OS_Name :: #sparse[OS]string{ .FAT = "FAT", .Amiga = "Amiga", .VMS = "VMS/OpenVMS", From b8c4bf2afb39ca2980b2827aa1775b35728bb195 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 5 Feb 2022 14:02:21 +0000 Subject: [PATCH 084/117] Add `#partial [Enum]Type{...}` support to check for missing enumerated array fields --- core/compress/gzip/gzip.odin | 1 + core/math/big/common.odin | 1 + src/check_expr.cpp | 145 +++++++++++++++++++++++++++++++++++ src/check_stmt.cpp | 90 +--------------------- 4 files changed, 149 insertions(+), 88 deletions(-) diff --git a/core/compress/gzip/gzip.odin b/core/compress/gzip/gzip.odin index 0ed805ef8..96e9c49a0 100644 --- a/core/compress/gzip/gzip.odin +++ b/core/compress/gzip/gzip.odin @@ -67,6 +67,7 @@ OS :: enum u8 { Unknown = 255, } OS_Name :: #sparse[OS]string{ + ._Unknown = "", .FAT = "FAT", .Amiga = "Amiga", .VMS = "VMS/OpenVMS", diff --git a/core/math/big/common.odin b/core/math/big/common.odin index e1198c352..74a641d83 100644 --- a/core/math/big/common.odin +++ b/core/math/big/common.odin @@ -182,6 +182,7 @@ Error_String :: #sparse[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", diff --git a/src/check_expr.cpp b/src/check_expr.cpp index d51444b4d..40777df2a 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -6956,6 +6956,100 @@ void check_matrix_index_expr(CheckerContext *c, Operand *o, Ast *node, Type *typ } +struct TypeAndToken { + Type *type; + Token token; +}; + +void add_constant_switch_case(CheckerContext *ctx, PtrMap *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); +} + +typedef PtrMap SeenMap; + +void add_to_seen_map(CheckerContext *ctx, SeenMap *seen, TokenKind upper_op, Operand const &x, Operand const &lhs, Operand const &rhs) { + 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); + } + } +} +void add_to_seen_map(CheckerContext *ctx, SeenMap *seen, Operand const &x) { + add_constant_switch_case(ctx, seen, x); +} + + ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) { u32 prev_state_flags = c->state_flags; defer (c->state_flags = prev_state_flags); @@ -7863,6 +7957,11 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type if (bet == t_invalid) { break; } + bool is_partial = cl->tag && (cl->tag->BasicDirective.name.string == "partial"); + + SeenMap seen = {}; // NOTE(bill): Multimap, Key: ExactValue + map_init(&seen, heap_allocator()); + defer (map_destroy(&seen)); if (cl->elems.count > 0 && cl->elems[0]->kind == Ast_FieldValue) { RangeCache rc = range_cache_make(heap_allocator()); @@ -7936,6 +8035,8 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type check_assignment(c, &operand, elem_type, context_name); is_constant = is_constant && operand.mode == Addressing_Constant; + + add_to_seen_map(c, &seen, op.kind, x, x, y); } else { Operand op_index = {}; check_expr_with_type_hint(c, &op_index, fv->field, index_type); @@ -7971,6 +8072,8 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type check_assignment(c, &operand, elem_type, context_name); is_constant = is_constant && operand.mode == Addressing_Constant; + + add_to_seen_map(c, &seen, op_index); } } @@ -8006,11 +8109,53 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type } } + bool was_error = false; if (cl->elems.count > 0 && cl->elems[0]->kind != Ast_FieldValue) { if (0 < max && max < t->EnumeratedArray.count) { error(node, "Expected %lld values for this enumerated array literal, got %lld", cast(long long)t->EnumeratedArray.count, cast(long long)max); + was_error = true; } else { error(node, "Enumerated array literals must only have 'field = value' elements, bare elements are not allowed"); + was_error = true; + } + } + + // NOTE(bill): Check for missing cases when `#partial literal` is not present + if (cl->elems.count > 0 && !was_error && !is_partial) { + Type *et = base_type(index_type); + GB_ASSERT(et->kind == Type_Enum); + auto fields = et->Enum.fields; + + auto unhandled = array_make(temporary_allocator(), 0, fields.count); + + for_array(i, fields) { + Entity *f = fields[i]; + if (f->kind != Entity_Constant) { + continue; + } + ExactValue v = f->Constant.value; + auto found = map_get(&seen, hash_exact_value(v)); + if (!found) { + array_add(&unhandled, f); + } + } + + if (unhandled.count > 0) { + begin_error_block(); + defer (end_error_block()); + + if (unhandled.count == 1) { + error_no_newline(node, "Unhandled enumerated array case: %.*s", LIT(unhandled[0]->token.string)); + } else { + error_no_newline(node, "Unhandled enumerated array cases: "); + for_array(i, unhandled) { + Entity *f = unhandled[i]; + error_line("\t%.*s\n", LIT(f->token.string)); + } + } + error_line("\n"); + + error_line("\tSuggestion: Was '#partial %s {...}' wanted?\n", type_to_string(index_type)); } } diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index f9e55ab37..50b7c3233 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -697,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 *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); @@ -1032,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 @@ -1115,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); } } } From dd84b61cc83c6bb3a179375f0a37adf6782b3be8 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 5 Feb 2022 14:07:17 +0000 Subject: [PATCH 085/117] Correct `add_to_seen_map` logic --- src/check_expr.cpp | 10 +++++++--- src/check_stmt.cpp | 6 +++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 40777df2a..b2ce6c897 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -7018,7 +7018,7 @@ void add_to_seen_map(CheckerContext *ctx, SeenMap *seen, TokenKind upper_op, Ope 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) { + if (upper_op != Token_LtEq && vi == v1) { break; } @@ -7040,7 +7040,7 @@ void add_to_seen_map(CheckerContext *ctx, SeenMap *seen, TokenKind upper_op, Ope } } else { add_constant_switch_case(ctx, seen, lhs); - if (upper_op == Token_GtEq) { + if (upper_op == Token_LtEq) { add_constant_switch_case(ctx, seen, rhs); } } @@ -8036,7 +8036,11 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type is_constant = is_constant && operand.mode == Addressing_Constant; - add_to_seen_map(c, &seen, op.kind, x, x, y); + TokenKind upper_op = Token_LtEq; + if (op.kind == Token_RangeHalf) { + upper_op = Token_Lt; + } + add_to_seen_map(c, &seen, upper_op, x, x, y); } else { Operand op_index = {}; check_expr_with_type_hint(c, &op_index, fv->field, index_type); diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 50b7c3233..0d18af199 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -961,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; } From cf246f65ff72db870313627b7db3b83601364385 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 5 Feb 2022 14:31:22 +0000 Subject: [PATCH 086/117] Add check for variables which are both shadowing and unused by default --- src/checker.cpp | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/checker.cpp b/src/checker.cpp index 188d68502..b62ef7c4c 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -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: From 3439139b1c763fe239967bd8c90d8ccbc1e0867f Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 5 Feb 2022 14:34:29 +0000 Subject: [PATCH 087/117] Minor clean up --- src/check_expr.cpp | 5 +++-- src/check_stmt.cpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index b2ce6c897..d90f93180 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -6961,7 +6961,9 @@ struct TypeAndToken { Token token; }; -void add_constant_switch_case(CheckerContext *ctx, PtrMap *seen, Operand operand, bool use_expr = true) { +typedef PtrMap SeenMap; + +void add_constant_switch_case(CheckerContext *ctx, SeenMap *seen, Operand operand, bool use_expr = true) { if (operand.mode != Addressing_Constant) { return; } @@ -7002,7 +7004,6 @@ void add_constant_switch_case(CheckerContext *ctx, PtrMap multi_map_insert(seen, key, tap); } -typedef PtrMap SeenMap; void add_to_seen_map(CheckerContext *ctx, SeenMap *seen, TokenKind upper_op, Operand const &x, Operand const &lhs, Operand const &rhs) { if (is_type_enum(x.type)) { diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 0d18af199..2d85db82c 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -921,7 +921,7 @@ void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) { } } - PtrMap seen = {}; // NOTE(bill): Multimap, Key: ExactValue + SeenMap seen = {}; // NOTE(bill): Multimap, Key: ExactValue map_init(&seen, heap_allocator()); defer (map_destroy(&seen)); From a4308e7246a995c745b120debbb61be9e1f19a38 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 5 Feb 2022 14:45:59 +0000 Subject: [PATCH 088/117] Improve union variant assignment determination --- src/check_expr.cpp | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index d90f93180..d6b454bf4 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -673,6 +673,42 @@ i64 check_distance_between_types(CheckerContext *c, Operand *operand, Type *type return 1; } } + + // TODO(bill): Determine which rule is a better on in practice + #if 1 + if (dst->Union.variants.count == 1) { + Type *vt = dst->Union.variants[0]; + i64 score = check_distance_between_types(c, operand, vt); + if (score >= 0) { + return score+2; + } + } + #else + // NOTE(bill): check to see you can assign to it with one of the variants? + i64 prev_lowest_score = -1; + i64 lowest_score = -1; + for_array(i, dst->Union.variants) { + Type *vt = dst->Union.variants[i]; + i64 score = check_distance_between_types(c, operand, vt); + if (score >= 0) { + if (lowest_score < 0) { + lowest_score = score; + } else { + if (prev_lowest_score < 0) { + prev_lowest_score = lowest_score; + } else { + prev_lowest_score = gb_min(prev_lowest_score, lowest_score); + } + lowest_score = gb_min(lowest_score, score); + } + } + } + if (lowest_score >= 0) { + if (prev_lowest_score != lowest_score) { // remove possible ambiguities + return lowest_score+2; + } + } + #endif } if (is_type_relative_pointer(dst)) { From 23c3573c307fc9b1c7aa2af2b445090543fd60d3 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 5 Feb 2022 14:56:06 +0000 Subject: [PATCH 089/117] Minor correction to error message suggestion --- src/check_expr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index d6b454bf4..4184d5b30 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -8196,7 +8196,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type } error_line("\n"); - error_line("\tSuggestion: Was '#partial %s {...}' wanted?\n", type_to_string(index_type)); + error_line("\tSuggestion: Was '#partial %s{...}' wanted?\n", type_to_string(type)); } } From 67ce0ec29f55621a36ddc1bde83f23a51c9ce355 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 5 Feb 2022 14:58:13 +0000 Subject: [PATCH 090/117] Improve printing for unhandled cases by adding a new line before the cases --- src/check_expr.cpp | 2 +- src/check_stmt.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 4184d5b30..4664d2244 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -8188,7 +8188,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type if (unhandled.count == 1) { error_no_newline(node, "Unhandled enumerated array case: %.*s", LIT(unhandled[0]->token.string)); } else { - error_no_newline(node, "Unhandled enumerated array cases: "); + error(node, "Unhandled enumerated array cases:"); for_array(i, unhandled) { Entity *f = unhandled[i]; error_line("\t%.*s\n", LIT(f->token.string)); diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 2d85db82c..7cae1893f 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -1065,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)); From c6ab8f82c88f7d5470fa2fb0459d09ba8a67a287 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 5 Feb 2022 15:17:47 +0000 Subject: [PATCH 091/117] Code refactor to aid development --- src/check_expr.cpp | 3552 ++++++++++++++++++++++---------------------- 1 file changed, 1811 insertions(+), 1741 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 4664d2244..fb58839bc 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -7086,6 +7086,1805 @@ void add_to_seen_map(CheckerContext *ctx, SeenMap *seen, Operand const &x) { add_constant_switch_case(ctx, seen, x); } +ExprKind check_basic_directive_expr(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) { + ast_node(bd, BasicDirective, node); + + ExprKind kind = Expr_Expr; + + o->mode = Addressing_Constant; + String name = bd->name.string; + if (name == "file") { + o->type = t_untyped_string; + o->value = exact_value_string(get_file_path_string(bd->token.pos.file_id)); + } else if (name == "line") { + o->type = t_untyped_integer; + o->value = exact_value_i64(bd->token.pos.line); + } else if (name == "procedure") { + if (c->curr_proc_decl == nullptr) { + error(node, "#procedure may only be used within procedures"); + o->type = t_untyped_string; + o->value = exact_value_string(str_lit("")); + } else { + o->type = t_untyped_string; + o->value = exact_value_string(c->proc_name); + } + } else if (name == "caller_location") { + init_core_source_code_location(c->checker); + error(node, "#caller_location may only be used as a default argument parameter"); + o->type = t_source_code_location; + o->mode = Addressing_Value; + } else { + if (name == "location") { + init_core_source_code_location(c->checker); + error(node, "'#%.*s' must be used in a call expression", LIT(name)); + o->type = t_source_code_location; + o->mode = Addressing_Value; + } else if ( + name == "assert" || + name == "defined" || + name == "config" || + name == "load" || + name == "load_hash" || + name == "load_or" + ) { + error(node, "'#%.*s' must be used as a call", LIT(name)); + o->type = t_invalid; + o->mode = Addressing_Invalid; + } else { + error(node, "Unknown directive: #%.*s", LIT(name)); + o->type = t_invalid; + o->mode = Addressing_Invalid; + } + + } + return kind; +} + +ExprKind check_ternary_if_expr(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) { + ExprKind kind = Expr_Expr; + Operand cond = {Addressing_Invalid}; + ast_node(te, TernaryIfExpr, node); + check_expr(c, &cond, te->cond); + node->viral_state_flags |= te->cond->viral_state_flags; + + if (cond.mode != Addressing_Invalid && !is_type_boolean(cond.type)) { + error(te->cond, "Non-boolean condition in ternary if expression"); + } + + Operand x = {Addressing_Invalid}; + Operand y = {Addressing_Invalid}; + check_expr_or_type(c, &x, te->x, type_hint); + node->viral_state_flags |= te->x->viral_state_flags; + + if (te->y != nullptr) { + check_expr_or_type(c, &y, te->y, type_hint); + node->viral_state_flags |= te->y->viral_state_flags; + } else { + error(node, "A ternary expression must have an else clause"); + return kind; + } + + if (x.type == nullptr || x.type == t_invalid || + y.type == nullptr || y.type == t_invalid) { + return kind; + } + + convert_to_typed(c, &x, y.type); + if (x.mode == Addressing_Invalid) { + return kind; + } + convert_to_typed(c, &y, x.type); + if (y.mode == Addressing_Invalid) { + x.mode = Addressing_Invalid; + return kind; + } + + if (!ternary_compare_types(x.type, y.type)) { + gbString its = type_to_string(x.type); + gbString ets = type_to_string(y.type); + error(node, "Mismatched types in ternary if expression, %s vs %s", its, ets); + gb_string_free(ets); + gb_string_free(its); + return kind; + } + + o->type = x.type; + if (is_type_untyped_nil(o->type) || is_type_untyped_undef(o->type)) { + o->type = y.type; + } + + o->mode = Addressing_Value; + o->expr = node; + if (type_hint != nullptr && is_type_untyped(o->type)) { + if (check_cast_internal(c, &x, type_hint) && + check_cast_internal(c, &y, type_hint)) { + convert_to_typed(c, o, type_hint); + update_untyped_expr_type(c, node, type_hint, !is_type_untyped(type_hint)); + } + } + return kind; +} + +ExprKind check_ternary_when_expr(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) { + ExprKind kind = Expr_Expr; + Operand cond = {}; + ast_node(te, TernaryWhenExpr, node); + check_expr(c, &cond, te->cond); + node->viral_state_flags |= te->cond->viral_state_flags; + + if (cond.mode != Addressing_Constant || !is_type_boolean(cond.type)) { + error(te->cond, "Expected a constant boolean condition in ternary when expression"); + return kind; + } + + if (cond.value.value_bool) { + check_expr_or_type(c, o, te->x, type_hint); + node->viral_state_flags |= te->x->viral_state_flags; + } else { + if (te->y != nullptr) { + check_expr_or_type(c, o, te->y, type_hint); + node->viral_state_flags |= te->y->viral_state_flags; + } else { + error(node, "A ternary when expression must have an else clause"); + return kind; + } + } + return kind; +} + +ExprKind check_or_else_expr(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) { + ast_node(oe, OrElseExpr, node); + + String name = oe->token.string; + Ast *arg = oe->x; + Ast *default_value = oe->y; + + Operand x = {}; + Operand y = {}; + check_multi_expr_with_type_hint(c, &x, arg, type_hint); + if (x.mode == Addressing_Invalid) { + o->mode = Addressing_Value; + o->type = t_invalid; + o->expr = node; + return Expr_Expr; + } + + check_multi_expr_with_type_hint(c, &y, default_value, x.type); + error_operand_no_value(&y); + if (y.mode == Addressing_Invalid) { + o->mode = Addressing_Value; + o->type = t_invalid; + o->expr = node; + return Expr_Expr; + } + + Type *left_type = nullptr; + Type *right_type = nullptr; + check_or_else_split_types(c, &x, name, &left_type, &right_type); + add_type_and_value(&c->checker->info, arg, x.mode, x.type, x.value); + + if (left_type != nullptr) { + check_assignment(c, &y, left_type, name); + } else { + check_or_else_expr_no_value_error(c, name, x, type_hint); + } + + if (left_type == nullptr) { + left_type = t_invalid; + } + o->mode = Addressing_Value; + o->type = left_type; + o->expr = node; + return Expr_Expr; +} + +ExprKind check_or_return_expr(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) { + ast_node(re, OrReturnExpr, node); + + String name = re->token.string; + Operand x = {}; + check_multi_expr_with_type_hint(c, &x, re->expr, type_hint); + if (x.mode == Addressing_Invalid) { + o->mode = Addressing_Value; + o->type = t_invalid; + o->expr = node; + return Expr_Expr; + } + + Type *left_type = nullptr; + Type *right_type = nullptr; + check_or_return_split_types(c, &x, name, &left_type, &right_type); + add_type_and_value(&c->checker->info, re->expr, x.mode, x.type, x.value); + + if (right_type == nullptr) { + check_or_else_expr_no_value_error(c, name, x, type_hint); + } else { + Type *proc_type = base_type(c->curr_proc_sig); + GB_ASSERT(proc_type->kind == Type_Proc); + Type *result_type = proc_type->Proc.results; + if (result_type == nullptr) { + error(node, "'%.*s' requires the current procedure to have at least one return value", LIT(name)); + } else { + GB_ASSERT(result_type->kind == Type_Tuple); + + auto const &vars = result_type->Tuple.variables; + Type *end_type = vars[vars.count-1]->type; + + if (vars.count > 1) { + if (!proc_type->Proc.has_named_results) { + error(node, "'%.*s' within a procedure with more than 1 return value requires that the return values are named, allowing for early return", LIT(name)); + } + } + + Operand rhs = {}; + rhs.type = right_type; + rhs.mode = Addressing_Value; + + // TODO(bill): better error message + if (!check_is_assignable_to(c, &rhs, end_type)) { + gbString a = type_to_string(right_type); + gbString b = type_to_string(end_type); + gbString ret_type = type_to_string(result_type); + error(node, "Cannot assign end value of type '%s' to '%s' in '%.*s'", a, b, LIT(name)); + if (vars.count == 1) { + error_line("\tProcedure return value type: %s\n", ret_type); + } else { + error_line("\tProcedure return value types: (%s)\n", ret_type); + } + gb_string_free(ret_type); + gb_string_free(b); + gb_string_free(a); + } + } + } + + o->expr = node; + o->type = left_type; + if (left_type != nullptr) { + o->mode = Addressing_Value; + } else { + o->mode = Addressing_NoValue; + } + + if (c->curr_proc_sig == nullptr) { + error(node, "'%.*s' can only be used within a procedure", LIT(name)); + } + + if (c->in_defer) { + error(node, "'or_return' cannot be used within a defer statement"); + } + + return Expr_Expr; +} + +ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) { + ExprKind kind = Expr_Expr; + ast_node(cl, CompoundLit, node); + + Type *type = type_hint; + if (type != nullptr && is_type_untyped(type)) { + type = nullptr; + } + bool is_to_be_determined_array_count = false; + bool is_constant = true; + if (cl->type != nullptr) { + type = nullptr; + + // [?]Type + if (cl->type->kind == Ast_ArrayType && cl->type->ArrayType.count != nullptr) { + Ast *count = cl->type->ArrayType.count; + if (count->kind == Ast_UnaryExpr && + count->UnaryExpr.op.kind == Token_Question) { + type = alloc_type_array(check_type(c, cl->type->ArrayType.elem), -1); + is_to_be_determined_array_count = true; + } + if (cl->elems.count > 0) { + if (cl->type->ArrayType.tag != nullptr) { + Ast *tag = cl->type->ArrayType.tag; + GB_ASSERT(tag->kind == Ast_BasicDirective); + String name = tag->BasicDirective.name.string; + if (name == "soa") { + error(node, "#soa arrays are not supported for compound literals"); + return kind; + } + } + } + } + if (cl->type->kind == Ast_DynamicArrayType && cl->type->DynamicArrayType.tag != nullptr) { + if (cl->elems.count > 0) { + Ast *tag = cl->type->DynamicArrayType.tag; + GB_ASSERT(tag->kind == Ast_BasicDirective); + String name = tag->BasicDirective.name.string; + if (name == "soa") { + error(node, "#soa arrays are not supported for compound literals"); + return kind; + } + } + } + + if (type == nullptr) { + type = check_type(c, cl->type); + } + } + + if (type == nullptr) { + error(node, "Missing type in compound literal"); + return kind; + } + + + Type *t = base_type(type); + if (is_type_polymorphic(t)) { + gbString str = type_to_string(type); + error(node, "Cannot use a polymorphic type for a compound literal, got '%s'", str); + o->expr = node; + o->type = type; + gb_string_free(str); + return kind; + } + + + switch (t->kind) { + case Type_Struct: { + if (cl->elems.count == 0) { + break; // NOTE(bill): No need to init + } + if (t->Struct.is_raw_union) { + if (cl->elems.count > 0) { + // NOTE: unions cannot be constant + is_constant = false; + + if (cl->elems[0]->kind != Ast_FieldValue) { + gbString type_str = type_to_string(type); + error(node, "%s ('struct #raw_union') compound literals are only allowed to contain 'field = value' elements", type_str); + gb_string_free(type_str); + } else { + if (cl->elems.count != 1) { + gbString type_str = type_to_string(type); + error(node, "%s ('struct #raw_union') compound literals are only allowed to contain up to 1 'field = value' element, got %td", type_str, cl->elems.count); + gb_string_free(type_str); + } else { + Ast *elem = cl->elems[0]; + ast_node(fv, FieldValue, elem); + if (fv->field->kind != Ast_Ident) { + gbString expr_str = expr_to_string(fv->field); + error(elem, "Invalid field name '%s' in structure literal", expr_str); + gb_string_free(expr_str); + break; + } + + String name = fv->field->Ident.token.string; + + Selection sel = lookup_field(type, name, o->mode == Addressing_Type); + bool is_unknown = sel.entity == nullptr; + if (is_unknown) { + error(elem, "Unknown field '%.*s' in structure literal", LIT(name)); + break; + } + + if (sel.index.count > 1) { + error(elem, "Cannot assign to an anonymous field '%.*s' in a structure literal (at the moment)", LIT(name)); + break; + } + + Entity *field = t->Struct.fields[sel.index[0]]; + add_entity_use(c, fv->field, field); + + Operand o = {}; + check_expr_or_type(c, &o, fv->value, field->type); + + + check_assignment(c, &o, field->type, str_lit("structure literal")); + } + + } + } + break; + } + + + isize field_count = t->Struct.fields.count; + isize min_field_count = t->Struct.fields.count; + for (isize i = min_field_count-1; i >= 0; i--) { + Entity *e = t->Struct.fields[i]; + GB_ASSERT(e->kind == Entity_Variable); + if (e->Variable.param_value.kind != ParameterValue_Invalid) { + min_field_count--; + } else { + break; + } + } + + if (cl->elems[0]->kind == Ast_FieldValue) { + bool *fields_visited = gb_alloc_array(temporary_allocator(), bool, field_count); + + for_array(i, cl->elems) { + Ast *elem = cl->elems[i]; + if (elem->kind != Ast_FieldValue) { + error(elem, "Mixture of 'field = value' and value elements in a literal is not allowed"); + continue; + } + ast_node(fv, FieldValue, elem); + if (fv->field->kind != Ast_Ident) { + gbString expr_str = expr_to_string(fv->field); + error(elem, "Invalid field name '%s' in structure literal", expr_str); + gb_string_free(expr_str); + continue; + } + String name = fv->field->Ident.token.string; + + Selection sel = lookup_field(type, name, o->mode == Addressing_Type); + bool is_unknown = sel.entity == nullptr; + if (is_unknown) { + error(elem, "Unknown field '%.*s' in structure literal", LIT(name)); + continue; + } + + if (sel.index.count > 1) { + error(elem, "Cannot assign to an anonymous field '%.*s' in a structure literal (at the moment)", LIT(name)); + continue; + } + + Entity *field = t->Struct.fields[sel.index[0]]; + add_entity_use(c, fv->field, field); + + if (fields_visited[sel.index[0]]) { + error(elem, "Duplicate field '%.*s' in structure literal", LIT(name)); + continue; + } + + fields_visited[sel.index[0]] = true; + + Operand o = {}; + check_expr_or_type(c, &o, fv->value, field->type); + + if (is_type_any(field->type) || is_type_union(field->type) || is_type_raw_union(field->type) || is_type_typeid(field->type)) { + is_constant = false; + } + if (is_constant) { + is_constant = check_is_operand_compound_lit_constant(c, &o); + } + + check_assignment(c, &o, field->type, str_lit("structure literal")); + } + } else { + bool seen_field_value = false; + + for_array(index, cl->elems) { + Entity *field = nullptr; + Ast *elem = cl->elems[index]; + if (elem->kind == Ast_FieldValue) { + seen_field_value = true; + error(elem, "Mixture of 'field = value' and value elements in a literal is not allowed"); + continue; + } else if (seen_field_value) { + error(elem, "Value elements cannot be used after a 'field = value'"); + continue; + } + if (index >= field_count) { + error(elem, "Too many values in structure literal, expected %td, got %td", field_count, cl->elems.count); + break; + } + + if (field == nullptr) { + field = t->Struct.fields[index]; + } + + Operand o = {}; + check_expr_or_type(c, &o, elem, field->type); + + if (is_type_any(field->type) || is_type_union(field->type) || is_type_raw_union(field->type) || is_type_typeid(field->type)) { + is_constant = false; + } + if (is_constant) { + is_constant = check_is_operand_compound_lit_constant(c, &o); + } + + check_assignment(c, &o, field->type, str_lit("structure literal")); + } + if (cl->elems.count < field_count) { + if (min_field_count < field_count) { + if (cl->elems.count < min_field_count) { + error(cl->close, "Too few values in structure literal, expected at least %td, got %td", min_field_count, cl->elems.count); + } + } else { + error(cl->close, "Too few values in structure literal, expected %td, got %td", field_count, cl->elems.count); + } + } + } + + break; + } + + case Type_Slice: + case Type_Array: + case Type_DynamicArray: + case Type_SimdVector: + case Type_Matrix: + { + Type *elem_type = nullptr; + String context_name = {}; + i64 max_type_count = -1; + if (t->kind == Type_Slice) { + elem_type = t->Slice.elem; + context_name = str_lit("slice literal"); + } else if (t->kind == Type_Array) { + elem_type = t->Array.elem; + context_name = str_lit("array literal"); + if (!is_to_be_determined_array_count) { + max_type_count = t->Array.count; + } + } else if (t->kind == Type_DynamicArray) { + elem_type = t->DynamicArray.elem; + context_name = str_lit("dynamic array literal"); + is_constant = false; + + if (!build_context.no_dynamic_literals) { + add_package_dependency(c, "runtime", "__dynamic_array_reserve"); + add_package_dependency(c, "runtime", "__dynamic_array_append"); + } + } else if (t->kind == Type_SimdVector) { + elem_type = t->SimdVector.elem; + context_name = str_lit("simd vector literal"); + max_type_count = t->SimdVector.count; + } else if (t->kind == Type_Matrix) { + elem_type = t->Matrix.elem; + context_name = str_lit("matrix literal"); + max_type_count = t->Matrix.row_count*t->Matrix.column_count; + } else { + GB_PANIC("unreachable"); + } + + + i64 max = 0; + + Type *bet = base_type(elem_type); + if (!elem_type_can_be_constant(bet)) { + is_constant = false; + } + + if (bet == t_invalid) { + break; + } + + if (cl->elems.count > 0 && cl->elems[0]->kind == Ast_FieldValue) { + if (is_type_simd_vector(t)) { + error(cl->elems[0], "'field = value' is not allowed for SIMD vector literals"); + } else { + RangeCache rc = range_cache_make(heap_allocator()); + defer (range_cache_destroy(&rc)); + + for_array(i, cl->elems) { + Ast *elem = cl->elems[i]; + if (elem->kind != Ast_FieldValue) { + error(elem, "Mixture of 'field = value' and value elements in a literal is not allowed"); + continue; + } + ast_node(fv, FieldValue, elem); + + if (is_ast_range(fv->field)) { + Token op = fv->field->BinaryExpr.op; + + Operand x = {}; + Operand y = {}; + bool ok = check_range(c, fv->field, &x, &y, nullptr); + if (!ok) { + continue; + } + if (x.mode != Addressing_Constant || !is_type_integer(core_type(x.type))) { + error(x.expr, "Expected a constant integer as an array field"); + continue; + } + + if (y.mode != Addressing_Constant || !is_type_integer(core_type(y.type))) { + error(y.expr, "Expected a constant integer as an array field"); + continue; + } + + i64 lo = exact_value_to_i64(x.value); + i64 hi = exact_value_to_i64(y.value); + i64 max_index = hi; + if (op.kind == Token_RangeHalf) { // ..< (exclusive) + hi -= 1; + } else { // .. (inclusive) + max_index += 1; + } + + bool new_range = range_cache_add_range(&rc, lo, hi); + if (!new_range) { + error(elem, "Overlapping field range index %lld %.*s %lld for %.*s", lo, LIT(op.string), hi, LIT(context_name)); + continue; + } + + + if (max_type_count >= 0 && (lo < 0 || lo >= max_type_count)) { + error(elem, "Index %lld is out of bounds (0..<%lld) for %.*s", lo, max_type_count, LIT(context_name)); + continue; + } + if (max_type_count >= 0 && (hi < 0 || hi >= max_type_count)) { + error(elem, "Index %lld is out of bounds (0..<%lld) for %.*s", hi, max_type_count, LIT(context_name)); + continue; + } + + if (max < hi) { + max = max_index; + } + + Operand operand = {}; + check_expr_with_type_hint(c, &operand, fv->value, elem_type); + check_assignment(c, &operand, elem_type, context_name); + + is_constant = is_constant && operand.mode == Addressing_Constant; + } else { + Operand op_index = {}; + check_expr(c, &op_index, fv->field); + + if (op_index.mode != Addressing_Constant || !is_type_integer(core_type(op_index.type))) { + error(elem, "Expected a constant integer as an array field"); + continue; + } + // add_type_and_value(c->info, op_index.expr, op_index.mode, op_index.type, op_index.value); + + i64 index = exact_value_to_i64(op_index.value); + + if (max_type_count >= 0 && (index < 0 || index >= max_type_count)) { + error(elem, "Index %lld is out of bounds (0..<%lld) for %.*s", index, max_type_count, LIT(context_name)); + continue; + } + + bool new_index = range_cache_add_index(&rc, index); + if (!new_index) { + error(elem, "Duplicate field index %lld for %.*s", index, LIT(context_name)); + continue; + } + + if (max < index+1) { + max = index+1; + } + + Operand operand = {}; + check_expr_with_type_hint(c, &operand, fv->value, elem_type); + check_assignment(c, &operand, elem_type, context_name); + + is_constant = is_constant && operand.mode == Addressing_Constant; + } + } + + cl->max_count = max; + } + + } else { + isize index = 0; + for (; index < cl->elems.count; index++) { + Ast *e = cl->elems[index]; + if (e == nullptr) { + error(node, "Invalid literal element"); + continue; + } + + if (e->kind == Ast_FieldValue) { + error(e, "Mixture of 'field = value' and value elements in a literal is not allowed"); + continue; + } + + if (0 <= max_type_count && max_type_count <= index) { + error(e, "Index %lld is out of bounds (>= %lld) for %.*s", index, max_type_count, LIT(context_name)); + } + + Operand operand = {}; + check_expr_with_type_hint(c, &operand, e, elem_type); + check_assignment(c, &operand, elem_type, context_name); + + is_constant = is_constant && operand.mode == Addressing_Constant; + } + + if (max < index) { + max = index; + } + } + + + if (t->kind == Type_Array) { + if (is_to_be_determined_array_count) { + t->Array.count = max; + } else if (cl->elems.count > 0 && cl->elems[0]->kind != Ast_FieldValue) { + if (0 < max && max < t->Array.count) { + error(node, "Expected %lld values for this array literal, got %lld", cast(long long)t->Array.count, cast(long long)max); + } + } + } + + + if (t->kind == Type_SimdVector) { + if (!is_constant) { + error(node, "Expected all constant elements for a simd vector"); + } + } + + + if (t->kind == Type_DynamicArray) { + if (build_context.no_dynamic_literals && cl->elems.count) { + error(node, "Compound literals of dynamic types have been disabled"); + } + } + + if (t->kind == Type_Matrix) { + if (cl->elems.count > 0 && cl->elems[0]->kind != Ast_FieldValue) { + if (0 < max && max < max_type_count) { + error(node, "Expected %lld values for this matrix literal, got %lld", cast(long long)max_type_count, cast(long long)max); + } + } + } + + break; + } + + case Type_EnumeratedArray: + { + Type *elem_type = t->EnumeratedArray.elem; + Type *index_type = t->EnumeratedArray.index; + String context_name = str_lit("enumerated array literal"); + i64 max_type_count = t->EnumeratedArray.count; + + gbString index_type_str = type_to_string(index_type); + defer (gb_string_free(index_type_str)); + + i64 total_lo = exact_value_to_i64(*t->EnumeratedArray.min_value); + i64 total_hi = exact_value_to_i64(*t->EnumeratedArray.max_value); + + String total_lo_string = {}; + String total_hi_string = {}; + GB_ASSERT(is_type_enum(index_type)); + { + Type *bt = base_type(index_type); + GB_ASSERT(bt->kind == Type_Enum); + for_array(i, bt->Enum.fields) { + Entity *f = bt->Enum.fields[i]; + if (f->kind != Entity_Constant) { + continue; + } + if (total_lo_string.len == 0 && compare_exact_values(Token_CmpEq, f->Constant.value, *t->EnumeratedArray.min_value)) { + total_lo_string = f->token.string; + } + if (total_hi_string.len == 0 && compare_exact_values(Token_CmpEq, f->Constant.value, *t->EnumeratedArray.max_value)) { + total_hi_string = f->token.string; + } + if (total_lo_string.len != 0 && total_hi_string.len != 0) { + break; + } + } + } + + i64 max = 0; + + Type *bet = base_type(elem_type); + if (!elem_type_can_be_constant(bet)) { + is_constant = false; + } + + if (bet == t_invalid) { + break; + } + bool is_partial = cl->tag && (cl->tag->BasicDirective.name.string == "partial"); + + SeenMap seen = {}; // NOTE(bill): Multimap, Key: ExactValue + map_init(&seen, heap_allocator()); + defer (map_destroy(&seen)); + + if (cl->elems.count > 0 && cl->elems[0]->kind == Ast_FieldValue) { + RangeCache rc = range_cache_make(heap_allocator()); + defer (range_cache_destroy(&rc)); + + for_array(i, cl->elems) { + Ast *elem = cl->elems[i]; + if (elem->kind != Ast_FieldValue) { + error(elem, "Mixture of 'field = value' and value elements in a literal is not allowed"); + continue; + } + ast_node(fv, FieldValue, elem); + + if (is_ast_range(fv->field)) { + Token op = fv->field->BinaryExpr.op; + + Operand x = {}; + Operand y = {}; + bool ok = check_range(c, fv->field, &x, &y, nullptr, index_type); + if (!ok) { + continue; + } + if (x.mode != Addressing_Constant || !are_types_identical(x.type, index_type)) { + error(x.expr, "Expected a constant enum of type '%s' as an array field", index_type_str); + continue; + } + + if (y.mode != Addressing_Constant || !are_types_identical(x.type, index_type)) { + error(y.expr, "Expected a constant enum of type '%s' as an array field", index_type_str); + continue; + } + + i64 lo = exact_value_to_i64(x.value); + i64 hi = exact_value_to_i64(y.value); + i64 max_index = hi; + if (op.kind == Token_RangeHalf) { + hi -= 1; + } + + bool new_range = range_cache_add_range(&rc, lo, hi); + if (!new_range) { + gbString lo_str = expr_to_string(x.expr); + gbString hi_str = expr_to_string(y.expr); + error(elem, "Overlapping field range index %s %.*s %s for %.*s", lo_str, LIT(op.string), hi_str, LIT(context_name)); + gb_string_free(hi_str); + gb_string_free(lo_str); + continue; + } + + + // NOTE(bill): These are sanity checks for invalid enum values + if (max_type_count >= 0 && (lo < total_lo || lo > total_hi)) { + gbString lo_str = expr_to_string(x.expr); + error(elem, "Index %s is out of bounds (%.*s .. %.*s) for %.*s", lo_str, LIT(total_lo_string), LIT(total_hi_string), LIT(context_name)); + gb_string_free(lo_str); + continue; + } + if (max_type_count >= 0 && (hi < 0 || hi > total_hi)) { + gbString hi_str = expr_to_string(y.expr); + error(elem, "Index %s is out of bounds (%.*s .. %.*s) for %.*s", hi_str, LIT(total_lo_string), LIT(total_hi_string), LIT(context_name)); + gb_string_free(hi_str); + continue; + } + + if (max < hi) { + max = max_index; + } + + Operand operand = {}; + check_expr_with_type_hint(c, &operand, fv->value, elem_type); + check_assignment(c, &operand, elem_type, context_name); + + is_constant = is_constant && operand.mode == Addressing_Constant; + + TokenKind upper_op = Token_LtEq; + if (op.kind == Token_RangeHalf) { + upper_op = Token_Lt; + } + add_to_seen_map(c, &seen, upper_op, x, x, y); + } else { + Operand op_index = {}; + check_expr_with_type_hint(c, &op_index, fv->field, index_type); + + if (op_index.mode != Addressing_Constant || !are_types_identical(op_index.type, index_type)) { + error(op_index.expr, "Expected a constant enum of type '%s' as an array field", index_type_str); + continue; + } + + i64 index = exact_value_to_i64(op_index.value); + + if (max_type_count >= 0 && (index < total_lo || index > total_hi)) { + gbString idx_str = expr_to_string(op_index.expr); + error(elem, "Index %s is out of bounds (%.*s .. %.*s) for %.*s", idx_str, LIT(total_lo_string), LIT(total_hi_string), LIT(context_name)); + gb_string_free(idx_str); + continue; + } + + bool new_index = range_cache_add_index(&rc, index); + if (!new_index) { + gbString idx_str = expr_to_string(op_index.expr); + error(elem, "Duplicate field index %s for %.*s", idx_str, LIT(context_name)); + gb_string_free(idx_str); + continue; + } + + if (max < index+1) { + max = index+1; + } + + Operand operand = {}; + check_expr_with_type_hint(c, &operand, fv->value, elem_type); + check_assignment(c, &operand, elem_type, context_name); + + is_constant = is_constant && operand.mode == Addressing_Constant; + + add_to_seen_map(c, &seen, op_index); + } + } + + cl->max_count = max; + + } else { + isize index = 0; + for (; index < cl->elems.count; index++) { + Ast *e = cl->elems[index]; + if (e == nullptr) { + error(node, "Invalid literal element"); + continue; + } + + if (e->kind == Ast_FieldValue) { + error(e, "Mixture of 'field = value' and value elements in a literal is not allowed"); + continue; + } + + if (0 <= max_type_count && max_type_count <= index) { + error(e, "Index %lld is out of bounds (>= %lld) for %.*s", index, max_type_count, LIT(context_name)); + } + + Operand operand = {}; + check_expr_with_type_hint(c, &operand, e, elem_type); + check_assignment(c, &operand, elem_type, context_name); + + is_constant = is_constant && operand.mode == Addressing_Constant; + } + + if (max < index) { + max = index; + } + } + + bool was_error = false; + if (cl->elems.count > 0 && cl->elems[0]->kind != Ast_FieldValue) { + if (0 < max && max < t->EnumeratedArray.count) { + error(node, "Expected %lld values for this enumerated array literal, got %lld", cast(long long)t->EnumeratedArray.count, cast(long long)max); + was_error = true; + } else { + error(node, "Enumerated array literals must only have 'field = value' elements, bare elements are not allowed"); + was_error = true; + } + } + + // NOTE(bill): Check for missing cases when `#partial literal` is not present + if (cl->elems.count > 0 && !was_error && !is_partial) { + Type *et = base_type(index_type); + GB_ASSERT(et->kind == Type_Enum); + auto fields = et->Enum.fields; + + auto unhandled = array_make(temporary_allocator(), 0, fields.count); + + for_array(i, fields) { + Entity *f = fields[i]; + if (f->kind != Entity_Constant) { + continue; + } + ExactValue v = f->Constant.value; + auto found = map_get(&seen, hash_exact_value(v)); + if (!found) { + array_add(&unhandled, f); + } + } + + if (unhandled.count > 0) { + begin_error_block(); + defer (end_error_block()); + + if (unhandled.count == 1) { + error_no_newline(node, "Unhandled enumerated array case: %.*s", LIT(unhandled[0]->token.string)); + } else { + error(node, "Unhandled enumerated array cases:"); + for_array(i, unhandled) { + Entity *f = unhandled[i]; + error_line("\t%.*s\n", LIT(f->token.string)); + } + } + error_line("\n"); + + error_line("\tSuggestion: Was '#partial %s{...}' wanted?\n", type_to_string(type)); + } + } + + break; + } + + case Type_Basic: { + if (!is_type_any(t)) { + if (cl->elems.count != 0) { + error(node, "Illegal compound literal"); + } + break; + } + if (cl->elems.count == 0) { + break; // NOTE(bill): No need to init + } + { // Checker values + Type *field_types[2] = {t_rawptr, t_typeid}; + isize field_count = 2; + if (cl->elems[0]->kind == Ast_FieldValue) { + bool fields_visited[2] = {}; + + for_array(i, cl->elems) { + Ast *elem = cl->elems[i]; + if (elem->kind != Ast_FieldValue) { + error(elem, "Mixture of 'field = value' and value elements in a 'any' literal is not allowed"); + continue; + } + ast_node(fv, FieldValue, elem); + if (fv->field->kind != Ast_Ident) { + gbString expr_str = expr_to_string(fv->field); + error(elem, "Invalid field name '%s' in 'any' literal", expr_str); + gb_string_free(expr_str); + continue; + } + String name = fv->field->Ident.token.string; + + Selection sel = lookup_field(type, name, o->mode == Addressing_Type); + if (sel.entity == nullptr) { + error(elem, "Unknown field '%.*s' in 'any' literal", LIT(name)); + continue; + } + + isize index = sel.index[0]; + + if (fields_visited[index]) { + error(elem, "Duplicate field '%.*s' in 'any' literal", LIT(name)); + continue; + } + + fields_visited[index] = true; + check_expr(c, o, fv->value); + + // NOTE(bill): 'any' literals can never be constant + is_constant = false; + + check_assignment(c, o, field_types[index], str_lit("'any' literal")); + } + } else { + for_array(index, cl->elems) { + Ast *elem = cl->elems[index]; + if (elem->kind == Ast_FieldValue) { + error(elem, "Mixture of 'field = value' and value elements in a 'any' literal is not allowed"); + continue; + } + + + check_expr(c, o, elem); + if (index >= field_count) { + error(o->expr, "Too many values in 'any' literal, expected %td", field_count); + break; + } + + // NOTE(bill): 'any' literals can never be constant + is_constant = false; + + check_assignment(c, o, field_types[index], str_lit("'any' literal")); + } + if (cl->elems.count < field_count) { + error(cl->close, "Too few values in 'any' literal, expected %td, got %td", field_count, cl->elems.count); + } + } + } + + break; + } + + case Type_Map: { + if (cl->elems.count == 0) { + break; + } + is_constant = false; + { // Checker values + bool key_is_typeid = is_type_typeid(t->Map.key); + bool value_is_typeid = is_type_typeid(t->Map.value); + + for_array(i, cl->elems) { + Ast *elem = cl->elems[i]; + if (elem->kind != Ast_FieldValue) { + error(elem, "Only 'field = value' elements are allowed in a map literal"); + continue; + } + ast_node(fv, FieldValue, elem); + + if (key_is_typeid) { + check_expr_or_type(c, o, fv->field, t->Map.key); + } else { + check_expr_with_type_hint(c, o, fv->field, t->Map.key); + } + check_assignment(c, o, t->Map.key, str_lit("map literal")); + if (o->mode == Addressing_Invalid) { + continue; + } + + if (value_is_typeid) { + check_expr_or_type(c, o, fv->value, t->Map.value); + } else { + check_expr_with_type_hint(c, o, fv->value, t->Map.value); + } + check_assignment(c, o, t->Map.value, str_lit("map literal")); + } + } + + if (build_context.no_dynamic_literals && cl->elems.count) { + error(node, "Compound literals of dynamic types have been disabled"); + } else { + add_package_dependency(c, "runtime", "__dynamic_map_reserve"); + add_package_dependency(c, "runtime", "__dynamic_map_set"); + } + break; + } + + case Type_BitSet: { + if (cl->elems.count == 0) { + break; // NOTE(bill): No need to init + } + Type *et = base_type(t->BitSet.elem); + isize field_count = 0; + if (et->kind == Type_Enum) { + field_count = et->Enum.fields.count; + } + + if (cl->elems[0]->kind == Ast_FieldValue) { + error(cl->elems[0], "'field = value' in a bit_set a literal is not allowed"); + is_constant = false; + } else { + for_array(index, cl->elems) { + Ast *elem = cl->elems[index]; + if (elem->kind == Ast_FieldValue) { + error(elem, "'field = value' in a bit_set a literal is not allowed"); + continue; + } + + check_expr_with_type_hint(c, o, elem, et); + + if (is_constant) { + is_constant = o->mode == Addressing_Constant; + } + + check_assignment(c, o, t->BitSet.elem, str_lit("bit_set literal")); + if (o->mode == Addressing_Constant) { + i64 lower = t->BitSet.lower; + i64 upper = t->BitSet.upper; + i64 v = exact_value_to_i64(o->value); + if (lower <= v && v <= upper) { + // okay + } else { + error(elem, "Bit field value out of bounds, %lld not in the range %lld .. %lld", v, lower, upper); + continue; + } + } + } + } + break; + } + + default: { + if (cl->elems.count == 0) { + break; // NOTE(bill): No need to init + } + + gbString str = type_to_string(type); + error(node, "Invalid compound literal type '%s'", str); + gb_string_free(str); + return kind; + } + } + + if (is_constant) { + o->mode = Addressing_Constant; + + if (is_type_bit_set(type)) { + // NOTE(bill): Encode as an integer + + i64 lower = base_type(type)->BitSet.lower; + + u64 bits = 0; + for_array(index, cl->elems) { + Ast *elem = cl->elems[index]; + GB_ASSERT(elem->kind != Ast_FieldValue); + TypeAndValue tav = elem->tav; + ExactValue i = exact_value_to_integer(tav.value); + if (i.kind != ExactValue_Integer) { + continue; + } + i64 val = big_int_to_i64(&i.value_integer); + val -= lower; + u64 bit = u64(1ll<value = exact_value_u64(bits); + } else if (is_type_constant_type(type) && cl->elems.count == 0) { + ExactValue value = exact_value_compound(node); + Type *bt = core_type(type); + if (bt->kind == Type_Basic) { + if (bt->Basic.flags & BasicFlag_Boolean) { + value = exact_value_bool(false); + } else if (bt->Basic.flags & BasicFlag_Integer) { + value = exact_value_i64(0); + } else if (bt->Basic.flags & BasicFlag_Unsigned) { + value = exact_value_i64(0); + } else if (bt->Basic.flags & BasicFlag_Float) { + value = exact_value_float(0); + } else if (bt->Basic.flags & BasicFlag_Complex) { + value = exact_value_complex(0, 0); + } else if (bt->Basic.flags & BasicFlag_Quaternion) { + value = exact_value_quaternion(0, 0, 0, 0); + } else if (bt->Basic.flags & BasicFlag_Pointer) { + value = exact_value_pointer(0); + } else if (bt->Basic.flags & BasicFlag_String) { + String empty_string = {}; + value = exact_value_string(empty_string); + } else if (bt->Basic.flags & BasicFlag_Rune) { + value = exact_value_i64(0); + } + } + + o->value = value; + } else { + o->value = exact_value_compound(node); + } + } else { + o->mode = Addressing_Value; + } + o->type = type; + return kind; +} + +ExprKind check_type_assertion(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) { + ExprKind kind = Expr_Expr; + ast_node(ta, TypeAssertion, node); + check_expr(c, o, ta->expr); + node->viral_state_flags |= ta->expr->viral_state_flags; + + if (o->mode == Addressing_Invalid) { + o->expr = node; + return kind; + } + if (o->mode == Addressing_Constant) { + gbString expr_str = expr_to_string(o->expr); + error(o->expr, "A type assertion cannot be applied to a constant expression: '%s'", expr_str); + gb_string_free(expr_str); + o->mode = Addressing_Invalid; + o->expr = node; + return kind; + } + + if (is_type_untyped(o->type)) { + gbString expr_str = expr_to_string(o->expr); + error(o->expr, "A type assertion cannot be applied to an untyped expression: '%s'", expr_str); + gb_string_free(expr_str); + o->mode = Addressing_Invalid; + o->expr = node; + return kind; + } + + Type *src = type_deref(o->type); + Type *bsrc = base_type(src); + + + if (ta->type != nullptr && ta->type->kind == Ast_UnaryExpr && ta->type->UnaryExpr.op.kind == Token_Question) { + if (!is_type_union(src)) { + gbString str = type_to_string(o->type); + error(o->expr, "Type assertions with .? can only operate on unions, got %s", str); + gb_string_free(str); + o->mode = Addressing_Invalid; + o->expr = node; + return kind; + } + + if (bsrc->Union.variants.count != 1 && type_hint != nullptr) { + bool allowed = false; + for_array(i, bsrc->Union.variants) { + Type *vt = bsrc->Union.variants[i]; + if (are_types_identical(vt, type_hint)) { + allowed = true; + add_type_info_type(c, vt); + break; + } + } + if (allowed) { + add_type_info_type(c, o->type); + o->type = type_hint; + o->mode = Addressing_OptionalOk; + return kind; + } + } + + if (bsrc->Union.variants.count != 1) { + error(o->expr, "Type assertions with .? can only operate on unions with 1 variant, got %lld", cast(long long)bsrc->Union.variants.count); + o->mode = Addressing_Invalid; + o->expr = node; + return kind; + } + + add_type_info_type(c, o->type); + add_type_info_type(c, bsrc->Union.variants[0]); + + o->type = bsrc->Union.variants[0]; + o->mode = Addressing_OptionalOk; + } else { + Type *t = check_type(c, ta->type); + Type *dst = t; + + if (is_type_union(src)) { + bool ok = false; + for_array(i, bsrc->Union.variants) { + Type *vt = bsrc->Union.variants[i]; + if (are_types_identical(vt, dst)) { + ok = true; + break; + } + } + + if (!ok) { + gbString expr_str = expr_to_string(o->expr); + gbString dst_type_str = type_to_string(t); + defer (gb_string_free(expr_str)); + defer (gb_string_free(dst_type_str)); + if (bsrc->Union.variants.count == 0) { + error(o->expr, "Cannot type assert '%s' to '%s' as this is an empty union", expr_str, dst_type_str); + } else { + error(o->expr, "Cannot type assert '%s' to '%s' as it is not a variant of that union", expr_str, dst_type_str); + } + o->mode = Addressing_Invalid; + o->expr = node; + return kind; + } + + add_type_info_type(c, o->type); + add_type_info_type(c, t); + + o->type = t; + o->mode = Addressing_OptionalOk; + } else if (is_type_any(src)) { + o->type = t; + o->mode = Addressing_OptionalOk; + + add_type_info_type(c, o->type); + add_type_info_type(c, t); + } else { + gbString str = type_to_string(o->type); + error(o->expr, "Type assertions can only operate on unions and 'any', got %s", str); + gb_string_free(str); + o->mode = Addressing_Invalid; + o->expr = node; + return kind; + } + } + + if ((c->state_flags & StateFlag_no_type_assert) == 0) { + add_package_dependency(c, "runtime", "type_assertion_check"); + add_package_dependency(c, "runtime", "type_assertion_check2"); + } + return kind; +} + +ExprKind check_selector_call_expr(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) { + ast_node(se, SelectorCallExpr, node); + // IMPORTANT NOTE(bill, 2020-05-22): This is a complete hack to get a shorthand which is extremely useful for vtables + // COM APIs is a great example of where this kind of thing is extremely useful + // General idea: + // + // x->y(123) == x.y(x, 123) + // + // How this has been implemented at the moment is quite hacky but it's done so to reduce need for huge backend changes + // Just regenerating a new AST aids things + // + // TODO(bill): Is this a good hack or not? + // + // NOTE(bill, 2020-05-22): I'm going to regret this decision, ain't I? + + + if (se->modified_call) { + // Prevent double evaluation + o->expr = node; + o->type = node->tav.type; + o->value = node->tav.value; + o->mode = node->tav.mode; + return Expr_Expr; + } + + bool allow_arrow_right_selector_expr; + allow_arrow_right_selector_expr = c->allow_arrow_right_selector_expr; + c->allow_arrow_right_selector_expr = true; + Operand x = {}; + ExprKind kind = check_expr_base(c, &x, se->expr, nullptr); + c->allow_arrow_right_selector_expr = allow_arrow_right_selector_expr; + + if (x.mode == Addressing_Invalid || x.type == t_invalid) { + o->mode = Addressing_Invalid; + o->type = t_invalid; + o->expr = node; + return kind; + } + if (!is_type_proc(x.type)) { + gbString type_str = type_to_string(x.type); + error(se->call, "Selector call expressions expect a procedure type for the call, got '%s'", type_str); + gb_string_free(type_str); + + o->mode = Addressing_Invalid; + o->type = t_invalid; + o->expr = node; + return Expr_Stmt; + } + + ast_node(ce, CallExpr, se->call); + + GB_ASSERT(x.expr->kind == Ast_SelectorExpr); + + Ast *first_arg = x.expr->SelectorExpr.expr; + GB_ASSERT(first_arg != nullptr); + + Type *pt = base_type(x.type); + GB_ASSERT(pt->kind == Type_Proc); + Type *first_type = nullptr; + String first_arg_name = {}; + if (pt->Proc.param_count > 0) { + Entity *f = pt->Proc.params->Tuple.variables[0]; + first_type = f->type; + first_arg_name = f->token.string; + } + if (first_arg_name.len == 0) { + first_arg_name = str_lit("_"); + } + + if (first_type == nullptr) { + error(se->call, "Selector call expressions expect a procedure type for the call with at least 1 parameter"); + o->mode = Addressing_Invalid; + o->type = t_invalid; + o->expr = node; + return Expr_Stmt; + } + + Operand y = {}; + y.mode = first_arg->tav.mode; + y.type = first_arg->tav.type; + y.value = first_arg->tav.value; + if (check_is_assignable_to(c, &y, first_type)) { + // Do nothing, it's valid + } else { + Operand z = y; + z.type = type_deref(y.type); + if (check_is_assignable_to(c, &z, first_type)) { + // NOTE(bill): AST GENERATION HACK! + Token op = {Token_Pointer}; + first_arg = ast_deref_expr(first_arg->file(), first_arg, op); + } else if (y.mode == Addressing_Variable) { + Operand w = y; + w.type = alloc_type_pointer(y.type); + if (check_is_assignable_to(c, &w, first_type)) { + // NOTE(bill): AST GENERATION HACK! + Token op = {Token_And}; + first_arg = ast_unary_expr(first_arg->file(), op, first_arg); + } + } + } + + if (ce->args.count > 0) { + bool fail = false; + bool first_is_field_value = (ce->args[0]->kind == Ast_FieldValue); + for_array(i, ce->args) { + Ast *arg = ce->args[i]; + bool mix = false; + if (first_is_field_value) { + mix = arg->kind != Ast_FieldValue; + } else { + mix = arg->kind == Ast_FieldValue; + } + if (mix) { + fail = true; + break; + } + } + if (!fail && first_is_field_value) { + Token op = {Token_Eq}; + AstFile *f = first_arg->file(); + first_arg = ast_field_value(f, ast_ident(f, make_token_ident(first_arg_name)), first_arg, op); + } + } + + + + auto modified_args = slice_make(heap_allocator(), ce->args.count+1); + modified_args[0] = first_arg; + slice_copy(&modified_args, ce->args, 1); + ce->args = modified_args; + se->modified_call = true; + + allow_arrow_right_selector_expr = c->allow_arrow_right_selector_expr; + c->allow_arrow_right_selector_expr = true; + check_expr_base(c, o, se->call, type_hint); + c->allow_arrow_right_selector_expr = allow_arrow_right_selector_expr; + + o->expr = node; + return Expr_Expr; +} + + +ExprKind check_index_expr(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) { + ExprKind kind = Expr_Expr; + ast_node(ie, IndexExpr, node); + check_expr(c, o, ie->expr); + node->viral_state_flags |= ie->expr->viral_state_flags; + if (o->mode == Addressing_Invalid) { + o->expr = node; + return kind; + } + + Type *t = base_type(type_deref(o->type)); + bool is_ptr = is_type_pointer(o->type); + bool is_const = o->mode == Addressing_Constant; + + if (is_type_map(t)) { + Operand key = {}; + if (is_type_typeid(t->Map.key)) { + check_expr_or_type(c, &key, ie->index, t->Map.key); + } else { + check_expr_with_type_hint(c, &key, ie->index, t->Map.key); + } + check_assignment(c, &key, t->Map.key, str_lit("map index")); + if (key.mode == Addressing_Invalid) { + o->mode = Addressing_Invalid; + o->expr = node; + return kind; + } + o->mode = Addressing_MapIndex; + o->type = t->Map.value; + o->expr = node; + + add_package_dependency(c, "runtime", "__dynamic_map_get"); + add_package_dependency(c, "runtime", "__dynamic_map_set"); + return Expr_Expr; + } + + i64 max_count = -1; + bool valid = check_set_index_data(o, t, is_ptr, &max_count, o->type); + + if (is_const) { + if (is_type_array(t)) { + // OKay + } else if (is_type_slice(t)) { + // Okay + } else if (is_type_enumerated_array(t)) { + // Okay + } else if (is_type_string(t)) { + // Okay + } else if (is_type_relative_slice(t)) { + // Okay + } else if (is_type_matrix(t)) { + // Okay + } else { + valid = false; + } + } + + if (!valid) { + gbString str = expr_to_string(o->expr); + gbString type_str = type_to_string(o->type); + defer (gb_string_free(str)); + defer (gb_string_free(type_str)); + if (is_const) { + error(o->expr, "Cannot index constant '%s' of type '%s'", str, type_str); + } else { + error(o->expr, "Cannot index '%s' of type '%s'", str, type_str); + } + o->mode = Addressing_Invalid; + o->expr = node; + return kind; + } + + if (ie->index == nullptr) { + gbString str = expr_to_string(o->expr); + error(o->expr, "Missing index for '%s'", str); + gb_string_free(str); + o->mode = Addressing_Invalid; + o->expr = node; + return kind; + } + + Type *index_type_hint = nullptr; + if (is_type_enumerated_array(t)) { + Type *bt = base_type(t); + GB_ASSERT(bt->kind == Type_EnumeratedArray); + index_type_hint = bt->EnumeratedArray.index; + } + + i64 index = 0; + bool ok = check_index_value(c, t, false, ie->index, max_count, &index, index_type_hint); + if (is_const) { + if (index < 0) { + gbString str = expr_to_string(o->expr); + error(o->expr, "Cannot index a constant '%s'", str); + error_line("\tSuggestion: store the constant into a variable in order to index it with a variable index\n"); + gb_string_free(str); + o->mode = Addressing_Invalid; + o->expr = node; + return kind; + } else if (ok) { + ExactValue value = type_and_value_of_expr(ie->expr).value; + o->mode = Addressing_Constant; + bool success = false; + bool finish = false; + o->value = get_constant_field_single(c, value, cast(i32)index, &success, &finish); + if (!success) { + gbString str = expr_to_string(o->expr); + error(o->expr, "Cannot index a constant '%s' with index %lld", str, cast(long long)index); + error_line("\tSuggestion: store the constant into a variable in order to index it with a variable index\n"); + gb_string_free(str); + o->mode = Addressing_Invalid; + o->expr = node; + return kind; + } + } + } + + if (type_hint != nullptr && is_type_matrix(t)) { + // TODO(bill): allow matrix columns to be assignable to other types which are the same internally + // if a type hint exists + } + return kind; +} + +ExprKind check_slice_expr(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) { + ExprKind kind = Expr_Stmt; + ast_node(se, SliceExpr, node); + check_expr(c, o, se->expr); + node->viral_state_flags |= se->expr->viral_state_flags; + + if (o->mode == Addressing_Invalid) { + o->mode = Addressing_Invalid; + o->expr = node; + return kind; + } + + bool valid = false; + i64 max_count = -1; + Type *t = base_type(type_deref(o->type)); + switch (t->kind) { + case Type_Basic: + if (t->Basic.kind == Basic_string || t->Basic.kind == Basic_UntypedString) { + valid = true; + if (o->mode == Addressing_Constant) { + max_count = o->value.value_string.len; + } + o->type = type_deref(o->type); + } + break; + + case Type_Array: + valid = true; + max_count = t->Array.count; + if (o->mode != Addressing_Variable && !is_type_pointer(o->type)) { + gbString str = expr_to_string(node); + error(node, "Cannot slice array '%s', value is not addressable", str); + gb_string_free(str); + o->mode = Addressing_Invalid; + o->expr = node; + return kind; + } + o->type = alloc_type_slice(t->Array.elem); + break; + + case Type_MultiPointer: + valid = true; + o->type = type_deref(o->type); + break; + + case Type_Slice: + valid = true; + o->type = type_deref(o->type); + break; + + case Type_DynamicArray: + valid = true; + o->type = alloc_type_slice(t->DynamicArray.elem); + break; + + case Type_Struct: + if (is_type_soa_struct(t)) { + valid = true; + o->type = make_soa_struct_slice(c, nullptr, nullptr, t->Struct.soa_elem); + } + break; + + case Type_RelativeSlice: + valid = true; + o->type = t->RelativeSlice.slice_type; + if (o->mode != Addressing_Variable) { + gbString str = expr_to_string(node); + error(node, "Cannot relative slice '%s', value is not addressable", str); + gb_string_free(str); + o->mode = Addressing_Invalid; + o->expr = node; + return kind; + } + break; + } + + if (!valid) { + gbString str = expr_to_string(o->expr); + gbString type_str = type_to_string(o->type); + error(o->expr, "Cannot slice '%s' of type '%s'", str, type_str); + gb_string_free(type_str); + gb_string_free(str); + o->mode = Addressing_Invalid; + o->expr = node; + return kind; + } + + if (se->low == nullptr && se->high != nullptr) { + // It is okay to continue as it will assume the 1st index is zero + } + + i64 indices[2] = {}; + Ast *nodes[2] = {se->low, se->high}; + for (isize i = 0; i < gb_count_of(nodes); i++) { + i64 index = max_count; + if (nodes[i] != nullptr) { + i64 capacity = -1; + if (max_count >= 0) { + capacity = max_count; + } + i64 j = 0; + if (check_index_value(c, t, true, nodes[i], capacity, &j)) { + index = j; + } + + node->viral_state_flags |= nodes[i]->viral_state_flags; + } else if (i == 0) { + index = 0; + } + indices[i] = index; + } + + for (isize i = 0; i < gb_count_of(indices); i++) { + i64 a = indices[i]; + for (isize j = i+1; j < gb_count_of(indices); j++) { + i64 b = indices[j]; + if (a > b && b >= 0) { + error(se->close, "Invalid slice indices: [%td > %td]", a, b); + } + } + } + + if (max_count < 0) { + if (o->mode == Addressing_Constant) { + gbString s = expr_to_string(se->expr); + error(se->expr, "Cannot slice constant value '%s'", s); + gb_string_free(s); + } + } + + if (t->kind == Type_MultiPointer && se->high != nullptr) { + /* + x[:] -> [^]T + x[i:] -> [^]T + x[:n] -> []T + x[i:n] -> []T + */ + o->type = alloc_type_slice(t->MultiPointer.elem); + } + + o->mode = Addressing_Value; + + if (is_type_string(t) && max_count >= 0) { + bool all_constant = true; + for (isize i = 0; i < gb_count_of(nodes); i++) { + if (nodes[i] != nullptr) { + TypeAndValue tav = type_and_value_of_expr(nodes[i]); + if (tav.mode != Addressing_Constant) { + all_constant = false; + break; + } + } + } + if (!all_constant) { + gbString str = expr_to_string(o->expr); + error(o->expr, "Cannot slice '%s' with non-constant indices", str); + error_line("\tSuggestion: store the constant into a variable in order to index it with a variable index\n"); + gb_string_free(str); + o->mode = Addressing_Value; // NOTE(bill): Keep subsequent values going without erring + o->expr = node; + return kind; + } + + String s = {}; + if (o->value.kind == ExactValue_String) { + s = o->value.value_string; + } + + o->mode = Addressing_Constant; + o->type = t; + o->value = exact_value_string(substring(s, cast(isize)indices[0], cast(isize)indices[1])); + } + return kind; +} ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) { u32 prev_state_flags = c->state_flags; @@ -7189,52 +8988,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type case_end; case_ast_node(bd, BasicDirective, node); - o->mode = Addressing_Constant; - String name = bd->name.string; - if (name == "file") { - o->type = t_untyped_string; - o->value = exact_value_string(get_file_path_string(bd->token.pos.file_id)); - } else if (name == "line") { - o->type = t_untyped_integer; - o->value = exact_value_i64(bd->token.pos.line); - } else if (name == "procedure") { - if (c->curr_proc_decl == nullptr) { - error(node, "#procedure may only be used within procedures"); - o->type = t_untyped_string; - o->value = exact_value_string(str_lit("")); - } else { - o->type = t_untyped_string; - o->value = exact_value_string(c->proc_name); - } - } else if (name == "caller_location") { - init_core_source_code_location(c->checker); - error(node, "#caller_location may only be used as a default argument parameter"); - o->type = t_source_code_location; - o->mode = Addressing_Value; - } else { - if (name == "location") { - init_core_source_code_location(c->checker); - error(node, "'#%.*s' must be used in a call expression", LIT(name)); - o->type = t_source_code_location; - o->mode = Addressing_Value; - } else if ( - name == "assert" || - name == "defined" || - name == "config" || - name == "load" || - name == "load_hash" || - name == "load_or" - ) { - error(node, "'#%.*s' must be used as a call", LIT(name)); - o->type = t_invalid; - o->mode = Addressing_Invalid; - } else { - error(node, "Unknown directive: #%.*s", LIT(name)); - o->type = t_invalid; - o->mode = Addressing_Invalid; - } - - } + kind = check_basic_directive_expr(c, o, node, type_hint); case_end; case_ast_node(pg, ProcGroup, node); @@ -7283,1165 +9037,23 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type case_end; case_ast_node(te, TernaryIfExpr, node); - Operand cond = {Addressing_Invalid}; - check_expr(c, &cond, te->cond); - node->viral_state_flags |= te->cond->viral_state_flags; - - if (cond.mode != Addressing_Invalid && !is_type_boolean(cond.type)) { - error(te->cond, "Non-boolean condition in ternary if expression"); - } - - Operand x = {Addressing_Invalid}; - Operand y = {Addressing_Invalid}; - check_expr_or_type(c, &x, te->x, type_hint); - node->viral_state_flags |= te->x->viral_state_flags; - - if (te->y != nullptr) { - check_expr_or_type(c, &y, te->y, type_hint); - node->viral_state_flags |= te->y->viral_state_flags; - } else { - error(node, "A ternary expression must have an else clause"); - return kind; - } - - if (x.type == nullptr || x.type == t_invalid || - y.type == nullptr || y.type == t_invalid) { - return kind; - } - - convert_to_typed(c, &x, y.type); - if (x.mode == Addressing_Invalid) { - return kind; - } - convert_to_typed(c, &y, x.type); - if (y.mode == Addressing_Invalid) { - x.mode = Addressing_Invalid; - return kind; - } - - if (!ternary_compare_types(x.type, y.type)) { - gbString its = type_to_string(x.type); - gbString ets = type_to_string(y.type); - error(node, "Mismatched types in ternary if expression, %s vs %s", its, ets); - gb_string_free(ets); - gb_string_free(its); - return kind; - } - - o->type = x.type; - if (is_type_untyped_nil(o->type) || is_type_untyped_undef(o->type)) { - o->type = y.type; - } - - o->mode = Addressing_Value; - o->expr = node; - if (type_hint != nullptr && is_type_untyped(o->type)) { - if (check_cast_internal(c, &x, type_hint) && - check_cast_internal(c, &y, type_hint)) { - convert_to_typed(c, o, type_hint); - update_untyped_expr_type(c, node, type_hint, !is_type_untyped(type_hint)); - } - } + kind = check_ternary_if_expr(c, o, node, type_hint); case_end; case_ast_node(te, TernaryWhenExpr, node); - Operand cond = {}; - check_expr(c, &cond, te->cond); - node->viral_state_flags |= te->cond->viral_state_flags; - - if (cond.mode != Addressing_Constant || !is_type_boolean(cond.type)) { - error(te->cond, "Expected a constant boolean condition in ternary when expression"); - return kind; - } - - if (cond.value.value_bool) { - check_expr_or_type(c, o, te->x, type_hint); - node->viral_state_flags |= te->x->viral_state_flags; - } else { - if (te->y != nullptr) { - check_expr_or_type(c, o, te->y, type_hint); - node->viral_state_flags |= te->y->viral_state_flags; - } else { - error(node, "A ternary when expression must have an else clause"); - return kind; - } - } + kind = check_ternary_when_expr(c, o, node, type_hint); case_end; case_ast_node(oe, OrElseExpr, node); - String name = oe->token.string; - Ast *arg = oe->x; - Ast *default_value = oe->y; - - Operand x = {}; - Operand y = {}; - check_multi_expr_with_type_hint(c, &x, arg, type_hint); - if (x.mode == Addressing_Invalid) { - o->mode = Addressing_Value; - o->type = t_invalid; - o->expr = node; - return Expr_Expr; - } - - check_multi_expr_with_type_hint(c, &y, default_value, x.type); - error_operand_no_value(&y); - if (y.mode == Addressing_Invalid) { - o->mode = Addressing_Value; - o->type = t_invalid; - o->expr = node; - return Expr_Expr; - } - - Type *left_type = nullptr; - Type *right_type = nullptr; - check_or_else_split_types(c, &x, name, &left_type, &right_type); - add_type_and_value(&c->checker->info, arg, x.mode, x.type, x.value); - - if (left_type != nullptr) { - check_assignment(c, &y, left_type, name); - } else { - check_or_else_expr_no_value_error(c, name, x, type_hint); - } - - if (left_type == nullptr) { - left_type = t_invalid; - } - o->mode = Addressing_Value; - o->type = left_type; - o->expr = node; - return Expr_Expr; + return check_or_else_expr(c, o, node, type_hint); case_end; case_ast_node(re, OrReturnExpr, node); - String name = re->token.string; - Operand x = {}; - check_multi_expr_with_type_hint(c, &x, re->expr, type_hint); - if (x.mode == Addressing_Invalid) { - o->mode = Addressing_Value; - o->type = t_invalid; - o->expr = node; - return Expr_Expr; - } - - Type *left_type = nullptr; - Type *right_type = nullptr; - check_or_return_split_types(c, &x, name, &left_type, &right_type); - add_type_and_value(&c->checker->info, re->expr, x.mode, x.type, x.value); - - if (right_type == nullptr) { - check_or_else_expr_no_value_error(c, name, x, type_hint); - } else { - Type *proc_type = base_type(c->curr_proc_sig); - GB_ASSERT(proc_type->kind == Type_Proc); - Type *result_type = proc_type->Proc.results; - if (result_type == nullptr) { - error(node, "'%.*s' requires the current procedure to have at least one return value", LIT(name)); - } else { - GB_ASSERT(result_type->kind == Type_Tuple); - - auto const &vars = result_type->Tuple.variables; - Type *end_type = vars[vars.count-1]->type; - - if (vars.count > 1) { - if (!proc_type->Proc.has_named_results) { - error(node, "'%.*s' within a procedure with more than 1 return value requires that the return values are named, allowing for early return", LIT(name)); - } - } - - Operand rhs = {}; - rhs.type = right_type; - rhs.mode = Addressing_Value; - - // TODO(bill): better error message - if (!check_is_assignable_to(c, &rhs, end_type)) { - gbString a = type_to_string(right_type); - gbString b = type_to_string(end_type); - gbString ret_type = type_to_string(result_type); - error(node, "Cannot assign end value of type '%s' to '%s' in '%.*s'", a, b, LIT(name)); - if (vars.count == 1) { - error_line("\tProcedure return value type: %s\n", ret_type); - } else { - error_line("\tProcedure return value types: (%s)\n", ret_type); - } - gb_string_free(ret_type); - gb_string_free(b); - gb_string_free(a); - } - } - } - - o->expr = node; - o->type = left_type; - if (left_type != nullptr) { - o->mode = Addressing_Value; - } else { - o->mode = Addressing_NoValue; - } - - if (c->curr_proc_sig == nullptr) { - error(node, "'%.*s' can only be used within a procedure", LIT(name)); - } - - if (c->in_defer) { - error(node, "'or_return' cannot be used within a defer statement"); - } - - return Expr_Expr; + return check_or_return_expr(c, o, node, type_hint); case_end; case_ast_node(cl, CompoundLit, node); - Type *type = type_hint; - if (type != nullptr && is_type_untyped(type)) { - type = nullptr; - } - bool is_to_be_determined_array_count = false; - bool is_constant = true; - if (cl->type != nullptr) { - type = nullptr; - - // [?]Type - if (cl->type->kind == Ast_ArrayType && cl->type->ArrayType.count != nullptr) { - Ast *count = cl->type->ArrayType.count; - if (count->kind == Ast_UnaryExpr && - count->UnaryExpr.op.kind == Token_Question) { - type = alloc_type_array(check_type(c, cl->type->ArrayType.elem), -1); - is_to_be_determined_array_count = true; - } - if (cl->elems.count > 0) { - if (cl->type->ArrayType.tag != nullptr) { - Ast *tag = cl->type->ArrayType.tag; - GB_ASSERT(tag->kind == Ast_BasicDirective); - String name = tag->BasicDirective.name.string; - if (name == "soa") { - error(node, "#soa arrays are not supported for compound literals"); - return kind; - } - } - } - } - if (cl->type->kind == Ast_DynamicArrayType && cl->type->DynamicArrayType.tag != nullptr) { - if (cl->elems.count > 0) { - Ast *tag = cl->type->DynamicArrayType.tag; - GB_ASSERT(tag->kind == Ast_BasicDirective); - String name = tag->BasicDirective.name.string; - if (name == "soa") { - error(node, "#soa arrays are not supported for compound literals"); - return kind; - } - } - } - - if (type == nullptr) { - type = check_type(c, cl->type); - } - } - - if (type == nullptr) { - error(node, "Missing type in compound literal"); - return kind; - } - - - Type *t = base_type(type); - if (is_type_polymorphic(t)) { - gbString str = type_to_string(type); - error(node, "Cannot use a polymorphic type for a compound literal, got '%s'", str); - o->expr = node; - o->type = type; - gb_string_free(str); - return kind; - } - - - switch (t->kind) { - case Type_Struct: { - if (cl->elems.count == 0) { - break; // NOTE(bill): No need to init - } - if (t->Struct.is_raw_union) { - if (cl->elems.count > 0) { - // NOTE: unions cannot be constant - is_constant = false; - - if (cl->elems[0]->kind != Ast_FieldValue) { - gbString type_str = type_to_string(type); - error(node, "%s ('struct #raw_union') compound literals are only allowed to contain 'field = value' elements", type_str); - gb_string_free(type_str); - } else { - if (cl->elems.count != 1) { - gbString type_str = type_to_string(type); - error(node, "%s ('struct #raw_union') compound literals are only allowed to contain up to 1 'field = value' element, got %td", type_str, cl->elems.count); - gb_string_free(type_str); - } else { - Ast *elem = cl->elems[0]; - ast_node(fv, FieldValue, elem); - if (fv->field->kind != Ast_Ident) { - gbString expr_str = expr_to_string(fv->field); - error(elem, "Invalid field name '%s' in structure literal", expr_str); - gb_string_free(expr_str); - break; - } - - String name = fv->field->Ident.token.string; - - Selection sel = lookup_field(type, name, o->mode == Addressing_Type); - bool is_unknown = sel.entity == nullptr; - if (is_unknown) { - error(elem, "Unknown field '%.*s' in structure literal", LIT(name)); - break; - } - - if (sel.index.count > 1) { - error(elem, "Cannot assign to an anonymous field '%.*s' in a structure literal (at the moment)", LIT(name)); - break; - } - - Entity *field = t->Struct.fields[sel.index[0]]; - add_entity_use(c, fv->field, field); - - Operand o = {}; - check_expr_or_type(c, &o, fv->value, field->type); - - - check_assignment(c, &o, field->type, str_lit("structure literal")); - } - - } - } - break; - } - - - isize field_count = t->Struct.fields.count; - isize min_field_count = t->Struct.fields.count; - for (isize i = min_field_count-1; i >= 0; i--) { - Entity *e = t->Struct.fields[i]; - GB_ASSERT(e->kind == Entity_Variable); - if (e->Variable.param_value.kind != ParameterValue_Invalid) { - min_field_count--; - } else { - break; - } - } - - if (cl->elems[0]->kind == Ast_FieldValue) { - bool *fields_visited = gb_alloc_array(temporary_allocator(), bool, field_count); - - for_array(i, cl->elems) { - Ast *elem = cl->elems[i]; - if (elem->kind != Ast_FieldValue) { - error(elem, "Mixture of 'field = value' and value elements in a literal is not allowed"); - continue; - } - ast_node(fv, FieldValue, elem); - if (fv->field->kind != Ast_Ident) { - gbString expr_str = expr_to_string(fv->field); - error(elem, "Invalid field name '%s' in structure literal", expr_str); - gb_string_free(expr_str); - continue; - } - String name = fv->field->Ident.token.string; - - Selection sel = lookup_field(type, name, o->mode == Addressing_Type); - bool is_unknown = sel.entity == nullptr; - if (is_unknown) { - error(elem, "Unknown field '%.*s' in structure literal", LIT(name)); - continue; - } - - if (sel.index.count > 1) { - error(elem, "Cannot assign to an anonymous field '%.*s' in a structure literal (at the moment)", LIT(name)); - continue; - } - - Entity *field = t->Struct.fields[sel.index[0]]; - add_entity_use(c, fv->field, field); - - if (fields_visited[sel.index[0]]) { - error(elem, "Duplicate field '%.*s' in structure literal", LIT(name)); - continue; - } - - fields_visited[sel.index[0]] = true; - - Operand o = {}; - check_expr_or_type(c, &o, fv->value, field->type); - - if (is_type_any(field->type) || is_type_union(field->type) || is_type_raw_union(field->type) || is_type_typeid(field->type)) { - is_constant = false; - } - if (is_constant) { - is_constant = check_is_operand_compound_lit_constant(c, &o); - } - - check_assignment(c, &o, field->type, str_lit("structure literal")); - } - } else { - bool seen_field_value = false; - - for_array(index, cl->elems) { - Entity *field = nullptr; - Ast *elem = cl->elems[index]; - if (elem->kind == Ast_FieldValue) { - seen_field_value = true; - error(elem, "Mixture of 'field = value' and value elements in a literal is not allowed"); - continue; - } else if (seen_field_value) { - error(elem, "Value elements cannot be used after a 'field = value'"); - continue; - } - if (index >= field_count) { - error(elem, "Too many values in structure literal, expected %td, got %td", field_count, cl->elems.count); - break; - } - - if (field == nullptr) { - field = t->Struct.fields[index]; - } - - Operand o = {}; - check_expr_or_type(c, &o, elem, field->type); - - if (is_type_any(field->type) || is_type_union(field->type) || is_type_raw_union(field->type) || is_type_typeid(field->type)) { - is_constant = false; - } - if (is_constant) { - is_constant = check_is_operand_compound_lit_constant(c, &o); - } - - check_assignment(c, &o, field->type, str_lit("structure literal")); - } - if (cl->elems.count < field_count) { - if (min_field_count < field_count) { - if (cl->elems.count < min_field_count) { - error(cl->close, "Too few values in structure literal, expected at least %td, got %td", min_field_count, cl->elems.count); - } - } else { - error(cl->close, "Too few values in structure literal, expected %td, got %td", field_count, cl->elems.count); - } - } - } - - break; - } - - case Type_Slice: - case Type_Array: - case Type_DynamicArray: - case Type_SimdVector: - case Type_Matrix: - { - Type *elem_type = nullptr; - String context_name = {}; - i64 max_type_count = -1; - if (t->kind == Type_Slice) { - elem_type = t->Slice.elem; - context_name = str_lit("slice literal"); - } else if (t->kind == Type_Array) { - elem_type = t->Array.elem; - context_name = str_lit("array literal"); - if (!is_to_be_determined_array_count) { - max_type_count = t->Array.count; - } - } else if (t->kind == Type_DynamicArray) { - elem_type = t->DynamicArray.elem; - context_name = str_lit("dynamic array literal"); - is_constant = false; - - if (!build_context.no_dynamic_literals) { - add_package_dependency(c, "runtime", "__dynamic_array_reserve"); - add_package_dependency(c, "runtime", "__dynamic_array_append"); - } - } else if (t->kind == Type_SimdVector) { - elem_type = t->SimdVector.elem; - context_name = str_lit("simd vector literal"); - max_type_count = t->SimdVector.count; - } else if (t->kind == Type_Matrix) { - elem_type = t->Matrix.elem; - context_name = str_lit("matrix literal"); - max_type_count = t->Matrix.row_count*t->Matrix.column_count; - } else { - GB_PANIC("unreachable"); - } - - - i64 max = 0; - - Type *bet = base_type(elem_type); - if (!elem_type_can_be_constant(bet)) { - is_constant = false; - } - - if (bet == t_invalid) { - break; - } - - if (cl->elems.count > 0 && cl->elems[0]->kind == Ast_FieldValue) { - if (is_type_simd_vector(t)) { - error(cl->elems[0], "'field = value' is not allowed for SIMD vector literals"); - } else { - RangeCache rc = range_cache_make(heap_allocator()); - defer (range_cache_destroy(&rc)); - - for_array(i, cl->elems) { - Ast *elem = cl->elems[i]; - if (elem->kind != Ast_FieldValue) { - error(elem, "Mixture of 'field = value' and value elements in a literal is not allowed"); - continue; - } - ast_node(fv, FieldValue, elem); - - if (is_ast_range(fv->field)) { - Token op = fv->field->BinaryExpr.op; - - Operand x = {}; - Operand y = {}; - bool ok = check_range(c, fv->field, &x, &y, nullptr); - if (!ok) { - continue; - } - if (x.mode != Addressing_Constant || !is_type_integer(core_type(x.type))) { - error(x.expr, "Expected a constant integer as an array field"); - continue; - } - - if (y.mode != Addressing_Constant || !is_type_integer(core_type(y.type))) { - error(y.expr, "Expected a constant integer as an array field"); - continue; - } - - i64 lo = exact_value_to_i64(x.value); - i64 hi = exact_value_to_i64(y.value); - i64 max_index = hi; - if (op.kind == Token_RangeHalf) { // ..< (exclusive) - hi -= 1; - } else { // .. (inclusive) - max_index += 1; - } - - bool new_range = range_cache_add_range(&rc, lo, hi); - if (!new_range) { - error(elem, "Overlapping field range index %lld %.*s %lld for %.*s", lo, LIT(op.string), hi, LIT(context_name)); - continue; - } - - - if (max_type_count >= 0 && (lo < 0 || lo >= max_type_count)) { - error(elem, "Index %lld is out of bounds (0..<%lld) for %.*s", lo, max_type_count, LIT(context_name)); - continue; - } - if (max_type_count >= 0 && (hi < 0 || hi >= max_type_count)) { - error(elem, "Index %lld is out of bounds (0..<%lld) for %.*s", hi, max_type_count, LIT(context_name)); - continue; - } - - if (max < hi) { - max = max_index; - } - - Operand operand = {}; - check_expr_with_type_hint(c, &operand, fv->value, elem_type); - check_assignment(c, &operand, elem_type, context_name); - - is_constant = is_constant && operand.mode == Addressing_Constant; - } else { - Operand op_index = {}; - check_expr(c, &op_index, fv->field); - - if (op_index.mode != Addressing_Constant || !is_type_integer(core_type(op_index.type))) { - error(elem, "Expected a constant integer as an array field"); - continue; - } - // add_type_and_value(c->info, op_index.expr, op_index.mode, op_index.type, op_index.value); - - i64 index = exact_value_to_i64(op_index.value); - - if (max_type_count >= 0 && (index < 0 || index >= max_type_count)) { - error(elem, "Index %lld is out of bounds (0..<%lld) for %.*s", index, max_type_count, LIT(context_name)); - continue; - } - - bool new_index = range_cache_add_index(&rc, index); - if (!new_index) { - error(elem, "Duplicate field index %lld for %.*s", index, LIT(context_name)); - continue; - } - - if (max < index+1) { - max = index+1; - } - - Operand operand = {}; - check_expr_with_type_hint(c, &operand, fv->value, elem_type); - check_assignment(c, &operand, elem_type, context_name); - - is_constant = is_constant && operand.mode == Addressing_Constant; - } - } - - cl->max_count = max; - } - - } else { - isize index = 0; - for (; index < cl->elems.count; index++) { - Ast *e = cl->elems[index]; - if (e == nullptr) { - error(node, "Invalid literal element"); - continue; - } - - if (e->kind == Ast_FieldValue) { - error(e, "Mixture of 'field = value' and value elements in a literal is not allowed"); - continue; - } - - if (0 <= max_type_count && max_type_count <= index) { - error(e, "Index %lld is out of bounds (>= %lld) for %.*s", index, max_type_count, LIT(context_name)); - } - - Operand operand = {}; - check_expr_with_type_hint(c, &operand, e, elem_type); - check_assignment(c, &operand, elem_type, context_name); - - is_constant = is_constant && operand.mode == Addressing_Constant; - } - - if (max < index) { - max = index; - } - } - - - if (t->kind == Type_Array) { - if (is_to_be_determined_array_count) { - t->Array.count = max; - } else if (cl->elems.count > 0 && cl->elems[0]->kind != Ast_FieldValue) { - if (0 < max && max < t->Array.count) { - error(node, "Expected %lld values for this array literal, got %lld", cast(long long)t->Array.count, cast(long long)max); - } - } - } - - - if (t->kind == Type_SimdVector) { - if (!is_constant) { - error(node, "Expected all constant elements for a simd vector"); - } - } - - - if (t->kind == Type_DynamicArray) { - if (build_context.no_dynamic_literals && cl->elems.count) { - error(node, "Compound literals of dynamic types have been disabled"); - } - } - - if (t->kind == Type_Matrix) { - if (cl->elems.count > 0 && cl->elems[0]->kind != Ast_FieldValue) { - if (0 < max && max < max_type_count) { - error(node, "Expected %lld values for this matrix literal, got %lld", cast(long long)max_type_count, cast(long long)max); - } - } - } - - break; - } - - case Type_EnumeratedArray: - { - Type *elem_type = t->EnumeratedArray.elem; - Type *index_type = t->EnumeratedArray.index; - String context_name = str_lit("enumerated array literal"); - i64 max_type_count = t->EnumeratedArray.count; - - gbString index_type_str = type_to_string(index_type); - defer (gb_string_free(index_type_str)); - - i64 total_lo = exact_value_to_i64(*t->EnumeratedArray.min_value); - i64 total_hi = exact_value_to_i64(*t->EnumeratedArray.max_value); - - String total_lo_string = {}; - String total_hi_string = {}; - GB_ASSERT(is_type_enum(index_type)); - { - Type *bt = base_type(index_type); - GB_ASSERT(bt->kind == Type_Enum); - for_array(i, bt->Enum.fields) { - Entity *f = bt->Enum.fields[i]; - if (f->kind != Entity_Constant) { - continue; - } - if (total_lo_string.len == 0 && compare_exact_values(Token_CmpEq, f->Constant.value, *t->EnumeratedArray.min_value)) { - total_lo_string = f->token.string; - } - if (total_hi_string.len == 0 && compare_exact_values(Token_CmpEq, f->Constant.value, *t->EnumeratedArray.max_value)) { - total_hi_string = f->token.string; - } - if (total_lo_string.len != 0 && total_hi_string.len != 0) { - break; - } - } - } - - i64 max = 0; - - Type *bet = base_type(elem_type); - if (!elem_type_can_be_constant(bet)) { - is_constant = false; - } - - if (bet == t_invalid) { - break; - } - bool is_partial = cl->tag && (cl->tag->BasicDirective.name.string == "partial"); - - SeenMap seen = {}; // NOTE(bill): Multimap, Key: ExactValue - map_init(&seen, heap_allocator()); - defer (map_destroy(&seen)); - - if (cl->elems.count > 0 && cl->elems[0]->kind == Ast_FieldValue) { - RangeCache rc = range_cache_make(heap_allocator()); - defer (range_cache_destroy(&rc)); - - for_array(i, cl->elems) { - Ast *elem = cl->elems[i]; - if (elem->kind != Ast_FieldValue) { - error(elem, "Mixture of 'field = value' and value elements in a literal is not allowed"); - continue; - } - ast_node(fv, FieldValue, elem); - - if (is_ast_range(fv->field)) { - Token op = fv->field->BinaryExpr.op; - - Operand x = {}; - Operand y = {}; - bool ok = check_range(c, fv->field, &x, &y, nullptr, index_type); - if (!ok) { - continue; - } - if (x.mode != Addressing_Constant || !are_types_identical(x.type, index_type)) { - error(x.expr, "Expected a constant enum of type '%s' as an array field", index_type_str); - continue; - } - - if (y.mode != Addressing_Constant || !are_types_identical(x.type, index_type)) { - error(y.expr, "Expected a constant enum of type '%s' as an array field", index_type_str); - continue; - } - - i64 lo = exact_value_to_i64(x.value); - i64 hi = exact_value_to_i64(y.value); - i64 max_index = hi; - if (op.kind == Token_RangeHalf) { - hi -= 1; - } - - bool new_range = range_cache_add_range(&rc, lo, hi); - if (!new_range) { - gbString lo_str = expr_to_string(x.expr); - gbString hi_str = expr_to_string(y.expr); - error(elem, "Overlapping field range index %s %.*s %s for %.*s", lo_str, LIT(op.string), hi_str, LIT(context_name)); - gb_string_free(hi_str); - gb_string_free(lo_str); - continue; - } - - - // NOTE(bill): These are sanity checks for invalid enum values - if (max_type_count >= 0 && (lo < total_lo || lo > total_hi)) { - gbString lo_str = expr_to_string(x.expr); - error(elem, "Index %s is out of bounds (%.*s .. %.*s) for %.*s", lo_str, LIT(total_lo_string), LIT(total_hi_string), LIT(context_name)); - gb_string_free(lo_str); - continue; - } - if (max_type_count >= 0 && (hi < 0 || hi > total_hi)) { - gbString hi_str = expr_to_string(y.expr); - error(elem, "Index %s is out of bounds (%.*s .. %.*s) for %.*s", hi_str, LIT(total_lo_string), LIT(total_hi_string), LIT(context_name)); - gb_string_free(hi_str); - continue; - } - - if (max < hi) { - max = max_index; - } - - Operand operand = {}; - check_expr_with_type_hint(c, &operand, fv->value, elem_type); - check_assignment(c, &operand, elem_type, context_name); - - is_constant = is_constant && operand.mode == Addressing_Constant; - - TokenKind upper_op = Token_LtEq; - if (op.kind == Token_RangeHalf) { - upper_op = Token_Lt; - } - add_to_seen_map(c, &seen, upper_op, x, x, y); - } else { - Operand op_index = {}; - check_expr_with_type_hint(c, &op_index, fv->field, index_type); - - if (op_index.mode != Addressing_Constant || !are_types_identical(op_index.type, index_type)) { - error(op_index.expr, "Expected a constant enum of type '%s' as an array field", index_type_str); - continue; - } - - i64 index = exact_value_to_i64(op_index.value); - - if (max_type_count >= 0 && (index < total_lo || index > total_hi)) { - gbString idx_str = expr_to_string(op_index.expr); - error(elem, "Index %s is out of bounds (%.*s .. %.*s) for %.*s", idx_str, LIT(total_lo_string), LIT(total_hi_string), LIT(context_name)); - gb_string_free(idx_str); - continue; - } - - bool new_index = range_cache_add_index(&rc, index); - if (!new_index) { - gbString idx_str = expr_to_string(op_index.expr); - error(elem, "Duplicate field index %s for %.*s", idx_str, LIT(context_name)); - gb_string_free(idx_str); - continue; - } - - if (max < index+1) { - max = index+1; - } - - Operand operand = {}; - check_expr_with_type_hint(c, &operand, fv->value, elem_type); - check_assignment(c, &operand, elem_type, context_name); - - is_constant = is_constant && operand.mode == Addressing_Constant; - - add_to_seen_map(c, &seen, op_index); - } - } - - cl->max_count = max; - - } else { - isize index = 0; - for (; index < cl->elems.count; index++) { - Ast *e = cl->elems[index]; - if (e == nullptr) { - error(node, "Invalid literal element"); - continue; - } - - if (e->kind == Ast_FieldValue) { - error(e, "Mixture of 'field = value' and value elements in a literal is not allowed"); - continue; - } - - if (0 <= max_type_count && max_type_count <= index) { - error(e, "Index %lld is out of bounds (>= %lld) for %.*s", index, max_type_count, LIT(context_name)); - } - - Operand operand = {}; - check_expr_with_type_hint(c, &operand, e, elem_type); - check_assignment(c, &operand, elem_type, context_name); - - is_constant = is_constant && operand.mode == Addressing_Constant; - } - - if (max < index) { - max = index; - } - } - - bool was_error = false; - if (cl->elems.count > 0 && cl->elems[0]->kind != Ast_FieldValue) { - if (0 < max && max < t->EnumeratedArray.count) { - error(node, "Expected %lld values for this enumerated array literal, got %lld", cast(long long)t->EnumeratedArray.count, cast(long long)max); - was_error = true; - } else { - error(node, "Enumerated array literals must only have 'field = value' elements, bare elements are not allowed"); - was_error = true; - } - } - - // NOTE(bill): Check for missing cases when `#partial literal` is not present - if (cl->elems.count > 0 && !was_error && !is_partial) { - Type *et = base_type(index_type); - GB_ASSERT(et->kind == Type_Enum); - auto fields = et->Enum.fields; - - auto unhandled = array_make(temporary_allocator(), 0, fields.count); - - for_array(i, fields) { - Entity *f = fields[i]; - if (f->kind != Entity_Constant) { - continue; - } - ExactValue v = f->Constant.value; - auto found = map_get(&seen, hash_exact_value(v)); - if (!found) { - array_add(&unhandled, f); - } - } - - if (unhandled.count > 0) { - begin_error_block(); - defer (end_error_block()); - - if (unhandled.count == 1) { - error_no_newline(node, "Unhandled enumerated array case: %.*s", LIT(unhandled[0]->token.string)); - } else { - error(node, "Unhandled enumerated array cases:"); - for_array(i, unhandled) { - Entity *f = unhandled[i]; - error_line("\t%.*s\n", LIT(f->token.string)); - } - } - error_line("\n"); - - error_line("\tSuggestion: Was '#partial %s{...}' wanted?\n", type_to_string(type)); - } - } - - break; - } - - case Type_Basic: { - if (!is_type_any(t)) { - if (cl->elems.count != 0) { - error(node, "Illegal compound literal"); - } - break; - } - if (cl->elems.count == 0) { - break; // NOTE(bill): No need to init - } - { // Checker values - Type *field_types[2] = {t_rawptr, t_typeid}; - isize field_count = 2; - if (cl->elems[0]->kind == Ast_FieldValue) { - bool fields_visited[2] = {}; - - for_array(i, cl->elems) { - Ast *elem = cl->elems[i]; - if (elem->kind != Ast_FieldValue) { - error(elem, "Mixture of 'field = value' and value elements in a 'any' literal is not allowed"); - continue; - } - ast_node(fv, FieldValue, elem); - if (fv->field->kind != Ast_Ident) { - gbString expr_str = expr_to_string(fv->field); - error(elem, "Invalid field name '%s' in 'any' literal", expr_str); - gb_string_free(expr_str); - continue; - } - String name = fv->field->Ident.token.string; - - Selection sel = lookup_field(type, name, o->mode == Addressing_Type); - if (sel.entity == nullptr) { - error(elem, "Unknown field '%.*s' in 'any' literal", LIT(name)); - continue; - } - - isize index = sel.index[0]; - - if (fields_visited[index]) { - error(elem, "Duplicate field '%.*s' in 'any' literal", LIT(name)); - continue; - } - - fields_visited[index] = true; - check_expr(c, o, fv->value); - - // NOTE(bill): 'any' literals can never be constant - is_constant = false; - - check_assignment(c, o, field_types[index], str_lit("'any' literal")); - } - } else { - for_array(index, cl->elems) { - Ast *elem = cl->elems[index]; - if (elem->kind == Ast_FieldValue) { - error(elem, "Mixture of 'field = value' and value elements in a 'any' literal is not allowed"); - continue; - } - - - check_expr(c, o, elem); - if (index >= field_count) { - error(o->expr, "Too many values in 'any' literal, expected %td", field_count); - break; - } - - // NOTE(bill): 'any' literals can never be constant - is_constant = false; - - check_assignment(c, o, field_types[index], str_lit("'any' literal")); - } - if (cl->elems.count < field_count) { - error(cl->close, "Too few values in 'any' literal, expected %td, got %td", field_count, cl->elems.count); - } - } - } - - break; - } - - case Type_Map: { - if (cl->elems.count == 0) { - break; - } - is_constant = false; - { // Checker values - bool key_is_typeid = is_type_typeid(t->Map.key); - bool value_is_typeid = is_type_typeid(t->Map.value); - - for_array(i, cl->elems) { - Ast *elem = cl->elems[i]; - if (elem->kind != Ast_FieldValue) { - error(elem, "Only 'field = value' elements are allowed in a map literal"); - continue; - } - ast_node(fv, FieldValue, elem); - - if (key_is_typeid) { - check_expr_or_type(c, o, fv->field, t->Map.key); - } else { - check_expr_with_type_hint(c, o, fv->field, t->Map.key); - } - check_assignment(c, o, t->Map.key, str_lit("map literal")); - if (o->mode == Addressing_Invalid) { - continue; - } - - if (value_is_typeid) { - check_expr_or_type(c, o, fv->value, t->Map.value); - } else { - check_expr_with_type_hint(c, o, fv->value, t->Map.value); - } - check_assignment(c, o, t->Map.value, str_lit("map literal")); - } - } - - if (build_context.no_dynamic_literals && cl->elems.count) { - error(node, "Compound literals of dynamic types have been disabled"); - } else { - add_package_dependency(c, "runtime", "__dynamic_map_reserve"); - add_package_dependency(c, "runtime", "__dynamic_map_set"); - } - break; - } - - case Type_BitSet: { - if (cl->elems.count == 0) { - break; // NOTE(bill): No need to init - } - Type *et = base_type(t->BitSet.elem); - isize field_count = 0; - if (et->kind == Type_Enum) { - field_count = et->Enum.fields.count; - } - - if (cl->elems[0]->kind == Ast_FieldValue) { - error(cl->elems[0], "'field = value' in a bit_set a literal is not allowed"); - is_constant = false; - } else { - for_array(index, cl->elems) { - Ast *elem = cl->elems[index]; - if (elem->kind == Ast_FieldValue) { - error(elem, "'field = value' in a bit_set a literal is not allowed"); - continue; - } - - check_expr_with_type_hint(c, o, elem, et); - - if (is_constant) { - is_constant = o->mode == Addressing_Constant; - } - - check_assignment(c, o, t->BitSet.elem, str_lit("bit_set literal")); - if (o->mode == Addressing_Constant) { - i64 lower = t->BitSet.lower; - i64 upper = t->BitSet.upper; - i64 v = exact_value_to_i64(o->value); - if (lower <= v && v <= upper) { - // okay - } else { - error(elem, "Bit field value out of bounds, %lld not in the range %lld .. %lld", v, lower, upper); - continue; - } - } - } - } - break; - } - - default: { - if (cl->elems.count == 0) { - break; // NOTE(bill): No need to init - } - - gbString str = type_to_string(type); - error(node, "Invalid compound literal type '%s'", str); - gb_string_free(str); - return kind; - } - } - - if (is_constant) { - o->mode = Addressing_Constant; - - if (is_type_bit_set(type)) { - // NOTE(bill): Encode as an integer - - i64 lower = base_type(type)->BitSet.lower; - - u64 bits = 0; - for_array(index, cl->elems) { - Ast *elem = cl->elems[index]; - GB_ASSERT(elem->kind != Ast_FieldValue); - TypeAndValue tav = elem->tav; - ExactValue i = exact_value_to_integer(tav.value); - if (i.kind != ExactValue_Integer) { - continue; - } - i64 val = big_int_to_i64(&i.value_integer); - val -= lower; - u64 bit = u64(1ll<value = exact_value_u64(bits); - } else if (is_type_constant_type(type) && cl->elems.count == 0) { - ExactValue value = exact_value_compound(node); - Type *bt = core_type(type); - if (bt->kind == Type_Basic) { - if (bt->Basic.flags & BasicFlag_Boolean) { - value = exact_value_bool(false); - } else if (bt->Basic.flags & BasicFlag_Integer) { - value = exact_value_i64(0); - } else if (bt->Basic.flags & BasicFlag_Unsigned) { - value = exact_value_i64(0); - } else if (bt->Basic.flags & BasicFlag_Float) { - value = exact_value_float(0); - } else if (bt->Basic.flags & BasicFlag_Complex) { - value = exact_value_complex(0, 0); - } else if (bt->Basic.flags & BasicFlag_Quaternion) { - value = exact_value_quaternion(0, 0, 0, 0); - } else if (bt->Basic.flags & BasicFlag_Pointer) { - value = exact_value_pointer(0); - } else if (bt->Basic.flags & BasicFlag_String) { - String empty_string = {}; - value = exact_value_string(empty_string); - } else if (bt->Basic.flags & BasicFlag_Rune) { - value = exact_value_i64(0); - } - } - - o->value = value; - } else { - o->value = exact_value_compound(node); - } - } else { - o->mode = Addressing_Value; - } - o->type = type; + kind = check_compound_literal(c, o, node, type_hint); case_end; case_ast_node(pe, ParenExpr, node); @@ -8461,127 +9073,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type case_end; case_ast_node(ta, TypeAssertion, node); - check_expr(c, o, ta->expr); - node->viral_state_flags |= ta->expr->viral_state_flags; - - if (o->mode == Addressing_Invalid) { - o->expr = node; - return kind; - } - if (o->mode == Addressing_Constant) { - gbString expr_str = expr_to_string(o->expr); - error(o->expr, "A type assertion cannot be applied to a constant expression: '%s'", expr_str); - gb_string_free(expr_str); - o->mode = Addressing_Invalid; - o->expr = node; - return kind; - } - - if (is_type_untyped(o->type)) { - gbString expr_str = expr_to_string(o->expr); - error(o->expr, "A type assertion cannot be applied to an untyped expression: '%s'", expr_str); - gb_string_free(expr_str); - o->mode = Addressing_Invalid; - o->expr = node; - return kind; - } - - Type *src = type_deref(o->type); - Type *bsrc = base_type(src); - - - if (ta->type != nullptr && ta->type->kind == Ast_UnaryExpr && ta->type->UnaryExpr.op.kind == Token_Question) { - if (!is_type_union(src)) { - gbString str = type_to_string(o->type); - error(o->expr, "Type assertions with .? can only operate on unions, got %s", str); - gb_string_free(str); - o->mode = Addressing_Invalid; - o->expr = node; - return kind; - } - - if (bsrc->Union.variants.count != 1 && type_hint != nullptr) { - bool allowed = false; - for_array(i, bsrc->Union.variants) { - Type *vt = bsrc->Union.variants[i]; - if (are_types_identical(vt, type_hint)) { - allowed = true; - add_type_info_type(c, vt); - break; - } - } - if (allowed) { - add_type_info_type(c, o->type); - o->type = type_hint; - o->mode = Addressing_OptionalOk; - return kind; - } - } - - if (bsrc->Union.variants.count != 1) { - error(o->expr, "Type assertions with .? can only operate on unions with 1 variant, got %lld", cast(long long)bsrc->Union.variants.count); - o->mode = Addressing_Invalid; - o->expr = node; - return kind; - } - - add_type_info_type(c, o->type); - add_type_info_type(c, bsrc->Union.variants[0]); - - o->type = bsrc->Union.variants[0]; - o->mode = Addressing_OptionalOk; - } else { - Type *t = check_type(c, ta->type); - Type *dst = t; - - if (is_type_union(src)) { - bool ok = false; - for_array(i, bsrc->Union.variants) { - Type *vt = bsrc->Union.variants[i]; - if (are_types_identical(vt, dst)) { - ok = true; - break; - } - } - - if (!ok) { - gbString expr_str = expr_to_string(o->expr); - gbString dst_type_str = type_to_string(t); - defer (gb_string_free(expr_str)); - defer (gb_string_free(dst_type_str)); - if (bsrc->Union.variants.count == 0) { - error(o->expr, "Cannot type assert '%s' to '%s' as this is an empty union", expr_str, dst_type_str); - } else { - error(o->expr, "Cannot type assert '%s' to '%s' as it is not a variant of that union", expr_str, dst_type_str); - } - o->mode = Addressing_Invalid; - o->expr = node; - return kind; - } - - add_type_info_type(c, o->type); - add_type_info_type(c, t); - - o->type = t; - o->mode = Addressing_OptionalOk; - } else if (is_type_any(src)) { - o->type = t; - o->mode = Addressing_OptionalOk; - - add_type_info_type(c, o->type); - add_type_info_type(c, t); - } else { - gbString str = type_to_string(o->type); - error(o->expr, "Type assertions can only operate on unions and 'any', got %s", str); - gb_string_free(str); - o->mode = Addressing_Invalid; - o->expr = node; - return kind; - } - } - - add_package_dependency(c, "runtime", "type_assertion_check"); - add_package_dependency(c, "runtime", "type_assertion_check2"); + kind = check_type_assertion(c, o, node, type_hint); case_end; case_ast_node(tc, TypeCast, node); @@ -8669,443 +9161,19 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type case_end; case_ast_node(se, SelectorCallExpr, node); - // IMPORTANT NOTE(bill, 2020-05-22): This is a complete hack to get a shorthand which is extremely useful for vtables - // COM APIs is a great example of where this kind of thing is extremely useful - // General idea: - // - // x->y(123) == x.y(x, 123) - // - // How this has been implemented at the moment is quite hacky but it's done so to reduce need for huge backend changes - // Just regenerating a new AST aids things - // - // TODO(bill): Is this a good hack or not? - // - // NOTE(bill, 2020-05-22): I'm going to regret this decision, ain't I? - - - if (se->modified_call) { - // Prevent double evaluation - o->expr = node; - o->type = node->tav.type; - o->value = node->tav.value; - o->mode = node->tav.mode; - return Expr_Expr; - } - - bool allow_arrow_right_selector_expr; - allow_arrow_right_selector_expr = c->allow_arrow_right_selector_expr; - c->allow_arrow_right_selector_expr = true; - Operand x = {}; - ExprKind kind = check_expr_base(c, &x, se->expr, nullptr); - c->allow_arrow_right_selector_expr = allow_arrow_right_selector_expr; - - if (x.mode == Addressing_Invalid || x.type == t_invalid) { - o->mode = Addressing_Invalid; - o->type = t_invalid; - o->expr = node; - return kind; - } - if (!is_type_proc(x.type)) { - gbString type_str = type_to_string(x.type); - error(se->call, "Selector call expressions expect a procedure type for the call, got '%s'", type_str); - gb_string_free(type_str); - - o->mode = Addressing_Invalid; - o->type = t_invalid; - o->expr = node; - return Expr_Stmt; - } - - ast_node(ce, CallExpr, se->call); - - GB_ASSERT(x.expr->kind == Ast_SelectorExpr); - - Ast *first_arg = x.expr->SelectorExpr.expr; - GB_ASSERT(first_arg != nullptr); - - Type *pt = base_type(x.type); - GB_ASSERT(pt->kind == Type_Proc); - Type *first_type = nullptr; - String first_arg_name = {}; - if (pt->Proc.param_count > 0) { - Entity *f = pt->Proc.params->Tuple.variables[0]; - first_type = f->type; - first_arg_name = f->token.string; - } - if (first_arg_name.len == 0) { - first_arg_name = str_lit("_"); - } - - if (first_type == nullptr) { - error(se->call, "Selector call expressions expect a procedure type for the call with at least 1 parameter"); - o->mode = Addressing_Invalid; - o->type = t_invalid; - o->expr = node; - return Expr_Stmt; - } - - Operand y = {}; - y.mode = first_arg->tav.mode; - y.type = first_arg->tav.type; - y.value = first_arg->tav.value; - if (check_is_assignable_to(c, &y, first_type)) { - // Do nothing, it's valid - } else { - Operand z = y; - z.type = type_deref(y.type); - if (check_is_assignable_to(c, &z, first_type)) { - // NOTE(bill): AST GENERATION HACK! - Token op = {Token_Pointer}; - first_arg = ast_deref_expr(first_arg->file(), first_arg, op); - } else if (y.mode == Addressing_Variable) { - Operand w = y; - w.type = alloc_type_pointer(y.type); - if (check_is_assignable_to(c, &w, first_type)) { - // NOTE(bill): AST GENERATION HACK! - Token op = {Token_And}; - first_arg = ast_unary_expr(first_arg->file(), op, first_arg); - } - } - } - - if (ce->args.count > 0) { - bool fail = false; - bool first_is_field_value = (ce->args[0]->kind == Ast_FieldValue); - for_array(i, ce->args) { - Ast *arg = ce->args[i]; - bool mix = false; - if (first_is_field_value) { - mix = arg->kind != Ast_FieldValue; - } else { - mix = arg->kind == Ast_FieldValue; - } - if (mix) { - fail = true; - break; - } - } - if (!fail && first_is_field_value) { - Token op = {Token_Eq}; - AstFile *f = first_arg->file(); - first_arg = ast_field_value(f, ast_ident(f, make_token_ident(first_arg_name)), first_arg, op); - } - } - - - - auto modified_args = slice_make(heap_allocator(), ce->args.count+1); - modified_args[0] = first_arg; - slice_copy(&modified_args, ce->args, 1); - ce->args = modified_args; - se->modified_call = true; - - allow_arrow_right_selector_expr = c->allow_arrow_right_selector_expr; - c->allow_arrow_right_selector_expr = true; - check_expr_base(c, o, se->call, type_hint); - c->allow_arrow_right_selector_expr = allow_arrow_right_selector_expr; - - o->expr = node; - return Expr_Expr; + return check_selector_call_expr(c, o, node, type_hint); case_end; - case_ast_node(ise, ImplicitSelectorExpr, node); return check_implicit_selector_expr(c, o, node, type_hint); case_end; case_ast_node(ie, IndexExpr, node); - check_expr(c, o, ie->expr); - node->viral_state_flags |= ie->expr->viral_state_flags; - if (o->mode == Addressing_Invalid) { - o->expr = node; - return kind; - } - - Type *t = base_type(type_deref(o->type)); - bool is_ptr = is_type_pointer(o->type); - bool is_const = o->mode == Addressing_Constant; - - if (is_type_map(t)) { - Operand key = {}; - if (is_type_typeid(t->Map.key)) { - check_expr_or_type(c, &key, ie->index, t->Map.key); - } else { - check_expr_with_type_hint(c, &key, ie->index, t->Map.key); - } - check_assignment(c, &key, t->Map.key, str_lit("map index")); - if (key.mode == Addressing_Invalid) { - o->mode = Addressing_Invalid; - o->expr = node; - return kind; - } - o->mode = Addressing_MapIndex; - o->type = t->Map.value; - o->expr = node; - - add_package_dependency(c, "runtime", "__dynamic_map_get"); - add_package_dependency(c, "runtime", "__dynamic_map_set"); - return Expr_Expr; - } - - i64 max_count = -1; - bool valid = check_set_index_data(o, t, is_ptr, &max_count, o->type); - - if (is_const) { - if (is_type_array(t)) { - // OKay - } else if (is_type_slice(t)) { - // Okay - } else if (is_type_enumerated_array(t)) { - // Okay - } else if (is_type_string(t)) { - // Okay - } else if (is_type_relative_slice(t)) { - // Okay - } else if (is_type_matrix(t)) { - // Okay - } else { - valid = false; - } - } - - if (!valid) { - gbString str = expr_to_string(o->expr); - gbString type_str = type_to_string(o->type); - defer (gb_string_free(str)); - defer (gb_string_free(type_str)); - if (is_const) { - error(o->expr, "Cannot index constant '%s' of type '%s'", str, type_str); - } else { - error(o->expr, "Cannot index '%s' of type '%s'", str, type_str); - } - o->mode = Addressing_Invalid; - o->expr = node; - return kind; - } - - if (ie->index == nullptr) { - gbString str = expr_to_string(o->expr); - error(o->expr, "Missing index for '%s'", str); - gb_string_free(str); - o->mode = Addressing_Invalid; - o->expr = node; - return kind; - } - - Type *index_type_hint = nullptr; - if (is_type_enumerated_array(t)) { - Type *bt = base_type(t); - GB_ASSERT(bt->kind == Type_EnumeratedArray); - index_type_hint = bt->EnumeratedArray.index; - } - - i64 index = 0; - bool ok = check_index_value(c, t, false, ie->index, max_count, &index, index_type_hint); - if (is_const) { - if (index < 0) { - gbString str = expr_to_string(o->expr); - error(o->expr, "Cannot index a constant '%s'", str); - error_line("\tSuggestion: store the constant into a variable in order to index it with a variable index\n"); - gb_string_free(str); - o->mode = Addressing_Invalid; - o->expr = node; - return kind; - } else if (ok) { - ExactValue value = type_and_value_of_expr(ie->expr).value; - o->mode = Addressing_Constant; - bool success = false; - bool finish = false; - o->value = get_constant_field_single(c, value, cast(i32)index, &success, &finish); - if (!success) { - gbString str = expr_to_string(o->expr); - error(o->expr, "Cannot index a constant '%s' with index %lld", str, cast(long long)index); - error_line("\tSuggestion: store the constant into a variable in order to index it with a variable index\n"); - gb_string_free(str); - o->mode = Addressing_Invalid; - o->expr = node; - return kind; - } - } - } - - if (type_hint != nullptr && is_type_matrix(t)) { - // TODO(bill): allow matrix columns to be assignable to other types which are the same internally - // if a type hint exists - } - + kind = check_index_expr(c, o, node, type_hint); case_end; case_ast_node(se, SliceExpr, node); - check_expr(c, o, se->expr); - node->viral_state_flags |= se->expr->viral_state_flags; - - if (o->mode == Addressing_Invalid) { - o->mode = Addressing_Invalid; - o->expr = node; - return kind; - } - - bool valid = false; - i64 max_count = -1; - Type *t = base_type(type_deref(o->type)); - switch (t->kind) { - case Type_Basic: - if (t->Basic.kind == Basic_string || t->Basic.kind == Basic_UntypedString) { - valid = true; - if (o->mode == Addressing_Constant) { - max_count = o->value.value_string.len; - } - o->type = type_deref(o->type); - } - break; - - case Type_Array: - valid = true; - max_count = t->Array.count; - if (o->mode != Addressing_Variable && !is_type_pointer(o->type)) { - gbString str = expr_to_string(node); - error(node, "Cannot slice array '%s', value is not addressable", str); - gb_string_free(str); - o->mode = Addressing_Invalid; - o->expr = node; - return kind; - } - o->type = alloc_type_slice(t->Array.elem); - break; - - case Type_MultiPointer: - valid = true; - o->type = type_deref(o->type); - break; - - case Type_Slice: - valid = true; - o->type = type_deref(o->type); - break; - - case Type_DynamicArray: - valid = true; - o->type = alloc_type_slice(t->DynamicArray.elem); - break; - - case Type_Struct: - if (is_type_soa_struct(t)) { - valid = true; - o->type = make_soa_struct_slice(c, nullptr, nullptr, t->Struct.soa_elem); - } - break; - - case Type_RelativeSlice: - valid = true; - o->type = t->RelativeSlice.slice_type; - if (o->mode != Addressing_Variable) { - gbString str = expr_to_string(node); - error(node, "Cannot relative slice '%s', value is not addressable", str); - gb_string_free(str); - o->mode = Addressing_Invalid; - o->expr = node; - return kind; - } - break; - } - - if (!valid) { - gbString str = expr_to_string(o->expr); - gbString type_str = type_to_string(o->type); - error(o->expr, "Cannot slice '%s' of type '%s'", str, type_str); - gb_string_free(type_str); - gb_string_free(str); - o->mode = Addressing_Invalid; - o->expr = node; - return kind; - } - - if (se->low == nullptr && se->high != nullptr) { - // It is okay to continue as it will assume the 1st index is zero - } - - i64 indices[2] = {}; - Ast *nodes[2] = {se->low, se->high}; - for (isize i = 0; i < gb_count_of(nodes); i++) { - i64 index = max_count; - if (nodes[i] != nullptr) { - i64 capacity = -1; - if (max_count >= 0) { - capacity = max_count; - } - i64 j = 0; - if (check_index_value(c, t, true, nodes[i], capacity, &j)) { - index = j; - } - - node->viral_state_flags |= nodes[i]->viral_state_flags; - } else if (i == 0) { - index = 0; - } - indices[i] = index; - } - - for (isize i = 0; i < gb_count_of(indices); i++) { - i64 a = indices[i]; - for (isize j = i+1; j < gb_count_of(indices); j++) { - i64 b = indices[j]; - if (a > b && b >= 0) { - error(se->close, "Invalid slice indices: [%td > %td]", a, b); - } - } - } - - if (max_count < 0) { - if (o->mode == Addressing_Constant) { - gbString s = expr_to_string(se->expr); - error(se->expr, "Cannot slice constant value '%s'", s); - gb_string_free(s); - } - } - - if (t->kind == Type_MultiPointer && se->high != nullptr) { - /* - x[:] -> [^]T - x[i:] -> [^]T - x[:n] -> []T - x[i:n] -> []T - */ - o->type = alloc_type_slice(t->MultiPointer.elem); - } - - o->mode = Addressing_Value; - - if (is_type_string(t) && max_count >= 0) { - bool all_constant = true; - for (isize i = 0; i < gb_count_of(nodes); i++) { - if (nodes[i] != nullptr) { - TypeAndValue tav = type_and_value_of_expr(nodes[i]); - if (tav.mode != Addressing_Constant) { - all_constant = false; - break; - } - } - } - if (!all_constant) { - gbString str = expr_to_string(o->expr); - error(o->expr, "Cannot slice '%s' with non-constant indices", str); - error_line("\tSuggestion: store the constant into a variable in order to index it with a variable index\n"); - gb_string_free(str); - o->mode = Addressing_Value; // NOTE(bill): Keep subsequent values going without erring - o->expr = node; - return kind; - } - - String s = {}; - if (o->value.kind == ExactValue_String) { - s = o->value.value_string; - } - - o->mode = Addressing_Constant; - o->type = t; - o->value = exact_value_string(substring(s, cast(isize)indices[0], cast(isize)indices[1])); - } - + kind = check_slice_expr(c, o, node, type_hint); case_end; case_ast_node(mie, MatrixIndexExpr, node); @@ -9230,6 +9298,8 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type return kind; } + + ExprKind check_expr_base(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) { ExprKind kind = check_expr_base_internal(c, o, node, type_hint); if (o->type != nullptr && core_type(o->type) == nullptr) { From 445ca705210999e106b6aeb265cfb2979cbd857c Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 5 Feb 2022 16:11:48 +0000 Subject: [PATCH 092/117] Correct implicit union cast --- src/check_expr.cpp | 11 +++++++++++ src/llvm_backend_expr.cpp | 9 +++++++++ 2 files changed, 20 insertions(+) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index fb58839bc..3f31ac810 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -508,6 +508,10 @@ bool check_cast_internal(CheckerContext *c, Operand *x, Type *type); #define MAXIMUM_TYPE_DISTANCE 10 i64 check_distance_between_types(CheckerContext *c, Operand *operand, Type *type) { + if (c == nullptr) { + GB_ASSERT(operand->mode == Addressing_Value); + GB_ASSERT(is_type_typed(operand->type)); + } if (operand->mode == Addressing_Invalid || type == t_invalid) { return -1; @@ -818,6 +822,13 @@ bool check_is_assignable_to(CheckerContext *c, Operand *operand, Type *type) { return check_is_assignable_to_with_score(c, operand, type, &score); } +bool internal_check_is_assignable_to(Type *src, Type *dst) { + Operand x = {}; + x.type = src; + x.mode = Addressing_Value; + return check_is_assignable_to(nullptr, &x, dst); +} + AstPackage *get_package_of_type(Type *type) { for (;;) { if (type == nullptr) { diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index ea031ee56..715b7df78 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -1834,6 +1834,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 From bccbdefde952f605bde620c8d9d0c7f9a5dfc3e0 Mon Sep 17 00:00:00 2001 From: Andrea Piseri Date: Sat, 5 Feb 2022 18:00:59 +0100 Subject: [PATCH 093/117] Update interface to allow more modes of iteration It's now possible to iterate over: - all keys in the range min_value ..= max_value, with `iterate_all` - all set keys in the bit array, with `iterate_set` - all unset keys in the range min_value ..= max_value, with `iterate_unset` `Bit_Array` now stores the `max_value` provided during construction, and updates it when a key that was previously out of range is set. --- core/container/bit_array/bit_array.odin | 113 +++++++++++++++++++----- 1 file changed, 91 insertions(+), 22 deletions(-) diff --git a/core/container/bit_array/bit_array.odin b/core/container/bit_array/bit_array.odin index bf2ae3a40..0a92e3dc4 100644 --- a/core/container/bit_array/bit_array.odin +++ b/core/container/bit_array/bit_array.odin @@ -17,12 +17,24 @@ NUM_BITS :: 64 Bit_Array :: struct { bits: [dynamic]u64, bias: int, + max_index: int, } Bit_Array_Iterator :: struct { array: ^Bit_Array, - current_word: uint, - current_bit: uint, + 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 } } /* @@ -30,30 +42,85 @@ Bit_Array_Iterator :: struct { - 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 + - 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 */ -next :: proc (it: ^Bit_Array_Iterator) -> (index: int, ok: bool) { - words := it.array.bits - // if the word is empty or we have already gone over all the bits in it, - // b.current_bit is greater than the index of any set bit in the word, - // meaning that word >> b.current_bit == 0. - for it.current_word < len(words) && (words[it.current_word] >> it.current_bit == 0) { - it.current_word += 1 - it.current_bit = 0 +iterate_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 } - if it.current_word >= len(words) { return 0, false } + return set, index, true +} - // since we exited the loop and didn't return, this word has some bits higher than - // or equal to `it.current_bit` set. - offset := intrinsics.count_trailing_zeros(words[it.current_word] >> it.current_bit) - // skip over the bit, if the resulting it.current_bit is over 63, - // it is handled by the initial for loop in the next iteration. - it.current_bit += uint(offset) - defer it.current_bit += 1 - return int(it.current_word * NUM_BITS + it.current_bit) + it.array.bias, 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_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_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 } @@ -111,6 +178,7 @@ set :: proc(ba: ^Bit_Array, #any_int index: uint, allocator := context.allocator resize_if_needed(ba, leg_index) or_return + if idx > ba.max_index { ba.max_index = idx } ba.bits[leg_index] |= 1 << uint(bit_index) return true } @@ -128,6 +196,7 @@ 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, legs) } From b6ebfe4b2c1445f59ed35c20bf8d4ba8910b59de Mon Sep 17 00:00:00 2001 From: Andrea Piseri Date: Sat, 5 Feb 2022 18:11:48 +0100 Subject: [PATCH 094/117] rename iterator procedures --- core/container/bit_array/bit_array.odin | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/container/bit_array/bit_array.odin b/core/container/bit_array/bit_array.odin index 0a92e3dc4..5fbac69af 100644 --- a/core/container/bit_array/bit_array.odin +++ b/core/container/bit_array/bit_array.odin @@ -47,7 +47,7 @@ make_iterator :: proc (ba: ^Bit_Array) -> (it: Bit_Array_Iterator) { - ok: bool - `true` if the iterator returned a valid index, `false` if there were no more bits */ -iterate_all :: proc (it: ^Bit_Array_Iterator) -> (set: bool, index: int, ok: bool) { +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 } @@ -72,7 +72,7 @@ iterate_all :: proc (it: ^Bit_Array_Iterator) -> (set: bool, index: int, ok: boo - ok: bool - `true` if the iterator returned a valid index, `false` if there were no more bits set */ -iterate_set :: proc (it: ^Bit_Array_Iterator) -> (index: int, ok: bool) { +iterate_by_set :: proc (it: ^Bit_Array_Iterator) -> (index: int, ok: bool) { return iterate_internal_(it, true) } @@ -85,7 +85,7 @@ iterate_set :: proc (it: ^Bit_Array_Iterator) -> (index: int, ok: bool) { - ok: bool - `true` if the iterator returned a valid index, `false` if there were no more unset bits */ -iterate_unset:: proc (it: ^Bit_Array_Iterator) -> (index: int, ok: bool) { +iterate_by_unset:: proc (it: ^Bit_Array_Iterator) -> (index: int, ok: bool) { return iterate_internal_(it, false) } From 697f8c7ee6ef3d0af4d8e44163e770ef1f2227c5 Mon Sep 17 00:00:00 2001 From: ap29600 <66381278+ap29600@users.noreply.github.com> Date: Sat, 5 Feb 2022 18:46:25 +0100 Subject: [PATCH 095/117] replace a branch with `max` in `core:container/bit_array.set` --- core/container/bit_array/bit_array.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/container/bit_array/bit_array.odin b/core/container/bit_array/bit_array.odin index 5fbac69af..5eebe1bcb 100644 --- a/core/container/bit_array/bit_array.odin +++ b/core/container/bit_array/bit_array.odin @@ -178,7 +178,7 @@ set :: proc(ba: ^Bit_Array, #any_int index: uint, allocator := context.allocator resize_if_needed(ba, leg_index) or_return - if idx > ba.max_index { ba.max_index = idx } + ba.max_index = max(idx, ba.max_index) ba.bits[leg_index] |= 1 << uint(bit_index) return true } From a571153458211ba34973811eae9057140634b509 Mon Sep 17 00:00:00 2001 From: Platin21 Date: Sat, 5 Feb 2022 20:45:32 +0100 Subject: [PATCH 096/117] Adds missing calls for os --- core/os/os_darwin.odin | 62 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/core/os/os_darwin.odin b/core/os/os_darwin.odin index adb490e4f..948f68410 100644 --- a/core/os/os_darwin.odin +++ b/core/os/os_darwin.odin @@ -296,6 +296,9 @@ foreign libc { @(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="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 --- @@ -412,6 +415,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) != -1 +} @private _stat :: proc(path: string) -> (OS_Stat, Errno) { From de7e6121866e9fcbe5c9f7fda2a594fa243942b5 Mon Sep 17 00:00:00 2001 From: Platin21 Date: Sat, 5 Feb 2022 20:45:55 +0100 Subject: [PATCH 097/117] Ignores DS_Store files which MacOS uses for Indexing or some crap --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 0d606498e..abbdccecd 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,9 @@ # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs +# For macOS +.DS_Store + # Build results [Dd]ebug/ [Dd]ebugPublic/ From 3edf638cc6c40e0c05e041359372200150ebc0f8 Mon Sep 17 00:00:00 2001 From: Platin21 Date: Sat, 5 Feb 2022 20:54:27 +0100 Subject: [PATCH 098/117] Fixed Typo --- core/os/os_darwin.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/os/os_darwin.odin b/core/os/os_darwin.odin index 948f68410..48fcbc724 100644 --- a/core/os/os_darwin.odin +++ b/core/os/os_darwin.odin @@ -472,7 +472,7 @@ rename :: proc(old: string, new: string) -> bool { remove :: proc(path: string) -> bool { path_cstr := strings.clone_to_cstring(path, context.temp_allocator) - return _unix_remove(path) != -1 + return _unix_remove(path_cstr) != -1 } @private From a724573bb3338e3f096134cbf35325b2dedffb18 Mon Sep 17 00:00:00 2001 From: Platin21 Date: Sat, 5 Feb 2022 21:16:58 +0100 Subject: [PATCH 099/117] Fixes fopendir and readdir_r for arm64 or seemingly doing so --- core/os/os_darwin.odin | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/core/os/os_darwin.odin b/core/os/os_darwin.odin index 48fcbc724..e64542f84 100644 --- a/core/os/os_darwin.odin +++ b/core/os/os_darwin.odin @@ -290,10 +290,15 @@ 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="rename") _unix_rename :: proc(old: cstring, new: cstring) -> c.int --- @@ -315,6 +320,14 @@ foreign libc { @(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 --- From a3d99765cc1012c2bb3e4f7e953c8126a9c158d2 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Sat, 5 Feb 2022 22:18:22 +0100 Subject: [PATCH 100/117] mem: Add `doc.odin` with `Tracking_Allocator` example. --- core/mem/doc.odin | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 core/mem/doc.odin diff --git a/core/mem/doc.odin b/core/mem/doc.odin new file mode 100644 index 000000000..2a5ee06d3 --- /dev/null +++ b/core/mem/doc.odin @@ -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 \ No newline at end of file From 8b1100bf2b2488c181f7f8112cf079c475f5f59c Mon Sep 17 00:00:00 2001 From: Platin21 Date: Sat, 5 Feb 2022 23:12:55 +0100 Subject: [PATCH 101/117] os.open does r/d as default which makes a call to open a dir invalid this should fix this problem --- core/path/filepath/walk.odin | 2 +- tools/odinfmt/main.odin | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/core/path/filepath/walk.odin b/core/path/filepath/walk.odin index 29d4fd5b1..dad63cc09 100644 --- a/core/path/filepath/walk.odin +++ b/core/path/filepath/walk.odin @@ -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 } diff --git a/tools/odinfmt/main.odin b/tools/odinfmt/main.odin index bc1b521ca..cebb20888 100644 --- a/tools/odinfmt/main.odin +++ b/tools/odinfmt/main.odin @@ -114,7 +114,6 @@ main :: proc() { filepath.walk(path, walk_files); for file in files { - fmt.println(file); backup_path := strings.concatenate({file, "_bk"}); defer delete(backup_path); From 19aec13a1060a521913abc6bd669080171d43594 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 6 Feb 2022 11:42:59 +0000 Subject: [PATCH 102/117] Support rank-2 arrays (matrix-like) for `transpose` --- src/check_builtin.cpp | 38 ++++++++++++++++++++++++++++++++++++-- src/llvm_backend_expr.cpp | 21 +++++++++++++++++++++ src/types.cpp | 19 +++++++++++++++++++ 3 files changed, 76 insertions(+), 2 deletions(-) diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index a42741976..d3a3103b1 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -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); diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 715b7df78..29a86d116 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -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; diff --git a/src/types.cpp b/src/types.cpp index e0d35a12c..9ee6ba359 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -363,6 +363,7 @@ enum TypeInfoFlag : u32 { enum : int { MATRIX_ELEMENT_COUNT_MIN = 1, MATRIX_ELEMENT_COUNT_MAX = 16, + MATRIX_ELEMENT_MAX_SIZE = MATRIX_ELEMENT_COUNT_MAX * (2 * 8), // complex128 }; @@ -1583,6 +1584,24 @@ Type *core_array_type(Type *t) { } } +i32 type_math_rank(Type *t) { + i32 rank = 0; + for (;;) { + t = base_type(t); + switch (t->kind) { + case Type_Array: + rank += 1; + t = t->Array.elem; + break; + case Type_Matrix: + rank += 2; + t = t->Matrix.elem; + break; + default: + return rank; + } + } +} Type *base_complex_elem_type(Type *t) { From 0c16f27814a344f0694b8d4ae580f82393a0d540 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 6 Feb 2022 11:50:27 +0000 Subject: [PATCH 103/117] Update parser for `#sparse` --- core/odin/parser/parser.odin | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/core/odin/parser/parser.odin b/core/odin/parser/parser.odin index 0ebabfd70..cc802e7d2 100644 --- a/core/odin/parser/parser.odin +++ b/core/odin/parser/parser.odin @@ -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 From cda9fd527199a6046b1a442ed634ac282df4d799 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 6 Feb 2022 11:59:12 +0000 Subject: [PATCH 104/117] Add `tag` to `ast.Comp_Lit` --- core/odin/ast/ast.odin | 1 + 1 file changed, 1 insertion(+) diff --git a/core/odin/ast/ast.odin b/core/odin/ast/ast.odin index 9db57541b..8eb0def44 100644 --- a/core/odin/ast/ast.odin +++ b/core/odin/ast/ast.odin @@ -151,6 +151,7 @@ Comp_Lit :: struct { open: tokenizer.Pos, elems: []^Expr, close: tokenizer.Pos, + tag: ^Expr, } From 9cbf46e6898a6d60e8e8580aad93773c193ba22f Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 7 Feb 2022 11:00:38 +0000 Subject: [PATCH 105/117] Fix constant multi pointer declarations through integers --- src/llvm_backend_const.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/llvm_backend_const.cpp b/src/llvm_backend_const.cpp index 5862a7add..8f17a1cfb 100644 --- a/src/llvm_backend_const.cpp +++ b/src/llvm_backend_const.cpp @@ -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); From 3c2ed3bb69df24ba162e5f2ea8f61ee3f7fd8e2f Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 7 Feb 2022 11:37:13 +0000 Subject: [PATCH 106/117] Correct `//+private file` bug --- src/checker.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/checker.cpp b/src/checker.cpp index b62ef7c4c..7fb4fdb29 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -3477,11 +3477,11 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) { if (entity_visibility_kind == EntityVisiblity_Public && (c->scope->flags&ScopeFlag_File) && c->scope->file) { - if (c->scope->file->flags & AstFile_IsPrivatePkg) { - entity_visibility_kind = EntityVisiblity_PrivateToPackage; - } else if (c->scope->file->flags & AstFile_IsPrivateFile) { + 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)) { From 817bc7434dfd0ebfeb1310c22741b9d66af67ac2 Mon Sep 17 00:00:00 2001 From: NoahR02 Date: Tue, 8 Feb 2022 06:16:10 -0500 Subject: [PATCH 107/117] Ports OpenSimplex2 from https://github.com/KdotJPG/OpenSimplex2 to Odin. Adds tests for the noise procedures. --- core/math/noise/internal.odin | 734 ++++++++++++++++++ core/math/noise/opensimplex2.odin | 171 ++++ tests/core/Makefile | 7 +- tests/core/build.bat | 7 +- .../core/math/noise/test_core_math_noise.odin | 153 ++++ 5 files changed, 1069 insertions(+), 3 deletions(-) create mode 100644 core/math/noise/internal.odin create mode 100644 core/math/noise/opensimplex2.odin create mode 100644 tests/core/math/noise/test_core_math_noise.odin diff --git a/core/math/noise/internal.odin b/core/math/noise/internal.odin new file mode 100644 index 000000000..5837f9235 --- /dev/null +++ b/core/math/noise/internal.odin @@ -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) +} \ No newline at end of file diff --git a/core/math/noise/opensimplex2.odin b/core/math/noise/opensimplex2.odin new file mode 100644 index 000000000..d90dafdf5 --- /dev/null +++ b/core/math/noise/opensimplex2.odin @@ -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) +} \ No newline at end of file diff --git a/tests/core/Makefile b/tests/core/Makefile index 0f0ffe4d6..1c2cee6bd 100644 --- a/tests/core/Makefile +++ b/tests/core/Makefile @@ -1,7 +1,7 @@ ODIN=../../odin PYTHON=$(shell which python3) -all: download_test_assets image_test compress_test strings_test hash_test crypto_test +all: download_test_assets image_test compress_test strings_test hash_test crypto_test noise_test download_test_assets: $(PYTHON) download_assets.py @@ -19,4 +19,7 @@ hash_test: $(ODIN) run hash -out=test_hash -o:speed -no-bounds-check crypto_test: - $(ODIN) run crypto -out=crypto_hash -o:speed -no-bounds-check \ No newline at end of file + $(ODIN) run crypto -out=crypto_hash -o:speed -no-bounds-check + +noise_test: + $(ODIN) run math/noise -out=test_noise \ No newline at end of file diff --git a/tests/core/build.bat b/tests/core/build.bat index 176b7f175..6af39e688 100644 --- a/tests/core/build.bat +++ b/tests/core/build.bat @@ -35,4 +35,9 @@ echo --- echo --- echo Running core:encoding tests echo --- -%PATH_TO_ODIN% run encoding %COMMON% \ No newline at end of file +%PATH_TO_ODIN% run encoding %COMMON% + +echo --- +echo Running core:math/noise tests +echo --- +%PATH_TO_ODIN% run math/noise %COMMON% \ No newline at end of file diff --git a/tests/core/math/noise/test_core_math_noise.odin b/tests/core/math/noise/test_core_math_noise.odin new file mode 100644 index 000000000..a3ac1b955 --- /dev/null +++ b/tests/core/math/noise/test_core_math_noise.odin @@ -0,0 +1,153 @@ +package test_core_math_noise + +import "core:testing" +import "core:math/noise" +import "core:fmt" + +TEST_count := 0 +TEST_fail := 0 + +V2 :: noise.Vec2 +V3 :: noise.Vec3 +V4 :: noise.Vec4 + +when ODIN_TEST { + expect :: testing.expect + log :: testing.log +} else { + expect :: proc(t: ^testing.T, condition: bool, message: string, loc := #caller_location) { + fmt.printf("[%v] ", loc) + TEST_count += 1 + if !condition { + TEST_fail += 1 + fmt.println(message) + return + } + fmt.println(" PASS") + } + log :: proc(t: ^testing.T, v: any, loc := #caller_location) { + fmt.printf("[%v] ", loc) + fmt.printf("log: %v\n", v) + } +} + +main :: proc() { + t := testing.T{} + noise_test(&t) + fmt.printf("%v/%v tests successful.\n", TEST_count - TEST_fail, TEST_count) +} + +Test_Vector :: struct { + seed: i64, + coord: union {V2, V3, V4}, + expected: f32, + + test_proc: union { + proc(_: i64, _: V2) -> f32, + proc(_: i64, _: V3) -> f32, + proc(_: i64, _: V4) -> f32, + }, +} + +SEED_1 :: 2324223232 +SEED_2 :: 932466901 +SEED_3 :: 9321 + +COORD_1 :: V4{ 242.0, 3433.0, 920.0, 222312.0} +COORD_2 :: V4{ 590.0, 9411.0, 5201.0, 942124256.0} +COORD_3 :: V4{12090.0, 19411.0, 81950901.0, 4224219.0} + +Noise_Tests := []Test_Vector{ + /* + `noise_2d` tests. + */ + {SEED_1, COORD_1.xy, 0.25010583, noise.noise_2d}, + {SEED_2, COORD_2.xy, -0.92513955, noise.noise_2d}, + {SEED_3, COORD_3.xy, 0.67327416, noise.noise_2d}, + + /* + `noise_2d_improve_x` tests. + */ + {SEED_1, COORD_1.xy, 0.17074019, noise.noise_2d_improve_x}, + {SEED_2, COORD_2.xy, 0.72330487, noise.noise_2d_improve_x}, + {SEED_3, COORD_3.xy, -0.032076947, noise.noise_2d_improve_x}, + + /* + `noise_3d_improve_xy` tests. + */ + {SEED_1, COORD_1.xyz, 0.14819577, noise.noise_3d_improve_xy}, + {SEED_2, COORD_2.xyz, -0.065345764, noise.noise_3d_improve_xy}, + {SEED_3, COORD_3.xyz, -0.37761918, noise.noise_3d_improve_xy}, + + /* + `noise_3d_improve_xz` tests. + */ + {SEED_1, COORD_1.xyz, -0.50075006, noise.noise_3d_improve_xz}, + {SEED_2, COORD_2.xyz, -0.36039603, noise.noise_3d_improve_xz}, + {SEED_3, COORD_3.xyz, -0.3479203, noise.noise_3d_improve_xz}, + + /* + `noise_3d_fallback` tests. + */ + {SEED_1, COORD_1.xyz, 0.6557345, noise.noise_3d_fallback}, + {SEED_2, COORD_2.xyz, 0.55452216, noise.noise_3d_fallback}, + {SEED_3, COORD_3.xyz, -0.26408964, noise.noise_3d_fallback}, + + /* + `noise_3d_fallback` tests. + */ + {SEED_1, COORD_1.xyz, 0.6557345, noise.noise_3d_fallback}, + {SEED_2, COORD_2.xyz, 0.55452216, noise.noise_3d_fallback}, + {SEED_3, COORD_3.xyz, -0.26408964, noise.noise_3d_fallback}, + + /* + `noise_4d_improve_xyz_improve_xy` tests. + */ + {SEED_1, COORD_1, 0.44929826, noise.noise_4d_improve_xyz_improve_xy}, + {SEED_2, COORD_2, -0.13270882, noise.noise_4d_improve_xyz_improve_xy}, + {SEED_3, COORD_3, 0.10298563, noise.noise_4d_improve_xyz_improve_xy}, + + /* + `noise_4d_improve_xyz_improve_xz` tests. + */ + {SEED_1, COORD_1, -0.078514606, noise.noise_4d_improve_xyz_improve_xz}, + {SEED_2, COORD_2, -0.032157656, noise.noise_4d_improve_xyz_improve_xz}, + {SEED_3, COORD_3, -0.38607058, noise.noise_4d_improve_xyz_improve_xz}, + + /* + `noise_4d_improve_xyz` tests. + */ + {SEED_1, COORD_1, -0.4442258, noise.noise_4d_improve_xyz}, + {SEED_2, COORD_2, 0.36822623, noise.noise_4d_improve_xyz}, + {SEED_3, COORD_3, 0.22628775, noise.noise_4d_improve_xyz}, + + /* + `noise_4d_fallback` tests. + */ + {SEED_1, COORD_1, -0.14233987, noise.noise_4d_fallback}, + {SEED_2, COORD_2, 0.1354035, noise.noise_4d_fallback}, + {SEED_3, COORD_3, 0.14565045, noise.noise_4d_fallback}, + + // TODO: Output according to C# - Figure out which of these two is right (and why). + // {SEED_1, COORD_1, -0.14233987, noise.noise_4d_fallback}, + // {SEED_2, COORD_2, 0.1354035, noise.noise_4d_fallback}, + // {SEED_3, COORD_3, 0.14565045, noise.noise_4d_fallback}, +} + +noise_test :: proc(t: ^testing.T) { + for test in Noise_Tests { + output: f32 + + switch coord in test.coord { + case V2: + output = test.test_proc.(proc(_: i64, _: V2) -> f32)(test.seed, test.coord.(V2)) + case V3: + output = test.test_proc.(proc(_: i64, _: V3) -> f32)(test.seed, test.coord.(V3)) + case V4: + output = test.test_proc.(proc(_: i64, _: V4) -> f32)(test.seed, test.coord.(V4)) + } + + error := fmt.tprintf("Seed %v, Coord: %v, Expected: %3.8f. Got %3.8f", test.seed, test.coord, test.expected, output) + expect(t, test.expected == output, error) + } +} \ No newline at end of file From accb35506f5c0b66fa25fb7ccec7e97a9da61d8e Mon Sep 17 00:00:00 2001 From: NoahR02 Date: Tue, 8 Feb 2022 06:25:07 -0500 Subject: [PATCH 108/117] Ports OpenSimplex2 from https://github.com/KdotJPG/OpenSimplex2 to Odin. Adds tests for the noise procedures. --- tests/core/math/noise/test_core_math_noise.odin | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/core/math/noise/test_core_math_noise.odin b/tests/core/math/noise/test_core_math_noise.odin index a3ac1b955..c3a3e4228 100644 --- a/tests/core/math/noise/test_core_math_noise.odin +++ b/tests/core/math/noise/test_core_math_noise.odin @@ -128,10 +128,6 @@ Noise_Tests := []Test_Vector{ {SEED_2, COORD_2, 0.1354035, noise.noise_4d_fallback}, {SEED_3, COORD_3, 0.14565045, noise.noise_4d_fallback}, - // TODO: Output according to C# - Figure out which of these two is right (and why). - // {SEED_1, COORD_1, -0.14233987, noise.noise_4d_fallback}, - // {SEED_2, COORD_2, 0.1354035, noise.noise_4d_fallback}, - // {SEED_3, COORD_3, 0.14565045, noise.noise_4d_fallback}, } noise_test :: proc(t: ^testing.T) { From 30bb2382aa0c7a9d6407c0b28258cd9fd00c560d Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 8 Feb 2022 11:48:59 +0000 Subject: [PATCH 109/117] Correct simple boolean intrinsics --- src/check_builtin.cpp | 5 +++-- src/checker_builtin_procs.hpp | 4 ---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index d3a3103b1..1fb3d6037 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -3344,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: @@ -3354,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: diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index e8f5174c0..d833a055f 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -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}, From 83e9a6b417c449e0ffa413f4841ce0d19b1c7732 Mon Sep 17 00:00:00 2001 From: CiD- Date: Tue, 8 Feb 2022 09:21:43 -0500 Subject: [PATCH 110/117] fix -vet for filepath/match.odin --- core/path/filepath/match.odin | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/path/filepath/match.odin b/core/path/filepath/match.odin index cba44953d..bde7f5393 100644 --- a/core/path/filepath/match.odin +++ b/core/path/filepath/match.odin @@ -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) From 251edf7bc7eff05b1dcead77133fe1a3ec2e973c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikkel=20Hjortsh=C3=B8j?= Date: Fri, 11 Feb 2022 17:22:14 +0100 Subject: [PATCH 111/117] Update ci.yml --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a1f96d20b..c62fcd36b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -79,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 From 1c57d1c01921284e82329933df558bf9edd317bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikkel=20Hjortsh=C3=B8j?= Date: Fri, 11 Feb 2022 17:22:33 +0100 Subject: [PATCH 112/117] Update nightly.yml --- .github/workflows/nightly.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 2b33c45a8..7175843f5 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -7,7 +7,7 @@ on: jobs: build_windows: - runs-on: windows-latest + runs-on: windows-2019 steps: - uses: actions/checkout@v1 - name: build Odin From e59064dd59d69fe94b5c6ba8c24ed92bc2143e4e Mon Sep 17 00:00:00 2001 From: FancyKillerPanda Date: Sun, 13 Feb 2022 10:33:48 +1100 Subject: [PATCH 113/117] Updated vendor/sdl2/ttf LIB and DLL. --- vendor/sdl2/ttf/SDL2_ttf.dll | Bin 33792 -> 1534464 bytes vendor/sdl2/ttf/SDL2_ttf.lib | Bin 12122 -> 18406 bytes vendor/sdl2/ttf/sdl_ttf.odin | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/sdl2/ttf/SDL2_ttf.dll b/vendor/sdl2/ttf/SDL2_ttf.dll index 575636a915df04b5a82b36a5635e59624380c9de..2acc0e5bc8b9ca9933e585af49f64923297e41c2 100644 GIT binary patch literal 1534464 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⪚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%0D{zjT1=Zl4P}yFs46T_3cGbVm0S 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%0DiJ`O(q(-Rm#gM|=Ux_j55|KYy@4#? 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®Fe_=1!;eKxqj7 z_Hgh%rXD7^n1c)d_IwV{?l_AyP^-Vnm+`4j=QGeQKJYo6%%CwT&`e2(+kYR+cO|L( z`?&vKZ9P!>1Z4IVW>9{4%aAtWW3Jw2QBr z4>9s@zw}~@Ff3G#gF*##{%AKSR35&t`v3bss4>}kpfnW{Di2?jF~UP7(1m|{Ifo}` zKUtdN#dnb1xUT%$zxj0j^JV<^S_M+C^Y8O!1cgS4BxJtj7$ayl031}`O0pWP8A|Sg zYR9!qpkM;cqq-XYf3ZIj5lk;Z;R6k-7t11%gXssTbr2mFkJOikpHB*!e!1)0`416Z zY~TYLT$uj+e|;ov0%ZLnH1!ntbT0&*)!@;24s_6qFeC;F5Jn%K;L*HO0JNs9MEtuW z3j@Rddj3|>xk29?IUD#}LFf2`7Aquxl3v6v(8f7X7n!3Qbn|n`Mvr6{l?c#{7G5A$ z0_Z9X9iLtn2aoPHP?OlBdm3oXgHJDSdl#rB0^Z}`*UNI?h4|n9|2;d8_;fAX3T?1BvJ>3GjPyL%4$kU+xU>ydoh{%wpc2TJro z^#}jH3(c<#K)2WOb{=YebietPW5X}Wa(2fK2G9|y{M#JC*PXT;D7^|k!40(j26TK( zZv>-f=bsn6;eYk&x!{fOhe1Yx2KT;$n9i;rmNAr+puZ)Om>&cRWW6XNay)2y|$MpIzu=@0Rvw?0r zec;)Agz?}n0msg(&4&ycAA;ug9XmomH_M&lZ+Xwcz|hOn$#~M&@=WOk&(4FMnm0Y0 zf3otofbQ9A_+`M~It_e5paX+P=V6fb4HgE+92gl&K6JZ_fUbI$X!xa2qR7ARRP##% zP#2uH^J4SE`^_&M8-7Zbb9M-KyNiH|aF9{~;+1j`sq~$s|2(wz5a_A%TMj_%jc5PUl-~c;es* zUKhp#y*&-mXJx`NoxXrX4;~Q6Jn+GT66e((f; z=7GuGj~BWa-Z*%GpYexF@0xE32WTMhB50(i^QC9!n-@JR*cm)}V^|qqCWD5RFFEpWbL26+ z0P!ipOUE7gw*_(^d?W#q=Q{X6!0-Y{g!AAd4#PtrF%FO(lwfi+1oiU+*`b=);F?(B znpi-ZPy*l4@BqkMW~e46xF$xJCPt7RP%tCn^Pr>Q4a1v`hPMsxJN2?Kx-i~g{NdOu z!T`FqiSaPwamRx%1UfG|8Xh?KQouFyK=!HEt%esfPl9Nd&I1Qu@H!eE=sa=o1+Q!7 z0n>Gx4jCTIJPD#fdkqf06aYyH7#?)#ym9b_fQ#V`pWYai1c))9e8vlM5J)+QBVc%; z^Vh*w0*1d_4Nv&=^6t&&W5~P&vdOXYlHD=MHpQfFMu{j z<~TB50F9U@fHr4%ajnw>mF^iVe`6@DKSN`M2?Kc6cy?3a{s$%`Z57EpPF+l>PYs-?RA@i(|LY>l22T zz`K;bGSVGJ)j; zs6D^wD`<4&IB2D%52&xSXem2G=b`2w(Pf;++@l$GMT3n8wD&1Nv@5LFMgjE57{xzYDaC)Ti@hca2I!_iE4*yUt@T_`m%A4<4T>-P8D&0d$O?0;FHn_!n}T z-#sP<2FPiCjIU>c(=TX=evD7&OW*EN1CP#EFL-`}W{y%+Vn97qFW1&5rRO0=q**tY zFfuTd9{?@k)^Oq9{sVmQ%12NG4dfOESLh)uFMg_mmLi6z#DFRz3(!8#RyStQm8>H6 zAlGMo1@{kPzz*ea)dsH^`On|733M14sAmW2(s^~3sQ7qvLbeZk_Odwmb{_ZXJPb0? z!K3pSV#pn|2B`Tk(+igGzyGIoLe6k~4GI^Ke(0{f7wzAE{|9Y$b}&5Y$iJQ4g@60W z&O^40prwAox**EM@ZQG3Dl6=?xNxVT5#E74O&_I9dxs&kKs3%UmQFCbRK@W8MJ&568@d9 zK!KwA9Te;?Dlz=qet_!X)-X`DWBI2@6eQdJ2^6mfTsj|U{&2KBP$uTn`O>BH`HTEd zzyE6<2kls7@Zk6O0d_7pE&G7ixWZlR((BLoB1r|@){XJ(Wcdz09FxEGBWP6&q}Oip z2@)%y6)vCyTRgj2zJofb$5<>F(kwsow=se@CA{qX{^I9H&@{;r{&olOTI3WJ9}j3i zd-j@q2e1EdKsW_0l{kV{6EnQH3R-FoP9kiemMmylX7h1I@DazyIMQ4!-xuu#Cj+0( z-5Jab3~8OsppzUyLJn!2&7dP7JwQptqZ54C>2OXm02nt3}KlH_`50H=qr|;65*8e4Xj{N)BEsxh^v>vEP*#VlA0bL^s z$BeT3%bv^BolIIsTBCo(voWMBn4=a6Ff=|ZkILe4giG+e+%f0 zE&lD`+;bEXAX{8IU()*$v~&w8G{NSzo-C2(-`)r+yDcx2 zalD)jY3J?$)q{uAChSl~z0b=7v{B8s^<+sHs3Hdq*31NL5Akh1P-5b^3p6(BXnDCz zq4Scf;U$lQk61jICxQ}4H!Du zP>;^1!5)ooKx_4Ux+hKmmoig3z+;WAV5-wsz^8L6=r&={28fo+puy*fph*(YLCI}L zz(+NJRr)Yq^5~qJ0n!RO&8!nF=+OIO?TzhFdG3+jC< zBOK__e1OBlvK8b){wC18DmKR<`<;JV5X5nhI5;n)b+&?5V-c(8cpfEh(!Q2Xt#m-hxqt~N*Due>___qmx z&dP%rwf#V6E9mY4k6u>a7(ND%&ej=VvmsQo1w*OMOVEHfIDL0RMGtUbs^f0~-B#xT zRniSIX#v=zsUWHwY>A~)Kc@!9H8|GptRfg2(;c8v_JOZ3;vcWM$qzP z$T|VXhM$bx49z$GLsnb1mxJUwPeWqZrSrIJZ^eHP=5A1?1x6x9>(Z+@FD2fqMNRqCmi{= zzpy-7#_ihjmcQj60|P_n3rEYt{7s;y6aRK&(7qxGpUx#JppBz0iU&c9*j@Oy^Mt$b zZ@XeDlx${H>e7Ys)V2w+MoK1v-z+!?Hw0 zfWJACk%0kx(+wzn^_p0?@NYln+VZv}*{6Gn3Mjx_tzAIs9)b-x;J`oSxI@eT5@TCX zF!HxEfd*+n7Zo2a?oFEj(gSj$NAn@@2)2iHh>8M#D`@4ctKor$8WkOe5-w2t2^1@^ ziV8_<$}vE@pLT z`Cr=X$iLmd)$jl)Y|=p0C#XVkVLS)&5NP)x$S*F|ZUV(ouB{+%98>)M60|)Wi=o0s< zU@OY)zBwu|mP%MVYLqy`=lTsCV_$x%`u`tvUuB?#M>i*=nF;D(H6H;BxA_ zBZjUYK-oW;lA4hO=`dp5Zv~y-FA4+Amc!@wH-7@1z`y{%&)T575VYdWqw{*}w>n2x z!zZAgpvDCL?ci>ni{*ndWlzu%9*;mRjI?i{7D=ffsJ*EH>fGO*3M%SKctC4mTr8iJ zo`7Hc2D`Wd77opCEINw$Ics|&eJQ0 zKmQ>;YWS@eE({Egdq52zOmR=psPaM2?j}&H#+85jBv9+e^WY;E(A`;<7m5U4>w@zm zXb-ig<)JcpYk|_wF5MA4uC2FAUV$1;%&wi1-2oggjh_7epEd!!D;8JOC2@?!tMX)A5g|<;l`(p1mx)j)Tl+@aen&J9O+Y zXwJsQqchCHvGXPLV3-il0vXUbW)5PY9guDYo}Gsva|fk@oq0Ooqw5gmx8WsZ<0ioT z(=Ek+x;Gnigqct0L4?n)gS-Xu639QvAphJh@#uB_@6j91;tM{=x`ES^@h77H!M}}( zf14NR&|Fr}<^wDTA95UgAi#Nof1B4|&J&KE4u3o?FP7fwyzSY`G7Hmp(EDUS2m2|& zJm}HsX8{^F(0Gv`iq(HF3(tSYZtAWpcyy(*zZUK&bNVs@FX1HxU zI^7LCI}f*BD&^>m*8$%X?`nA4rxSF;9>gG!Z#=p^4Pf2@U0e*hdh~TSG+p_qD1bZs zU@IVnFp@?0g+USEZs5^*5SqZ|A9n|@QhdD&>K{kc_3$1(-I)@eoo75duY30Tvbl5~ zdJ)wMn%q1L?hG7c1l=5N(CxtD$bZhI^E>|u&g1+oD;OCVTtW36XdQ`b=Qm%*cc7Md z79#^g=K;rVGf&2&p1p4Dj@_{gpoOv^m2RMmKg0febYA!EbpgdBEIsgVLyFG>r5`{` z{XiF!fubLD;JhnnU3YJeFr#mGj0!wlTtI9792r5I5VyIpIPz}`WA*J#<1l>d$iK~( z)s=r+9lLL@D`+$yl)6EU=`gl~4>=&$?s07aHpji7DCIl_x-!$Pbo^F`` z96JwoGJ@^}Z9d52YI&;kJ?PXi$KD)$Mn}tU{O#=!Kd`8PT5Kwepi>`R`M1@mfci@y zr=I|e|KmIXa_!6b|DY)*{?_&2b9sJ%_n?C+AaLSwjDcLw_;Mv^Km%q!Y663)0acce z@ey#k^6jiq0To!Fr6-_NjFhB$1VKYFE-Ije3r$mN96NJVbY6m5Eol=v5BPTe@azp? z1|uelUqEC3pg?kg1QICcJ`~_Q=m=W30?N8RD*rhTdL$q9>=kM5b!2qwW#M?u z20Gv20AnXt=RwF(zXwV`IQ8c6GWuFxDP8B0{MPX}3uw6s!^@kX!%i*lmcMrC^<@M} zbc(F@=w$(|@?j|U1K-Eq>-^tE^My}uNCT@cBVs<*k$)R#J!k-^JYn@{J_ug*`T*L2 z`^$Nu)A5h5<)P9WpefqBE{tbicer$(eccQ%??LSk&{_@G&Lf_kr+qt5v|cLl_UHy3 zpu@nwy%SVBf({q)U_9tyd7?-eT-|{-BE#a>r8|Jfwe?bIIH3r@1UpUQp>@`2Q-gj;NR+{Z$d9TF1+nL#=yO`ah`7k&C2}k~O ztp`dTbsp?|<;mSN?6m-(c&FK_Sn-E%-a7Tg8~^|Rk5=AV_;hasg{vc^ZUvw34jO%H*a^PI zg}-GAxWwJL1$??^Bj|z;r(PLQXPm*Kw}8Wg@v|?eI86qf$pYF23Obwxv`%MgH#>tP zc<9Ho^C-CJW(610|M^?~fTF+imn;8vHz}W9o@uW|LH_Gy>0~_M!Fbry@*{tX2>5Ux zG0@!u9?i$VcXC6vHlIjyw7gJy8FY|0XptTN_5&WhEDb)rCeE<*#lPK|rSll52lVZT z0DlX}rQO0V-Frb-j_{uXbqT@uPP%sfaMZluYx#n|Z5C*wb9e6w76t~;HH{B_7*ByV z{%O28*~QM_*m&Taz_F18Ww?L3ge)cyyL?xPV({s9iopdmyd(A2WZ;H_%CZ z;PmIwe3;9}@-u&{GAQ!EA^LhRC_Z~vf+EAGdnRaR$>TUUYCx?&kK>ICKnr+4J2Z~F zf?CWBp2uB5r*MF1@XQVW_KDzp49V5tQ9Z^(9+nr1#9!uuLSEhlboC(U%%DU3ZPAPj z42>2FZZ1xxue&37T5p#;=?>rkHDo$tR5V`L-2D9?G>2dU>IMI1_vwyN(co`W1Eq(~ z7oE4@>bBg0sN(^5zFR?V@4N+8?ZJ4+qjM_A&7foGyCK)rrZrkHFuL$>|HXfjzZJ9) z33N?yTR$l2^g8}vU{icQddYX0p9dRZD64|p;j z@U%Qt`o!1rL^=PlR#47he8~bC$MNZW<X_y#rS z436MI^Ov9%Sm5|R&JG&3?sVsPc?C4bG2u8nXu&jye+0b9>jtEG4xb-@o~Gg8(RmFt zU)C$C?!w0ax*M?9MaAF+-yd+X1X^$I5FH0PF9OtcQt;>%6?6gj7GJyptr9susk}&K(vKNr|@g&eK08HN#mOnplPgb2A}Rk z1E0>Lpi?(JJJ0%nPW7CkA_1E4>upg1P5yZFiav7YV>sTT0@~0B3a1xLPk#UJgzz0Z zkAc$EHPD$^dsINfZANbX<@_!CL1V!!DxhN%9IahB_*>V3mMrma?@_4%Wf;($T+3`G z@YG{xugFx;l|7ah_}e-_+NP*L2^9|Ij=&Vr* zcyWybG+omJ)&^>Wdw6sn1G%;}7i1ntGq@G~5S$p`=D5Io_F@`XKO}HK`W-wvL3f_= zw}Q6a^KWl~_#f2hEn;S1@a+68;^&JvXb&(1%-o&P*K*Qh9f zm7NEjZqPYLMT41v0d#-1i;Bf-TS)t+^A_VF{wDC+KWOkecDhM8cE*V~c9scvbe{0- zGerVtP zz`o(9J%0;meG_P4&%&eE^l~i^!%lfnh|T!yv9z17lfS#A1>|zaPB#{i&qA0O7!JH* zvrVhaN#}2Q!@$5`o0y!R!`}iLmoq%ja*2QHfrAe?__uumueS^1;5_!iuIE22O@R{B zCs6CQ+l|Aq(~al*G0?aPe+%d)AAmxp9EFfzfyWM#BTc3ev0{B}& zJ%P?!FF`x5Ays=cF<`daA~+4G;E-y6DY!7-bFD8bR#w>3xNi5L74}Xh#fq-LyrIG zc9LLr66tJFnZwAyP_(uYQhcQ)mz3-Pl?caMRF;5f(5Q4LBsBP2DnNw*QkeltiY=fm z#8Xs22M%?%s4M_=S6u{{yQhE)zvc&jKwIH_K(~(cfXlVklO>{-2l-nq|NsBb+@b<1 zY91Fkuq0Sbt;_f+M%A>nP zCBUcip=alZ&RZ|cpZ@;e3@LQMCx#e!faaA=SU^SHhg}|^23+UE7lJ6Nj`6pGj$!8C z)}jKM#^_)N6_cQ&p*q|dyIa7ON=G^qjOEVk0+NSTBL_+%9Qn5&Fudg0d9d?h^C3pZ zi!V#R?E*EXKrwA_@Bz!^N1%fc96?t#9O@`%anZbiFyP<;j-YkMI``KTY>@*R9hnUsr(1kW*RTHG5$e{U`X!gZw&zH zh1Opnbrzr~0u?i$JJ|a`=Vf9ts8#-{|~zU%J33s zsSl_SF#Hcbk?yi*=UbP~qp$fJe}Ss1QfB_`KR|0x`M0~VSl-}oTMcdjhp1S9=HmpI z85mwjpgK1Uv}A8Pq}ooigw*XG-90KGwft?M3yVFv!#I4pLsT5nI$5GXsRvX~dURg! z>=wDy9mLZ33shtAw^oBDXSTn1-RO~g12oSMjss9>23~H@JO>65eNR(m|vjFXo6V`54;xi?B+QR%4`lEojhQpEf3Yd z1}|`V2tMzvo4FH`i$OiUv`&Z}FH1ld9v^p60T=P8#W<)*`%>&DDAvF=-%GBa|Nn#T zWIDv(umAi1f5QVWHGcp9k6h@V`3ag~cmZ1K^A=XryKo-x>^xf{<^t+}oB}D({NdRA zf|0*C>T3b{+K&N^fcrE489i!sl z(JgWq6eEpQETCk_-?9l*c(l zU7)}KX$K`skeEm7ZT=~TJX%lkPdQ+5h`+UnpMk-n^>zt=x3hq;qrkT#jQp)}AhF&# zU{8Y1&<9_h11b$b{m5M)pTqOqi)DYofdmc@kgq|v&+@n0@Pi8c8?XW&RP4##M^<>4 zzjZUX#SRU$&R?Ky9iFFt|4%#aqEf&B>TiICAHZHX-l76Jj|s$1JKmzg0&)SvF&C8z z22e3z0ctSk_;juTXFFJv8FU&@f=A~)pUxT;1K-Z)-Fv`hSndG_D}P@n8)z~eA_z_D zA3eHRezUCowf6gTKWa%y|lK*S3N-+c-A< z0qqSg6>I*@&EM7sK8Vak#p1Y&1*jBY@L;Y{vFL`Ro6cJvy=%ZJ$fNV8Pwx_NLW4OX zJRG#}t42k`v-78C=L^t~tWPhba`yq<&UVSCa|(E-ywgP`;zi|*|NniuAp#&bgWBhy zZGE6f>}~;j+y^q!(hEuFaNX?PE-DeAbG1%%y0dh*fG_UhKhf#V(cPi~3Y<=N9#F`G zuQ>(PB`^49fEH{0^6B*#Fgyvf6ES6Wh{f^X1A&7NB%sq}|Dp6h&@7q@=K;oppxLGK z%swg+zF?pEbY5cY0oS{rmSn&TQ17`^#iJRLR6y+pP-HPfTxJakIsUe9fB*mY?fl~b zIti>s#RAlJN$>%+q(F_%98d!nRCL4IjLmz%S%9IG8=B)maRJ(T3Ch}_g3thTo){>w zKyJ9B1e!v*`C`j)Py_cCNa&=}A5fVAN)piiGANX7zJRU<>rq()9A$jKj2O{*lzyT&z}(nfjR{SuAL`9O>Cy)zyEu7yBc_O zx*2%%vMN6W1-+XF$mO7(eYXP#=%}|&@SP?gfrGEOJi0qTqf^a~7+gVxftfCm8@ z6FB~Z%IVGxAlZYp4Dv7QKEn%2P;h`t?w6ULK~_uw-$wHiR4Y0*{(+QbcR;7jHU5E= zQp+J6(8y6bc;M{ZKKjP862fQAIfxqPs=n}gC z5l}#B9s_4tkiDRYX=H<+?)C9SEUH{8sJ!T11MZ=NH`Kj)QGFU5BOu)jX`L=A1^lfG zKxPMn%|3e+#cWlO*+!sFbLYnwjHqUFg3RuG1#*!(l9`U3$M{?QKx0eIKR_dFIVuI9 zn@>T@U*YAi#7&k zkopbme*RX_It)-H0jeyR9YJ2`JoJJC)e{M<3=ClVKu)zmm2&}=S)iSUuU;gb0;M1y z6@xUVPL@Q_KCtFJ;DBS`Z>{_DA9Okgf1d~|0|Thk|M+6@5tNXM`Sbrj<9!csc%*?k zldVDj|Nno%dkWzz{#J9)s*&vn7!SPk0G%1B1PNGBMFFlH7#Lp6MKzTT)Urg4zuhMh zCW4wJpn8SB_3rQg{~a4)MKkD7wEAD96dErt{3c2H8obI451Z$Bmp8l3{w*UbkQo1gz{KF-p)M+J1K694++pehs8wz78T;BWP2 z19kVdfQv%M<~kl_{x%DcQ0H^s-W-*Xy(*xj3axWN&ie|<@gRpY@VA}@H4M7Lcr;&u zR%iYPwIM{bJKZ@vnve4^9_xN&^XSEADhPw#x{2x_9;2hEZ|Y6w9jU+}kr?oLf}>|}`p_0=u!*5C5z{O!{D+_m$K zD`*b-flqgiN(3nFMYwi8Ykt58H?5-uoMm21gBn@}{M%U~(i}ToVi_Rj@b|4_U|?u~ zlr{{dw>=939|RC5Q!TMs-6X6Eu3>`|JPzm*HQ*dqu$e>s<|>xEj8Fy$s0`SHriihTmRK z29IQc>Md9hd~s}k!sOWb&ZG0LPv_y+!q|LzzfRt@u6Y3m06Z1AGM)sjUygV&|2@JGaN!I(cg~~p5a?o$2*U%f zO)QVriGo(7xPcasF?D$TbL8L7EZ+X1_gbQfZ-$R$q z9&prwatdQ+zkrC%fCH3KPn!6A+Z~& z_~dWB4cg?1R9AH#0LL=8t^%0|I!u(mb?dMH{~eoMR9KkOnh!AYw>$uC3v1q^0+MCm zZ@mvXJ?%DsE9e+FQ1>0YDUQL_@EfQxQUDsC02kxEYrwi#RdSl0=P+|n>`@9>5PXs-9=3(GFBprcFYC(zPZ zE06#G8C_H&Kyx5q$CXHe++YAo3?Mh~Z=VCcqcg2j#u3z$1c@=eto`{PJQo2A@@7bD zg@M1N9&{taVUTn;Bzb~{dq4(*at=yq30}+W*m)4t=xI^80~#*KeS-)~P|;Vx-+GIa zfdLdT0-)-ucPC0z?BfKj+&*de)~9z1xZDSC8TbTJ*<1)7Lj}bOsMeUm2^!>wlqVqX zRit&YWP)4WvjIwbpyUi5zjZY{pm_n@HUwpN&;>f+V1tAiDAl~M ze2oY*&(5R#tp%Wa%({CZml;_@T*u!I%HTfCTU0=2ii6Hqy5tJF@~8!TAQC96gBGNK z+8Q7$K>5h0a|`&8%Fa0|pe2u;r=ccV_NdGO9lG1L0n}3LZUHL-IUA(Wg?}3lhfC*) z?-vfdVDEtV)ur=9^MiVuVE(prRt5%}a{jh+AiA2r{W1#!gKOsv$L0gf{7t(+vyYaL z3!V9!)_~?3dxIHWI&boC3lU}D-{!;1;MjTX;6oP2ga24u7(Y5TJY+0o`hL^3*Bf-V z!G#xYU^R`882A|&To_N;*zmVp1zFH~iNDW|m4RW$|NsB%T{JIP9^~)$1sTtHs`WO1 zA80uQSW5GT>5!e|dTT0tTVorn2b`#{SO55C|4)!m#&J8v{UU<5V8B`-BU`qzAj?b~4v{+4Y_ z3=GYOm_X@&GpZe+xrm0x3Z;uca?iK@{;&B0*8Kz-4!Q;jv~#6Z2PvPpbVHh(y*bQ0 zpcSHR%%Hr`S)&48s|>0HK|SwoNc#blTQy#+eF1hfDAzH7Tf8?wD;AHl|Njrl!VVzI zPi+Nz9;5{1`R(8i8)UQ%ByGJLVFIW$1toF*)`_70Cuqh1q@)AYgi??Rz2Qudc_)wp zafshxR)l~wH@m1faDW^EijEhqs74q;jNo$YyaCdG9aUBYq@OWH#l)qzmV9sn(U05x|z4`~O>bOv*Pq(Bu}r?U)bc)Oreq`P|# zxU1yT`ICSB9B@yh6Iwp?wx~paT8!OOz@k{5J~bn&-<&KToA1zL;U8SuxW`5>cZ57-IimpgBP zrlg>Q0xx8ophKs=pbL*)q70q(LY(WMf`4G!X8&K}-ym0ZANAm$D$Ad38I|BZ@bU6Hb z3A(hSc@H>nAmfi9&7f)?V$q8{gpr_54#-ka8Vd$>$sxAF;sF$jpuUVx=cCSp+TJpq zkk(D7HwUNzuf_-I(||iTl6-&ugI3x9e8CSAhV*V&z=AL3KL7v!?QjEsOXr{e|C2k0>RTm0L6L>U}=gBiia+rft%j2B@g znqzM;lWVUx^Mw~+IY_y7@DT^7P_yH2)&Bke|My!jRX`1!mcZZOElms!;L@wl>G%Kt zFAIMB{|_lv8Tp%%LDsHWmmHf9Frj$) z`FDty?|=XQpMTqdouCOJm)?RkE}b7{e*fvxc?;~ngAX`*eFPXCza0dZ=b+25_kmQ- zbo~CW^8zS{4*p<*sdQ|3$OJlGioaFm7dRMXfBpY&Bh0_;0Dn8^F4X21Tn8VptAc%T z(6!|@f9q^!28Qo94KKYk1g$^>-Ny-^uO<_vv53YY0Hi6<0%0dk5rZh^}KT;O5bPkL*i4pj6=F!uY|r^POjJj3@(W zLL5~68{YP@+yZV0@VEQ`FANlO?e=4FY^dX4=$ryRFqwbqAyBgn6t%9JH(fxBr$DVp z&D;E~6G3(HDFN^@xnM9`!D0&7QvOykCI*Ivpa1z=ctO*By&nIY4>CG6@bGhVKvaMX z0+|WA%m8ZU%Yy&^L2C>^o?+l`0iAdS+7RN{?aJcY>&oM}8&nr`9_qa5VmU_zq^P9W zwOhco+k?f$^0Fhp|1B5G6OR1;2VE>LI`aFRaipo*`LX#hj|bzA4gt`T0#G}wBY+W-e!|wGq#tL{ z6cH%JffT{h&qGv2prYM{e>=2a!C0c=`#yoXw;x|btpy#H;-aGQvgO z;RlJ#`t<*QCrF?}gx~Pw%S)h1`reuULCLN0H>hafZ_fs=Q9rpGG@9zT6SRujh2Q_Q zWAhp-lbhDP5u^80tMC3prcYAdNpd9XyqvGYLhMvzM#J5PBs z{%HIM@?d#P>&Z%H$M3gXI|P~!Ft%PQQFrP5=+Zk0qVR$T<4?!NUtpE0t(QP5Z@6?Y zf|l@s+U_8$c$yD0x^$j&?Y!}_5VVW#;2{pj=3`80or16LfYw7bA7Dyz?Bsa81k#=W zZ8`?+bABPl25Ap~$2d9J{``OW543r+`4H1f4N%1o2{5LY{Gc{EVlg~u|1Uopvi5|&NCj}T_EFKI-#AY&dbLkjcHJ0&Zj$*!xyy9n-g@~7I^iYN3W>9I3L3c zchF>H^KQ`URtAsGX3)7K{4J+ICtNn~egTR_{+1qg1_n>?JZbM970}iskK@fZK*oY9 zzFyr_aXyCQ&7fnJL1Li1Z2?+o+XIpX4QRiPgRX;Y`~_aR+7fyyf@* z&O_ZTV8?>YhD#E7+t!_Z9F=>gDOxVPIgeJi*@vIvf1pBbM$h;CY?qLp+wB_?toZ z3pYPw?krIW;BS2fDx$i3z|$YyEh?bz z&_gXwA2K)w(uor zgQ>@h4SPVxN`lbh*x|(j(gbpZYljmDXo94}i`Av`Bq(1xb_8*PZ(>bz z?DPWNADZUa>BI$IUk=g$TGoOz{i1OT;?E3Fp9!?O61?a#0^#MBKWq%pduKr_1R}uW zW+5s8FZ7ro`P>7v(n*o&&;M>{V1rf}wtg$MI}S;opv3jk@bCZs6S!McKoQ5^0y+^7 zl;4rpM>8-mpsbGuFB^IJ;shgT*!1Iz1rX7K3l29+xwoz0*dJ74Yx z^%S7z8FXG~`~^AzfxpENv^(J!B-yKi+5RCR{v}3@zfwz!N=mdEe;F23mXs(p{z^&8 zURom6_^YHiXK9I$<33Oc12Tn)fxlJg|NsAxk_BWEXk^X8v-1adrp*I<)B>nk;?da* zYR$aR-vt^j+XBww9-Ymg5*a*|4LU`^rBma0iwdX!0tGI7y?6H%@c2@9H>j-YyZ~Cy zdx(Ggf!0g>9iRr5<37-`ILj0Ky`7-7)dwFid2~+(nd{NL8C1@6i+~41!j^&y4Up;3 zy&0g5Y-T;YpBv+(>T`?P!mJGkSw%)E&^ymgBL(tNqUYiY|6XafSuK4}G zlihMNNLBrPP>uI}86w@fbZ!BsQc%KeiTnHiKcv!!?cW0}$UMQ{BgDzTV0hqVK4_f^ zcwdx9uV^bjC~#iB_}K)C+5;ZFqFwx;(}E7ZC~pSUgw3F;`=$F2(B*av9=)QWQ1vI_ z>V2T<-685h_5Vvwh7P(kaW;sLt0 zF`&B#95A3ggAtycM?sTZ37}J|k4TMsz$Z$H%O zqT*4K0XpwF4P;4yPv=|jUY}kD(2R3L=XKD&(*#i4t8)%`DPQMd(2BrckmfR|As@Bq z_kWM(qb!W~p+$m^<Wjyh zKye$Q0>0_N15tOjo&qJf?JeL25je9o9DKy|!etRudFz2rNYjG9b-@o%w-B_P5IngA zs;L?HTi%0OY@InO87|#9DgiJbdvsm~^*{qatJOR}ZHj`|GN2wBNRvmW$$ijlv`6zX z3CkP&ebc}uJbaO`1XNr;>|}cp24%UiyzquGIbJxxm^?2`m;C=KYdNJarG#y^TvQyuAqpyt`CB)j8OH}U4&olref6yeAcnTK!xe(^j|aq+55Qh>QE>oe z9FOKb;M@kCO-phh7oTY5EM7 z7fZ~W4>4I@EHP+)!05P3gn@zK<>DWZX-RNd2TIl8wE{22KtosHrozia(9yb$|NqyO zp9Br1x$tkl?#RFXRIkXS-jJybjHj$213Trbn@>Ou?F3igFQ0-6%YED+TV%ie|G(=$ zXgCoxarA#Di23sA7tpfd9F+`k%0f#~4?&44;KjNHkTrlFpb-jC()Q`)t<-{@>8?>J zaIySVZsMqU-O=)Uk&flXa*gJL%*}_G9Xks|Jev=4G(Y^){OAwk3C3$amOd&0B@Vvb zjE@+vGe1>2Q1*##Gqi&aOrj60k!qNo&^=ApzbHQ3GSkj0BWM$2QA?3E>Vf_ z?TzAr6i?7v!v|DcefR0S2P>m2T~reIdqG>(y4gLNj|up6K0NqBqQmV&H~YaC0v&E2 zyV*O^K6SHqxP9i|<}Tdf_Jx1DyHJPQ*KT)#jrQ4mO+nvX^+egL1gYl-LH3~vQ#`H>i_?Puedxr-84W;!7F2b|8GnNF98QGw)4CN9b*7JAFek< zK;X4x8o1rq__MemJ=2lj1vGjt;9+^FM53Fc@n>2=dS>Zk&>1D*b9Ou|50$>~=xzqh zPkS_11TgToB!i~D4Nv-ZKG;=}nN*D2NoYL|8c~91>}~@)5!Bn9$;80m(+N61?f->N z7sye;t)O9V@Zo~4hTp(bpOui#2gqD!A16fT!xe0oN9Rq)&ZE0RT%4RC{SH^qeFEal z3=AL}_?bZ?4b4KJ-Jk&$23PXl!qK`e;a|7oD*7Z5f` z^nX|dgyYkjECCTHfL_w}-{ZJ5_+Sc$R@Q;z-VN&JSP!a}->5$Glj56g@EZOowIJ1bD%we+=1 zcM#}Mosvf$orhivfzvfy-EGj&gH=&tSvp9a7Z2z(okxz1CqV0WUxJ1jAo;-6@V_hQ zNC0s13^Ra+S4$CSwMOF+P#Q)VX@QR)fEQarG+973wf+G2kqY& zml#BgXXlF-UP!t?8~mG}GkSD8E0k)228voiHz|8|zSt!Q(eOeBN%dw>5#8;q09M!q zKCa^hv`u>R#b+P5V_Nb+-QHHvU6&L1w@-#7i*87=c*Fv_InMGTe=|2|c~Iwx*L=|U z2A{`LCf8^IP8084x;;Q~&EFah>W?&oWy>FVbe?$43rR;{kuq1%*)49)rSDz39e6;; zw><+d#7BzX|BzG2UOoVIGaY$A5y1jB@}Pi+yA6KKj0CSLjilsa2@nL*`M0Sl;<;co$*jo{JU4606D__yx{mHqtN zS95{N`|b>bH1J6_;miySJ3s@4u!5D}<%J8V%7ZVB?=4Y@aqRpFTE7h1;0)f%4j#2F zQL%VoaRfAc;%opr-~RP)P^YUzMFV;sKB$}o^##BMGpM!44%XnJ;sDdJ6Es4)|Ex>r z51-x=l>}GAC!Ibj29EsO&!=5{;oJGW(?`XGfBONS&KwmF$IfG}i2Lb0y0Z;@JAb%< zHs;*?KMgd+0?G2Fv96tuyIoXDd^&G}O3Q;k*gP0t@^8;kNl5Et1kKFwuRnV5DO+bI zhYRC}ncr(vOwu|XnfSN6s3aYHz}D%=)9J`kBGLM`L2W0iBm|Y(C29 zV)-7jNgAZU0@RW9aP55P2pfKd?^pH#E!_d_mg5KQG--WOBJa`J3_4t(+nK|qGg+hg z1XHIo$7>$L|Aud0ZUZf^cjf@K~!Yf-`@vYcGZvmaG@U0m%+tR?_A_AUQ zY4!tClR;N>rgb`Jr7<@LF)=V`UP$W<&PnTZ&g0+S?8L~x0IjFeI-Lt3=OyxQZ(amm zq(8Ze2{fwWT*SY<8*~swCrE2q+QAq6j2F@_{?I&_*6CgH()2%Q`_Th%x&dV+RS$S+ z*18A0R@GSoT3ef}0tP|>}8GRRMc2hzSDVr1f< z3eLGq&5soLT@Su=1g!@$JZX3dbZ}7uXwi6r#|}{DVrF1u@aW~OVE_#Qx~OElFggZ0 z;h;pAf7=Bc_7a}PU!YrX_*+38YCXz3CEcIUj8VgLUBhqMpT+oF#AQ;xnY{|YhbW&cl5 z?~$MbK@$t0nv{XTL)kflzx4*F=-rN-lsb>4ab7Fc<=;LTbT0}2_T~`K;XM~YDU9*L z_nV-EmDcH<^Ku?&65a6IOS519LASABCcl?8ph|iI0vtxWufXsCvIyurXGaO2ZqEdd zZifV)&XXS94iX;!A0VcLJ(}NW?0OBp`}=@Lw<8BwZRZ5gIyS>g9>*I%YtlgViO2B< z(CRgCQ=r>X0%BCc{{R8-LBkq{VdKq?{OdhAe7gmGl23w8I_$jU(aRF#+biP$D<}B( zGk`A0WCGp8IKxNtgb(9|wAM={5+1!gK^}~t10MreJem(McLe+e9m)FMv-tpBJ7!Q?T+NArRY;|>080xpcF zIod^l&@K!NptF`0K;yvy z9-XIMI!|~cpK|Rybnpk~w`R~eT}&l)j-3a0feu!6Yw$`j-T+3Q-e%CjG9JAw4xN)h(x8ic(mFZPTsk9|Tsk~hntySXfbOSOh=zy1 zPj@${!ROL>@&9Dd0bR$z=7M9e`G`XFVaJ0%(apqTCLe32qk+R z89M|#dOa9B1U-=1V9P=Cg`Fo}--FVR9Qn6h^i4kO0g`_f@0grA60Z@O6)y0yb?u}1( zC#VGRvF@~BWMHU`_U#R1^zY^I^y!=k7Vn-2>el%8@|<$*WOV6n1Pw!Xcgiq=rl=hS zTss{(96LQ(d^$nLylH@rQgvZq=$;5t#TdZRJrSgk5tK-eXdDK2n*NJkYZqjg0B*;G zdo;gM=xzi}Y;|65Jy6Q!(YzC+lc6-Vdm?BjqDv>lcgMljf+D8Z>A&SKe!t_LU@wB( z9WIuQpfelmI9)8k-meqr1RDtoDbTT24h)6|EO&x-{PE8_fGjlubQ_xkXei0x#YXV5 zd+-)*9~Fbw4Pf_$ffA^N$8pe{DfqHI9goh-yFfi(kIr*1VP{)j^gQkW(#hc1?Wkbslu*KSc!EdcLD1}^Pv@bR3(J0Ej6a+J zm)%XEwysZir9gM3f=B0NpWa0vJszFsx&t^sB|IopTsx2Xbe^@WPAIVf34x|n4c~$% zC%-vxF!Hy8)-$xeF)%Q&x%BFAbspz$0om`-`nH6V*_FYCIhUpLc;{ai&bR!nte_*Udc89o zoBuKLw@nA#@7?Xk;nE#l(CwVz*gX-naLl#45man{zvT!%^YRsFaRzAY)w!2P8q|y| z==4$XabdjK>0PjM^{Q2?Jowii1dnO?s5pRTrYt~HQ5Db?KcLpH$H5nhoz59AA}T=h z8lOD6{Sy9%Wq{7;3+Vhn$L}|MIv;{&pkK&W{QmEe99#goYU-j# z=B2RE(9nZF{6XFF|#$yaTu&Bn%oGKModP0JR&T z=?By!1KsO;+&Q7RBs1ydHprwXq`wPFYf0cl3O4&?2UxoU1I*qz53t+20jlm>GpPIS zz~2h$QGoJc0q7=!0#MkY2k-wdu&-Z&Za0G0M?T3f5B`+*&3p?ADbIs%6&y9sIx=2; z`3!2lYv&8lg71ef4wwD@5B4o&Ji?=ww-M9;>P%6o@aXITFUj%f^-)OxaX@TEqwTIQ%d5!9Y=)ox4yrQpto z9^moV7vD>}~|v%>!VsId&d+5mpL{b-x6k&QH)BU;zp`(0Qv4 zj@@8Au26$CZ-NFw#KD=*yTbANjhFBKfF@$VW3r$|XY02T9uNNg&7j>FzP&uhx}9?l zK47v1-Q&#PZV&3FKo(eaJ7<8BPJ%}-FFSZaH)MVSI`a)qOr2A}(bXMX0E%VMpcBYd zNYRWOx2=~dI6>zstv}?!cn}hQ-EJA6d2>+W^tC+4-+UE(^4kYcIe$=r>0km26X?n% zAIlR(AHYEYa!-Nd{|lfZzygx)9J~2iPxb~fgW6)=c8Dcs3v7IQWan zu`}$CujR+`%P+-1L6IDy;^Wxe2#O)FsgBwc!7<8s5ggs;dEiB8=I{UAp&Fn&>n@c_dvv=hbT@$70Idf~6d;#mXgJ2i9!{I^f*WcE zOuqDiN4KxS3zqMoT^J8QH=TeL!pb|x@Es={7#JMG977>jkG!z@!^YsDd88ZMLU8Hc z2x=ZVb{=rm{NS5>pwmUg#iR4IXY-HHG7XQN2M<7iXKz4=N9P5P?+-md*9&%#Hh4Qh>f9DKzBYSDZ2vK;j2 zYzDQXcB}%`O_~=xI-5bwEf?z&6&LVSR^PP`t+^_wQ9Rv zR6Iaa@fM)91|hD!Ds0^@DlXvL9$hRSxbXWu0I>sJJ44c0^A899)+>w*3>W|Nx10er zl^MUgbe3^|&a>{c^RO;avEXl-1`_X9bLlQ)aRhfUJ-WfJHoW8sx{Brbi)jYz3@)G* z3pZUfzk3{S1~mskMc?seP-KDXJeSVRpa6C0TnuV}y}0`qyn(3ErF$`0*cvR%-zy8U zsq<0V1kjz57d*Nrg9B%VN4L!(575#IQ08{&mUlJ$2JQEBhqD}f#OcU*&9(ERi?%;U z38#zYY*2f!&eo&5UI4VK#H00pNdiby>$j2%E|#}yPdjQ}cJ2J=+WEkv^CqYeR(LV@ zGiXP({Ob*{^Z^=?g1Gw@MBR%jh!P}IOIIQKd!X~zox8!kiPlSXve52=FDQ5(qW2g; zLp&}JAJ^)4PX-0ROCHb}c=8Sm-QA$pC&YD{7dw4a6hOlm|33Zy|9T;){P1Xg#{!9! z<}7eKv_!?n#j-@jrA`|fDUcX?`Q`8b|2sfF05#wo&=x2f9(er%rGv`=y6cVsJXj~? z*?GdF+l#{&RNktB;-lM1UlwA;JG#`1haK0h-DOty*`ryvW}Qng;*O zpU=pz2|0TCGk?CP0KaAr_@GXYZbt>s7EDkd%(3|a6Xd=`k8UT>XiiBIND6e|qDQxr z#qkyu(Be2y@^k5SasWwz#wNR+TtMruLFuWpMFo_>x}7|_gFqLLfd^x!sDO?JcdtX7kwBnf@&I2{snC_0Ue_Xs$xK1 z0{H{P2KfQRhI$V)E^@pDd?p)I6yzlkv$F-fkN2e(XyH5j{B2O1Md1Y-Xxo_af6)A8 z2)M_h;J63W0|1BaWuMM-mQD$!dcLg(O87l`yFi@>pUy)s9u$BUvOV!={Z=C6((T65 zE#}eN4U&8@E%!I{4kHEdvE7LLfO6h;^Bd5@B2WXa^J@1L@IqRb&cmH9DmtE>XIwhZ zAN&f|8vsF=8RPXQmX=BWA8#qu+M ziwt#D2fQP2!z-&95hh8>_DEhHCco@hJ>=JBsTIMea_-_C2TmnzwsUog5bzT;ni z!jbWi3*&Fc&KIto5K}vEF&+mkq)~BUyy@84170`=sx9k2{{Qc2d5^yZWPZ1cips$U z9ANWYR8(3oRf5`dE{v}_T~t&YyL(hXC7f$_4|vz7BlILWSJ=^Tpv$~`R8&BI0+o%; z2N^*_(BRDqA6+}&Id-0XodWJ(x&C*teC>I>1?&h=#6q_I@cSNi>|6srvBa?xaw3d% zj*3RDq@(p3@c!i*epkcWj@EO)N5VMr&pqtgIS0J9*6;vmv9;w*{ua=L2jex+Zgoe? zZ}sfmJ}L$-n%^8dPdPH4U_1{Bl7o*pTsvDJAo2%4UI6(JG%Nt#vo{57CHh?{&~XG%c!He>O&_nfKj{QaP|I{&s7NUHB{1RXWy z!oTfQrwgdye$3xe1lp&t1uDG?2$oRfHM8(C$@?SlBcZiCIqvm(e%{PpfJvx87biM*@ zDR%Ar2%4>UaSwEoEpv{F1K5EFe{r~WzIY+|4s{TfTO?sQ5T`zH|jy^T?y~ zCrD#=3pjj0%U52^f}GO@>VtK*gF>|%62_hFpeXZbJ`#a4Qw%M~T|19D_v$b>9{kJE z_!KlO01Dvw3=9nWzzGvHAi?0cAH;UmJm2}kg>gS5{e5=iUw@pj9hAfzJ8!sv1JJSa zy$k>Pe=ic=fgSfjSJ&vh#JQ2ApM|lwt}cCy$kXfV>?KgfBg%_^&sUh zL1i*{90}ArWc&^aeem!+y#Lymqv8W{)jkH$aTgZ-<)S0aM%)p(=f(Rsq7^P)?)153An zz*?!mttmM{4GmVz=!H{^T@%fq#rE}gdz{^qc}Q77-x zc^JYHb?LkeX7Tq=2F*0dgVu#Gcz`-C9-XgWf_i_Tc*;oUL6mY z&KKWrIP!ZOwFT+m?+0CpMZoN7I=<1q5oA5e+bb?QTZvl0jEMN1t zsDoQt-XC1LqrW(I{_6bL9sI+k+xd@2^J@uyd4_J|?rIjdULDYWP*7yMXujxWDPTO| z*m>0P`&~zVPlzk(HQjo3K>KVMTsm)n)l`6sQ4~e|eR`mYiC!H+7shkFEP^hK_d5?c zc7AhVeBr|Q&av|#;|IsiuNQwE{K4$pYr^b!@Gn!Rw?U_~gmW(oljFgkOpX`-xpZa= zfR>2Y_}#Jdu;axaoxvKN{}_Kb9{kPZ(&??>c=7MSe@rf&#T*{Zhb0dFV0P&Y zmT~EH7IEo}=5guF{?b|er_-6`r6Q<3;?j8(5@r3qpk{67RVdFMbi-8V7Vt59j-7kJ z=M8%_9s#8=MD{)m9^dxx=se-mc@n%87F4IYb~AvIhK5VG6AOr;;L^(1*boYT0 zYxh1-;shm3$AiB)oO*e{=>U|oIzv=cI(<}hI%7a-)knp|(eihVeCJt^58u~|xjc9E)rl=^u%NNJa z+m7FFJ1X9Gy!ab(J+WhVj*5V5cZdpyPv-;2?iv*l*KQvb9;i9p98SFSXFFJN!Vmx*6XQ#)HZjUdH7k?f6#pKc%z~RDp(zWwor+_2l3CD{+ z9S{Csy7<$j(}TyQ(}AVa+*|!{QuwlnvuUX6SNej@dzkFAW;pvcLH>; z9gAbPh>Az&N6+Rr0xz6l%B}wY|Nr`YXB#MbI;Vl6!~;b$QgH>ECjs662}&;qu_TZ8 z;FTX9kSjkSary9-&M1=qo6Ox;bOW?bi2$Id?o|8jVAUIsN2AQKe3KoP}I zTGBlk)FJI$4W4~D-V7FHU|{HV`tN9Y#gX6lNM|#sbO!gPnK;y%LzF4l`dT}S@82SE3Yd30WU!SU?>|JO~BIZe>? zgn~zRBWQ)9Pv>b*=uM2R2TC~pPXO1U%-{?Gp7Mguw;6bJGkSD4fEOEfJAfwMKyyK< z9^D*1-GKtWt(Qt7yS+VJ4G$c5Q2}j5X7K6tQBgSVq5@jI%mC`Uc62Z!VT zORWb=HTd_ts3#2^~!eo{wB zhYKdO^*^KTab-z9vABds&g1avo3+QCB{{QEC;23qiM4*+jR2lH(B zw+FDnL zJPeM_RTUZ~_MMIq-Hjk0Fgv;&cZ>o113Yx3-3W>Xmrl=wV|MEo8dPGnlZgp(fRR|h9E)jQZ*i{B*@w#*#I`~T7h4IkEU$3VaUV1$NCHXoq zH2%u3NGj%U0qxf?Icsd@vji8=r^XP3{2fBglS6Y5@S;=$$w$mV0jR!%;JR2Tp{FPUfT;{>= zau622jlYU33X1t#R6y&Y+Cc91=xtO1tr7f{UsO_DvXsAVC&UCLCeRiukjqMnp(cRZ zCyfV_pb{k+1<6neP`Kn3C1>!r>;bJeX?q4TqPG#$p=|t>T%3}@-{SfI|9`NLGWc6T zEqRaLM$k$Wgu9Z9Q_A>Tw}8jl8s{-GFo5UhJbD{J3s4$=6@!Bdbe}ZH#KbcG)=r4h zIUuF*^3tSk{^cI!;g z7<_LdXsHFl{e}n9ns@$UVqoClZv)M#cyu>1fYysPACLiuA6%ZDzwH=!nH@}C0#%-k zzikJ`v9qG#tRk8U3o4bSc-0nlNvtp`eMJX$Z6u(@;# zxO57EhJe^Tx&t^oI|V?OM}yb`o}GfA;VX9VVwX-vkfDh2C6Hdo>^E4iCur;pbh*OG zlIw;CJRsE#QhDx?e90sEqzC`{Q=neP!5{V>y)BFk3JeS$2Y>J#PMg5L9bEPx{NLTE z0b1L0shed2s2$(|jI3E{js&GC-~#@P0IP3)Z~&xb0!V%H z0fpuV2fp8c>O&0H@yny@XS}crw2HF%!GY!j3LpbCFYJ5(nscKN4={m_l4`wFA;@?^@q`QG2}gbpP|f86TCoTb_)F6f{g z$oeUQ=Cxj`5N5nE^ZQT!^#>6qGH4?M1JJo-*^l|Kj=O<;`Dc3Kwa+!Y8oNshzTzI+b4qD z=fc0e^Bf}sgCqa`OCFsk(i|IqGB}iI^Y8Dx0P0Ndp8#@l8dy-wm4E*s{`IF^`S;&+ zUjP69|AX~_{0G(px+Bb|m(>lb$D^~u08|_G@|J)PQ0Q=g z@V0?=UvzeOfc7x_VsKz!C{b@b^dHRo$Iie|&UL&2gdbT=`3gW{~p36S^mY zngiX9pjHBNBWQG_6HHoOs5SNJp2z{3s!2ZK(<__&oR`6!e;W&zO9!~-cIV&6!tBxs z*67-LphC=r@qp!_T1#;6;<%#(X!PN5+60&02u2snTXiqo`M3FSF}i|A!*_rdFS%-- zaA7+rg7QlaH|&6vue%y{K+4wxuh;X-Gl1%xM$mi;sQNqB2pYv=t`r5#lawV zT>`D77l@97mfO8DLhijHoDc)}w}VUoABx7m{Q%S$J{SJ&!Axn62M=+$@^8NcF^%zn zE8`{0gGC!$EH4%dJ2t;$aY9&+pib2~3-9(vt|@FRHk zN5iAruwfquc-?&GY5vwr3=9m=u=42kl<)!V5$W^>RnXnu8a|!Q0ggLBN56P&%cQ7z8FhbOx@I3efWFRBDfiW$Y z_*+1OFyM314}ewxM90C~6Hqf+E|orT;opAJg@5~jG|Lmk7TwMPpcTU|ou^zn4|Y12 zyl@u&{lC*W1$@RyCur%2GpNVw(dq1PycyQKdOd$acd$=dr*n===gH&FDWF}>oxvq8 zorhkq2><^7`Z%aP6PCfh{lvkCY%e|v{r(RMFaGUe8J*5PAfbCg;00YiAYoAFmw&%o zfd~KkLmo3ddRqh_KKmg6slP$%?zcO8ymSQ>m+er zzI95fwI#G3Fg)N2I>y59faM|n9#B4k3V4D9`rANf zWJmJ<1|0-w{p z)9zwrz_>jcNngD#o} z95pXGb{=r)JoT~;Jh$M$V0aQuCDi@s^Shp%*Fa<5o##DzMI1c4-8g)DbuM^zy9$7o zavFe6FXUhU1GKf;0u&}zkR4Szpcbv+TX492hs@V`cDr(PzE5*(t`}hF7TMw1?JnWb zEpvgt1vEnDYWNKtw1(ea%fsBkzujG+`52=|^I;y(=3^|DANboqOFvz@xx1ZNK-c`; zbpdUEu{=fNdbMM`pnQ7bb>{@v&V!EN@N(%q^Mp~Rpv^i4 z;H%4;k23P_XQ?>&K)_=LXmKcNu4Z&m(Q&lQW#MlJP3?eYKv_W<{@@P*^x4Y8V9&o^ zW_aNB6HtDGr@zkY{QD<@s%P-p_+ze}XId|n%JT1@3~HLRUMh7$iED8E>Cx>j;K;xI zg-drMsD|}|E;vequW)&1xdTg570Ds z#*5uZMzH(>O?GFz3;|~vP*K3pup8Vg;cqGZ|Nno(Zb;K)`pa~%3ebErbb*{tccy?x zcc8{`aQ7YLR?wyBoiAT>Zv_>CQ&d1ZdqHQw9d}UyHCGrMK`WC$>Rx0*Re(0Df>pGr zWPn<53=9mQWdk6MV0DgLK}-D}L6v}1gM>j9fB{^&iwbzbx#w{f@IWpo7D460OV+K> z{TGnZUBjna(WCRUZ|jqiVvp`X1JK%tM_Yb_Hb@(Q4E5*^)&Pl}gNT70?9m-80TSB< z5d$rV1FiZ6ot*Gu8AJ?pM;=H_0iM}EU9Crpg59F+9a81Pkb&p3k zqfhq&&{`Ca&eNbqC8*2Oda^{|#ca^#rsLpUx)7I52Cbq4SzrjVpnEcCJRNi#)N%0g zI*^*<&7dVfAl3`sEx-R89`NYx2F<~H9B&3G21%rKg4edacndPUdopOZBgn{mn?dPm zGH5&zVkAfcr2fSbkj(MsDIg9gB_D4F4Yq@L9><$O>Y+@~;ut6s)@nug7CIiU;L&;d z1!&|E(s*G2)!WgaDiM^PLZFqAPxnGda9sB24&nd}=_GY?x1KEVG5il2_v!rM)A_LZ zIHO0ei32DLdvu2walDWNxw6|Cbd-b#;|CAu_5+XZ0D%|GV5wjZkK-;z;CQmMF5d<6 z^Q%qZc!xwxcd!J=D(h}%k=6qxDu&-Wzk}>K#^}*4^6SNZkW!G6<1D{Gp0q3$DZd9Y zV;M*Sy15?g-MDyg^g1v==99totAbDWLQnzi*?G>l^$C9qBdG7wy%OY0&^ZngpvsWL zr}JgE!Hcj>piC2@A^=Y8&_w;h0V=8i6$N|ag%(s)0xAkltS>~Mq86UVT~r`xwe?bo zTkE$HLyv>cSPXAN%Xg3N5GjzQFCK4%SZU#L+(il!7|n+TJS;z#-T}2Aj)0_(yQo-z z{0(xc2Pm8Zd^$hA@cj25d=Lfb5JHdc0D~7ZKx#qjH$fXYk2^qfRDi~dday)@3RvZF zCx}b4K!V3zR6q?I29U`SaFapvSD>H)9e4;f*$$)@bZI5J$*N$95YUZ5FFjx;3xEV+ zhlhboP5_x~?a_RQ1LW?BpdI7gE}$bJUwU*0XuNo^0TKiWVAG+_I}H*%?xKFU*TM8;}bra1jd1F5sCiP)Xz%_p)-s@BfJLbtDzeMECzg$92MKWG*N z=3lT!Jq|u#_UQIudI0Lgffz45I=vG>j1L~2-5`H?bh|M9@aP0jQ-Y@iH6V4OV=O3~ zJ-WL=^Hv_+&JsS|2?Y)vJ4Kio7(VmogUdCa?v%`#g3ir(bWaA20(f+T&mQ#Y zTnQTb@aP0@HS_3f1kC|@bUJ2ubOsi5t^|#l90!k+fKuJ@MiwT}p%|d!P69oAIwJ#o zIvpc?Iz1Ek1syH;1sy9qIvYX7u}5bk$W!1UlC;i7P~3sWdpjqB3TThciJ<8B>6{4a zb^3J91SKq=&PGuAS>E>;yUdc;g>NP*C!(kc5r}LBtB*A)gcZ0kO&NFM6Ku1}DGs;U#@ZJwd|I87(zSN_;Py^g51)YuN z+Ii;1=0NcFXMS+y73UZOt-oAA2hx0e@iZ7DTl&bOJIunPb22D@d31+4cyvM*f!ZR5-kPb+=g;0)#uryZe*f=$<=a~m%FuG4qRON5C;zq=FZPH0 z2Hl&$cr4Aa)4cU2HW(7Nj+}2CEx+)$ zZ30~uRRC`MLeobWQi<&ViY8dRcy^w3={)KPx&ab2dIQ=XXye*>5Pa0EtKk7~9DojY zg2#Yj6DS6bKw_XY1XM*kFj&4W_Vwv}Y546$Qt+qWFx@2F*9U|8W$;yJ;m z^JVif#uup|$y?2b8Np|0vP`l3Uc_Q~xBQ{yzw*7{%Md@lU|I!U{p{2Ez@zzy1FS4` z1Pvv*fJzpyIe&wG|L+8u!@utU!l<2=cgyct{^M`Y0|oqgaQo{<^D)Ne!;Fr{S-=5d z`Mqee<=yfZAXT8tTwixW!rKwnp7VfAY`JuIg2taauX%KycI`aUZL`6(^<=4x3;*`U zGoTIrpivHEm+nqbevo@1Ccf}}0@_A%(vg4v1;@@qFYLhFi=BsFJo)?UzhmdY*Qb#BdLVsh z`7y$Ue}ATlPxnShj$R2awz~@@TtO#eo(3)5ZUN20^Y3?);NKsXz<9xh@rAV;4}W_J zxWWvpaBTehkDq~ozaLb;c=GQ*;?v9HSD1VbIXoVsFb~ex6IwsJP z4%gPVbZpO3)2meOE!9h~`5~ zo|YHOuY=sy#|OH;fq#G2KSxkszGDk$tzPFV{{4PZ{QKRKdR-V<7%y16aqzc)1!?UL z7VzmUXFA>lss=y>xX1A(P{jaZdRo5YZ!ZD03bxy)9X!tA!oU6hH)jQ=(mapOmmtm# zG054!q1T$= z^1-v$fziYA1%ErJr03t}@!zBQ5Mzhe|8EC5_*?bCTe=VUSe`1n?$KRW01Bg)Qbq=b zZ|n{wEX{rv4nEy+8UDQ@mpws7fU>c#iROm_rT2Y% z3z$Hf)gAe_bNF_C039LDzyG8o_y7ObpvnrIZ5cqF$k}@aE}*TP zo}J*-1zM>Ls?<(`k|Z=4cKfKWZbgu+82R*uHg8Hkz-Khq? zoiC0#8!*DUX`lsiKL00zTEL(c^sNU<#4#4CL(2c|5EUO#hv|yf@Ba{`rB^}x5MNL~ z>1F5f7hb-<|92j1{10lQm4G_DFD!h1|9`z6q94>iw>Bt!0jfSd96LXP4gm)BdqK$n zG(-bGCkZ5A@#1dP@BiI3Djpu4&K91X$6EiFu50~PhqS*9WH-os7yj)h(i}V4V9Q~x zT~vJd+d&&jK;xYjAZtLKVDKo2iwa~A2ej7wMRgUZmUiO+^>14blqR?u{!epkwqq!9 z0+%;FoiDw5b^d~i$QKv9LH$WTju{6ZFgbOy`~-Crn~yWT*nuS8>7vQv$iJP<#qvk} z;pXFvp3TPuEdTMhf`;H;z6X!a1Y7jF|8M6=K&ARV;%>evVi*W9?kC* z!1j7{hiHL@JzhwIj)U$Fw(vOaq6P8+gGcjQ0T0V}rFTIC6@M3k2Rp#M_?HtvDH3_V z2<-gFji6}v>CQ4Z?xF%3w`2fq8ST6R+Bl`@(Y*5psEuAC@7Z|)lnzQjNhTSd7(kaK zw}8g|kGrUVyTqUv0^8?m2tGIxbfR~6h>8U$Ch``7Qo$z>Ga2ME(3Kf4UqpbJzd)kC zUmWOS zK*fVk=R@Ca8x=^>Ipp>Gzb!ZsO8ay^gt`93YR}*QUs{0Xs376o>!MNsN*$odM$k9` zC{cjC2u>m{-FzU!9A1Q0fDX!tQ7Q23Jm%VZy96{M2=)JqNKa54K!;LZegKu0@(iF< z=YVW3tXT*$Ps62~?*$Xs$PkqR5Aa#dC8|E155Y#h;6O1Doa5p1X<&1GI$y$!hC3B* z?y7Q-Q+-rGhf8~O9tRz5(Rzi6f#HRqCn$0rf+td3R6JfVdV&;!&JW*yz@_t$Yv-ZH zNB{X57}6X;bmv9TR&h{p_wsaDUgU2F9mVMZI&lUJvL2X=@ZWomr(9LBQpbY{Q zphh%5XsaT~(=Oc&pr8aF#^9rp^TO*h=uFz99<8_eTh4*n5uk~zqaa3ejY8JXCtz19UYBC|xAHD3}Y$2;is#3;A@udJ#1j zRBF1YICTERM)af#np_|R}NBL7wIO%{DrFF)r7EVTeAK zeoMLX7ofxUb6$S^3pz2(MFn(*1gM>o^FrhUXrs1^N(Cq$L3uF%H1(3>(Rui#9q29( zKEwZ@WeA|-FTv#w$ovM7`7n1mcCt*fv@3u9asp`B0~$+^sJ6Vo-}>j@|NkHde*rBz zg320RN}JGmvH1|AXR=E#D6$TEb{_IP_{-i4X>#6?k)_|!asnt;%P+m$3Tl^i`=~hh zLQ-UiN`x;oO?q~o@YQBfakV@Qnh>w?;CDLV+35o+*B`zxd;kBxZ?}w!OXn|8M1adi zkS8rbqq!D7jJJF`V?bx=yQp}8L>xRi5Bg}{bhJDVDhT+U4#CO=aD0REkON4!hD$fN zRCw{d2vQOifDYIQ02Kido}iNJKuH}aoPIciZbYb2vG~v5GVkaA|1Wz$=d{U#$5%k* zIyf`x$iTDn z0%+o_*GI+1v-9dMg_1Hv)oRgtphO=u-vx3LsF*W60Gc2JxeCOCbn795%<%Ogpj2f8 zYCM6OG@#)IP<;g+gMdejI+ z3@^AG!8NHx>w(f<&+a*3r7$HPy(Y~bmY<6ik;>PX9?geYUL0}y{eQ;62W*|re>^Pj zmA?R0?g38Vy4%9BVUG&v(l7@87EnbCzRT?4i=^-W|G(4#RlJDcN<%%bx*4>$@BFt$ zNfz*l#h^YpbdCjdRCt0T|8_>t?nn*L0cjq+I?W!IulbvWLESRYNk9Kx4Zpos0WAy% zEvLT&+GPORAdun0@A3jP3-4ihx6B7@PPZ`V-tnOG|NndT27-FJ&Mcs=AM{hrJ~;jcRX;JUmrD18u8J-Z z0-d%5%B`TKaFG70Pvb;oO1Emw7!s{GC!*$zFfKGFA>Es9X`HDbW z1Y1v*Yyn+606vQq(sFwUPya7gj`H}I~i(YG3nDDp0 z1{K8+=d*#_*&U-2lh)}j0N#y$4k7u{0aUt$sKkK!C@!7;BA}xvT0y;Pk8W29{_Wuc z)&eEGu%LN41+2411?)FaU?KNeUYyDO{lB?JC5FMH(_MnUHT~cJ|FBLRsIanh7vXOM zow5%O9Z)R_9wC0{(d{nb!oS^L0DO}>Jg9tnOaJKo{^F0@ap~ zfVvBk3sH#yotL&6G%UYAM8#qTD4;!>kMcnF@^-p{?imp14E@5tKSagl;3KBa&>t?A zAIck>T~s_6UyA$(9j{xXqT$lb52{!|v!Mtdbv}HtA_oyh9Q>`$kV7_IEY11b%t4pD zcY+#jj@==x3?A7pBs`e&IT&xf*ldZ2SwVz@b?l*Lfm)NU4E(KMK}Q-vJR^WC2fEOz z^#(%nvmI0;B-VXd_*-{@Zhx}&0i9gK2ii<(?JvUL&Vn4>7)kkVHq;c4PFD{8)(Y@x zt_NOQLLvgxICOc@X$Q_`E*{;!93WS+Oavzo&&~_{t?qyR|F?D*;cuP`T9MX#fU(<^ z#l`YK`F{TOt_7ulz-qpvPX9#Xbi-+JKw;g^L*#!mP;je$J{_CbNZ-6_;&u-733He z_Wy!o=Mm6hMIoTs6g$WgJhZY9Ufv#ab6^DZs$sf4P;{3b0^MNWo1+r);<7pD5b0Mw z-~$D0UTm=e6&fijA&#I9=abTz;E3_*{P`lv9Gp-?z-tvt8y)w6%7`@ZL4mEHnGEnP zls{h>gNr1%0gw?0kZql>UWg;)j)P{IT0zw`=u~!48``JyWy|f7$`?%DP#1V~x`FP~ z0xRSPm8C8!Hol-i$e&KVA_gy3{rnFa34*wXzZJ9s#kKW+X>fNt=-#=O+a)s1Cj^eU z1u}Mm1zw&3jbOpUr}+faF*iq;+=hSu|G((;LRjqK3F;g_Dd~PW68tp zRGRUZPj{)oi=U?800Grg9FCnwUS@+*P%pR|dg;^o>qVyZ@Be9?E-E&lTBP+r>1}YD zefc8L8d15pcKRx`9wYHq>u$qVNUP$lCEJ@mV@ z&9&QC0j3&RAz0@NQHW{{h!Y@@0oq$?<7#*bbX+WpW9PNz1B{N%&-g(u1<&}p_WFS? zi@p4y`32})3kO&0PzC22{>~ zDh9`c&p7zE9RlS*7e~%xpfd99c@1xw;x2cx~8F=fF@>)llciP~zgz9p(X5T5`49 zOTner@xSFwk8UpwPky%>F5N6MyJcoLcHRW_F^*jQ|DTZ^zODd1|J&{6^7=LCoCCLz z*N^$-8Fqn|+rQZM`~Uw=w-C?nE#M`ZNd7mx^kODh(giLFx)lcAes@ zeE#Ii7hn#gJ%m<1X@E!97=5}If*Qjf-5Ws@R6gC665SO79-U`jf(AIj;of|Z$&>Mf zkL5A`CP~m#G5-UKFB!;`Ltm!K*RK4fz2Jkk6}q0>Xar87XprPD*grPD!%zvUZv0_roU zAol?suJY-HPX=f`^HESctet^@0c0_YkL9tV^3EF`2OqF{GPi?rG;C#;BmZ_070_1b zw9Wv~FshFV6WGq}Cp$STf7UuVc3yJqyy)2ch%wEv`4^+)$>xXunh%1`d49;j-}>X< z|Nq|(Iq8y+D0n9P1$yHe+I|J=2kjgHPu=t;u(U@P>St5;KTU9L-RvtD`?5h z%NFzkfdRadPQ#<~oJZ$Hk6zJ_t9TiFIuE~C`+$w1^+1W>4j%A87HAO&WFJ6xSVgBW zB<{fbof>w6j$Q)~w`!Cq`E-L167cM9kN{Q#qyvdzyHOwPSAcI{_PV%=hq|Y z0&)4bcY=PYzX=BU_!4#Kblo%^ZKdCM0(;tRfF9yBq`@`434E4AH4#jex+ zkLBIc8{m@5BN}}A0`h)@)&nIqNR}~`+yGg25xZsJ{hw{1qZk}JZ}@h;1Z`$W0iE>s zvH39A+W!+k;R>p_!1lf_z3{pXl5V~^ayIa{s{a4~|0U=U7kGIG5eMy&d))>u|B>e> zn%`I$zV(3KTMZhw0rh%2Ay;`jc3$;heC?Th!87@w2jjbLp35%XGKafuuDNup9CPeE z=h}JSQS+ax=5rUz=lp$JL5JD?a?!jAI;IYk5M4AMfzHGNt%(93$n!$@!7os+LqL#cM>1qp;A;_ZK5$|D(8+Qc zH1+Ffd9_Bdo8_A2kGfYbmJez|T|mniU{bYDA>jhL$;ns$fI212Xf?m6JIyL=$^u4i|yfoJC#$IeSW zoyUDU&mV75IRhGt0v)N?0$OG0+xm^a}W zj(3L~WC1fnj)M;PXY{l@Q2NmDfU9L#1%KN@&|>iJX`mY4rSqa=ZxN#h=$1g2ZkbIk zmNH$Cwt!>jO;G<1)V}rTd>48putQJWQQVL_Y&kbjTcg2xAj0wJno_baS`Z(R!}VqIZX!CLIWLw*LiansCfW# zICP8^YRJ`CkO!g8>U2>t0C&1|K?6XbYhOLP+dx6tEz$v6Z)~ywd~MxBE%4oYpfCYd zzu;XQAu0hroi8=7b$)swq>CaAx~j>u+t&i@AyBY``l8@S@dR&wa#2CtaPA747V`nk z!@PW99sB!#H`I5XE-DqE4*yZmL=DJK;Kna#cCQn0#Va^eT)X*RFoJZ#;;aR{QwcOI z@Cv3G;Rr06kHkRc8o0|RsmWoM7d8U_Xi%TN66DPWg{s04Uuhp0sK znh123s1!hEz`lU5a01Qyfbzplu)i^5kw515|K>g5l)wOTa{zy<5<3I9^74R2KRDDe z($KYNRE-h*tp`EZTfx>bx85$%_2~BJ03X!s*m=Y705~5CIChF0gycg3$Ig(0huZ4Ju1pzz5p#w}38W^XS|IK6uopbB~GzXdzMO8n9-M z?i>{dP&jYb0f(~-|Mnj*R_lPK|G~3u?^zibIzNDC+Z@5uZO2#{7+kyAJiEid7lc-z z%(MNv!N!pG{TPD-f9rDaw44j*DpMDg3jXcad^$h+bVKR|P`D|)5Iy<-zY8d?+T zDxjsOoyS2{s~a-|gJ*XrgJ-v^1?WSQ2GCvPpi&QXTya8YiwbC|5vbY#(V(f<)&nm5E{9)S zybhZ3fk;Em0Idkm#G@E8{jD?ZGvzzCDN2kwG2GA^p zhvlKtr-lcb_kf+q;FEm3q{OlFpcDUg9zT!HQ;yx+f`3N=8bv;A+^g-0Y)y6B8cQkPqfXkj9x6w2N*3OelPC7-+C!==|4P&sg%((egKcPY5WHZ2_N) z?%4UkBl*8e=RKFsJ>W{sv-9|CMUT!L@J(ExyN?uJ)O-ic)c){jKF(zP1@NEF+lozU+zyH6?1D#Y3%fcY5z&5;IaU4?4gX=w* z^y^6;%{3|>|3OJ11ay)%q_leRryf!cf-^8EU_nXQqZ@LGFlc1`Hb_DD6!1;GApYrk z&~&V;11Ot-)Pu4HBwJXXD`xHd0L>K5E#R_%u^U2LLT<+`$${R0+v%cG@RIS*|No$+ zGW;$6e;{+MFJG+D00jjkt0LxHStdGy=UnfCGN}?=aXnbEk4grLN=v))M=$?^4jt%* zl{3)tryE-Sbo+qrLU&OKFg)YWBk z;0J#RI5G-$n}Fx~kc0wREDx8j1GN$YKv6fp4&<2-NJTdZ#A&WkN%+s-!Vg+D{1?36 z1QL?Ipqdk0xOi$_L15fLJPzwfRt2+ zJTyN!T3!T|R3|(bKY&UqSl#T{2~L^dCIY0Y>4dfu)`lWg6tJx_AVUKnjdLUuAQ~~M znrvhfI$cyE_*+4PNT9_UnjgT?4!R`^If+7J>E%)ITskB{82l?bYiw-&Su927UqD2fU}NwM<}C_#ft zmb7LUl>$akKcyhel8wK=3p97z4Jn9RI)8(fN`NjSbLox#-+8aM`mf;um)`1suT@+a zPlDsah4GMMCr=}&)Q#wb%m{l}9^-ETjlYAgBd`F;1c1^>giAM1W4F&y2A6J@CP!_a zL){@qSsb-P4zW0P9!{18pFIMzugZP#~8ix>}wuadoluQ7PbW%>|u^ z3yWL+);Q1tThJ+#Jk2kIkfap&TS3c7K(35%VLa3+()bc|!zV0ND3oq+WIP4(-b)!I zT}-7@KvjDHB(b!=1hwvAT3Gm7v%o!r8kGRBiR~{zt$Ua>6Mt(pXf}xPB*@MHmrkC> zmr@`Bs9Rb1TZ2Hed7y7bb)s6 z52JPNAqT2^9Q+~R!gv5OhXtQ6=?+m*==K45(MLrGH0-bO!t(sD|32N}0v_Gr9H8-i z9Z0E&-16|MMxPuFPQYNU(5jexf z09%g?S+4^+g%s>SP&52JXpo`1@dM~!%I=MzCNgxy#HV{9Xlx7=0H7m=UNAE-{J#L& zbIt*}cKm;ciiAgZH+VR^cQWWWo)`JDpoImCK|;ryL5KE$lDJ3r{zL$Z4;dt`_DC>pk;s5_VjyHqWe1Noq2UH<3hkU#i zDE&aMp#hz<;sM^}^M7Ih=z?86(0G}%0qA;l&?a*5^(*^8cQ*L+W?Q^=hUcHo6a3q{ zK}RP;#vKIOB0=3D9a~ z%fH3@JDp9y9)k^vg2x}5AM!i)dj525e#zm&?|HKGqgMAP&{*;1haTPBpq=`lxdYI_ zQK6t?@O(fAs^9!S8FX@1x3d9wq6b`lH6IXo>GB_RgaX*|687WH5{;k~cHp=(c!USj za&Wf+dK5&-BIrR3rFsp!K|56$O1RRRcZ2rmGL*LYbO(bLJDupf;P{P&OMt)S6{x)l zx;Jb>1LVjC{?_aNK>I$>*H2k=PXuk!^yoZo87RZwvyOoQbV3%WslmX%ed8g}MwRW3 zF8r;aLO0Fw7=JTpU!YHSvIl6-J^%LRBcK(lj9)yMiv!ZEn?XZd{LP-AE`RrAaL1za zCgcJOk6xBTkTa`YwOv$L9JNJM{!a!SW!CAUqQSp?GRPbc$Q5`Voi{ytSuQ|SyJ)+y zXp8-y3_2hUaw|=zi;B)m&|y`Oat9ij-OdL5t)P9mkozn_gJO^XwLlq-OPi3^yc2X< zJ_COXXfQ0Tc_(Nc9|M1jJZMJJ@>ubDpYFs6i02wXj`9R~t}r0Yx)JQTraed}zPK8K z*3y7?v3ENg`1EcD4J@=?;_n0PPXrwy0ZM_%Cpw)CT)K6-K)wXc@mO9h@`AdWzvVC} zn?X|GOTYjB|4)D>NBDgc$DyYXLxK@@c*g5~M1Fbi+AX5u*zKdj;?dm<3Q~`Q&zW68 zmkfbppnEcC7{Y_`7wCNGZXrj|88DYTI&c2J(0SB@c{ga~Bk1;^Zg-Y$apcf;H9XmQ zy!CAff42*$JNyzfPPQE6e$AiY8~8qf%z&ly?%kkN)EoXEat~?iCH{WU0#wL^E;#-B zbVK$%C(mvGttw9L2JIF1Wc=aSEdXjFx@cZ<)I8y8dAh{J1AJ1TC;$4(zWnPCdURg& z?L6pl@TWa!Ou?gf3Kytt<=@-F0irz){u1y6oiGFO&r5AkEQ0L=*J+@`k2+tzxN!`; zx9_DRxREm%TtX*zg52Se+zE0AD0OxVfKnVNVM2oul29#ABDv_I5C8guo}CwcIuC+f z10LmoxX2gNMXrYb|6c&5@0Zeuc`vm2+6DS|+fVXu|K`;zBH_XK19Y^JgG;wow*_d4u7yi?0Vr94 zn#GQqe>-bbLcDryK!pKAcNPmst%paih=ptCCl9Eh9*jR+x~)Jm8jhN;x-DF~lUN*g zfG$dN>AckKzyeyI6X2-%AG9prQS*okc=<}q3)7>&{=<~La_M~7dHjVEs?bly<1hG+ z{`%kf3a0L%i{>ZL(DsWTM}Gb9&QUP{Em8>Z>E-zfs-he_4|M(jbp|XzC(0jpVLaL^ za-dfv0Cd>_zsFI_L-i#d-N6B%Q8NutyVk>p8GHk$2Xi;bx1cr3pq2PO%)tTOj6TfZ z9sQ2X435l9%uFu55zLPK9)}P9U~=qa>~>^vWOiV2WOia84>+rAtpq`}$sE1?V!8{r4e29Zxn6;RlSX?_b z9XlOaUV?V-BF--Yr#cq??Gr)gJ$Q7UPP5(!F5;R&D-ODMg3hpZ>~&!5^=Gs^!QTwp zWsqhW?84tR3)Bxad;%&D-h=MP=zasL4ng?7#B)$S?Hpwn$Ze(m@JT5i+JBVu^Twe_S6zsIQ+ z93^ty%{M?{1nK7ZUi^N;5puI~>suFo&r=?~!4;rupg=*>32i$-ot)M=8B_;<1KTW6 z!k*T-8RV0+&ds2@3DkUsRBxcg2%yLVT|5tIUmS&2B(L{C>Pi0X&7e?Dvup-c?xo@` zoew%+xoAGpe8KN=$g=qfXdwo_&r|U61vmdsR$yjeaO^w?_47+}M7i2|2wd<-fX+LI zgezzb)i-bn2U?%f`Os1Gq9Mfh{-<7o4lqTUV4Q$f{#o#E-w5&w|Mo_ZM?E^HKxPU$ zPy2QrPwOmE(fbBI4V00;MJZSwW4I&PoMPe;(AfPIK){5I}^px=J zG)!~t%;ZRO?9Alz>@3vq?Tj=?bL|YYNb6(=A2q^w(1Y=UOSdBnIC*IcxM(}DKoSfr z#X`>3>OAP!dE`af0Z^WVOqn3kZYR47M9~Yk1E74(4xWTZZJ~hH6@X$AG!~`j(_L8M z!oPhbs3qvazkMO-Ksf&GE5VgOH~1J2kM7-|>I~Wr_2>rQBI?sU8kasmfJ z)9-(%jZcUnklwiArL<0g9iT?j%WP0gBf6gxx|v!JlybUs2O7AxUMfjMKEkyk*eAIW zbfSlA>w!8+pYBf3NnQTEEDrv?EC+qN9ey}kJ8;zN9RnXA&j2#0Qm(tPfti5;bnz0H zVcpom%)n5_e%w)_8+?Z8gyW79AnzmgFLWMI1-0uSchj`I1x+mXgW4gWk>T^8wm0bF zN6_>z|NcuZod=p97&QM-;BNs-4{~ z5p;aAOXq=uzc>#5;OLwPIy1Qwe3~+Ny-4#91O8U}~}eY2(p+0L=IB>~00E<$&=6Tn)du8vX~ZIdO30-#!&|CrD?AN`z;3 zFKEe`C;$Fq{M$_&9r?Gnf(BSMkM%nJx4g#h{K3WYAAi$6@N|AJXvL39=kM1-hy({3 zH31z`)_J4zZs)J&!;DHIj3uueJ6~GfE0%m|30j*54u|H$jF$I`^gO%4hIHQO`~_0@ z5_CD2V{ag%ORqC{D_1S(vMTVNEX#YvmmDo$^0#~fO;_fqD1ekXf>!rGWWU$EGWTf&`??5f%q6OF_-*W38Zr_88Mz50naGwD3HkF$A9C0WAf9 z#SUl*H8f^krvCf?e}YTr2}Y5Fprz6-mgkB;PH^nJ|1toa_)b7tIiQVm-697awM7n; zJaV=CS$5gA^Mq^XFIUYUUcD?A9h+Y;`Z8Yd>vcKE0cuw=3V@C-@U%Qo`t|in$78La z0{}se zyV*J~T3)E<==SHZJi+gK!lm1t$I0f+o~o^zC9}@a(R&0N>RL zI%~!7t!wN5lCrc3F8tfYK}!kC;yYjXbo+CF*I)Sbsx&)x^Qd_CI&!=ggrv_yjG%yX zw7gVe>e9{NVtKIkjZ1IV|Ly=5&x22yeHmZ6b_+Uc2eP_ej0h+LG-UGIufxpEO zQsjWfl0Zq)!l$5P={?PW1`Z9Q3{?%4d2(Wh5rEy%+@owqy> zK4kIl_2Cxq0iC&UNWhozf{*2?(vP5qw1WpTXxU4z&sqkLUekk3ybL~!w>)}fSA$r+ zvh$jF89W&;`t*wSHt{mF{x9`>osKBK920h%5<{$dg6z-gFa{H>rV z3~+Ss0yV-xT0rTKfBPKpavA>ZdsLP&FfhE>BL!L}-wI9~orj>l1f>I^|NsB@vg`$o z7{U}=-srUApW>pD@X{B4eu+<~#LE@nt`?{n!NB0rDe-a!65pr0L?xn^Wk1*{pi)1@ zqc?0;d3v&Hx3_A~KLWJv+e%HWj>(kpc~px~OD$bRwtHl7FBL zzL5%`$v#k3339(rFAF%idH0GKgX)wNzg`m|k4_JXPD`K8562xrOEUkvbS83mbOs9e zbQVf@bl&t~{OH>H#G~_ci72Gp^5_Je9V6hwc+kW0FerVxs5p2qyQlf2Xq79Hj*Ci0XN^jVPcP&uMxS2WswQ3r&~BCr-_9?to##BdBLqN2 zK__GZq)+EvaH+s}!=v-QN9SSR&IjP_6CYnp5(KXw1BE6iKAryl2d$d}&DnIii*!#> z0Uc&|@P$NYI7jys$P%4!o^Hqm_MPDZ{M)CffNSJ%36E~^4knLocK+?*VjTgD9^LHS z;UXOcAR!PVfZ3y){g?v_11M}jt*^9BSB7qP9!qzQdRA+9fjYKMcaBbX0Z`TA(R`H2 z!}2$OD`?YWca2JlOLvM&g=^B<};AehZZZWe=ZDgrplN z5I`;fEu_itIQW3YgBf(p`8Okf>)xN>?d+{v ze}WFe`LGK#WDeTg)GG#FzW`Fm;L+)pz~4F}HX(dn$g-+Ji>_}<|Z zko)}@;o$&s|8~$sH^{oqhy2?G4nAUjQOk^?VA_xW|9!gaK$8LNzTM>-9@z(YJbPu> zUVDQ~d%y~cf`^WsY%fe9%rwVNH~ zJel1EtOfX+LE|!>&Bu6rEI*fTczGH$Hz3adEjSx03>f%Z!a+K^V?gWhiX}X{BQzRn zR1z3nI+uVKYf2vQfGz}Ve(OS{l5pa6$av0fR;xd0qv&= zQAq*SH$9LTg_Rp74@7*hUb|Nr$LTst5Yy=p)H|9{!|`~Uxapfcg50%%1`=f@Wh{{Q+9s)##}y>Q(I zI>+u4$W*QWzd*?j79y{{|Nox`D|SG|SB6h_fdn*~Kykv~ng*I3DgfQy0!gi)UIi$9 z9AHAEMgCT=Z=m%yZV4{@+a-LuJv4l?Z}a#vo_;Ok*ewW}6?K{bTBUfPgoA%OLz-i! zBZp`6K^|Yr)8+Ra8+$?PQ$WkVU$T7r{~xKjirQaod;@YdyuAwEQhwY;1$^5ecmsrQ z=MhjUuyE--d#n+>`^y(JfjAw!Y_nFvrJLW;@}?ud+s)S7C9dEu-y_dnpB5HSBOF@) zHy>j0usl_w-p#}cI^4&Wfq{vk>?L?vwnyU;ko}M$G{;zQ(;9k>NGYFZ^Ip)f3j=@4 z50GumwHyq`TvQww_*)V|WpQ_?fG_COkZIt_(+i+Av?p6{m&&~S!Un2*8F~X5J(>@K zOHfbC6Z|bKpaHdRo1V^7mKG(C9KnMv`#}Y_OLrWL;8 z%I2mI<4xc0SPkD^nQlkRi~Mb6Yzz#Jy`KL;>$M%hcRXue^y#(f1(kP(Cqex+$8HgB zOA!uNe%E6j%?DXLEzg&}0WHjMZ8=aX{L-F{fdSI4XgchTL+07*#PM1H6duj6e%QqlJ>Ss4e88dD2z$#ET7UKz*=a4rZ2Dj-6~C&4&d*{Z1dt*QGN-8OZ^(g2AWTLBR09 zYdcu`szlkf+e5%n^P+F^Nyzaxn2TRQ3yvT@Z$6;lXnDL$%QKm$#j!hpr}bpzKF7|B zuG$_PulJ$Y0ooEf9lXD08ffPJSQ{wyGkUaMDlu#R&&b~bn%Qao&r}MYyRdkn8U~vE zp9ZR=K?T(DHjpMz!{f#5-QexEDIVR^KnWS#?tSqs6nrQ{ipTLbkRV9m%Xgsm$^>vS z<7a^+Gf?7+>0kj(2rxj`MYwbuxVC~# z#+nJ*;NHCsltNy5{rUfYLgz(S!vlu@J$qTYUNVAPm@r4bDBKLu_c9PPPuB~sT76VN z4KGAP3*H2K@fmcvN~bI69JUmYP5OWS{|9AIMwf2>m$9G{laL7;AtnfTb{^_>Q2`tB z>NjWw96xw*!pjd}x9I?vjg22FUsipcR9iKVR7V z`t=`l9!`Nruc$ydXmi?6(0I*@DQw_P$6&RfyRsW=K&PWIGJy9D^S6SIA@c0@mEhkV zqEeD(Ey&**4{{1<6u7M0M^-S1zZz1Uz^y#pkU!K z09jfC-sb-ie9j^~%w0fdA$EqSc!1;MMWHr$(|!hnXJ;#@sN`=29a9b3UIH3pay2~Q zYIxG8bBPM*yg|>-Ka2;NT~u9 zKAq3Ib5ufnx*<0EbpG?~Jpba!?_dAZnrl?b82DS-LDNHNvR{sQBr7oxuqO4LAZ?DkRdZ~^U&ErAD*tKk8VrZRBoc!2H;_UZiS z!oU8+3wJGeNVyj9x84PnVumNdihV%m7r*!D{0drye%kUde={R^e(f8`u_X*8mLP*1 zUbO!H^&jM{5>WninBmxY;ot)%7yk8!-FtZqe7ju>K;w}vmY|A&@DJ3wb^z1;QV z|9`^+FO7cv|8IB+bb`!*mpb5v^3NB=zkdDq?4Alr7@+k?ErGxPJ05qf02MW!$HB1( zVs?Z2m(a|Y`vaW$z{@!uJ6$t6KYMh(bLss1LgUx3|F5q?>aDO~(8?mnu4vF%_}5;n z`VQ(ElnQqTb97#8IM>kdw7&HlzstqWU=GN@8S)Axl>L?--QX4n^ri{exy{gq$59VZ zOJglKu4^Scx?MRCtql**vGkEgFH47G=dJEAmhXokHU1k028M&L1UwEtV)0-G^=*Sbc=U>NxmsQ< z(+Ab`E}$|vq=N-k-*j_Xa+Gj%a=;8ez~a$-hy`@A+Eb6_S^XQwq z_W`O^L5ISCdaCf$`eKthXru*n>Wxk7fl@Dz?mkc{-B1Z?$j<|HMY~-&d^=xu-g=?& z>i_?4aaY5WzMxYaKEAN{1}>;U+Jw8^I64nCoM~uyR^NJ?-{nxJ8wYr8-@_M^{K0jM z4f1K;hbMS|79Jja$m+p($`#b2aR;rC?DhN)^Jljg4;Bw9_*h;jeezNYJSzf9QlLSm z7Y?gIEmW|x!HZ`=^}XSx7cXDIofqf z!O0e!gh1=s__qi1Iqm^gNVI+{sr2X$m+1W9)4dwhK=tUn3F^6nsuc~7 z-W;Y69^K8LK?DBnp&b7wfF@DEYa&baJi3DwKuvRTKTvDHMMa}q95klX?aJWM>8$XA z;V&qsl;|}7`0v8+`oINz5;%PN5wc$zR6B!~2ferqULk*^F`46kJ*cnoAg!~Q4S8)Y zM7`mq7nLtT)eGqIvb7%F;3a}D)geIuTF;5R{Aoz|q5715XE}cg` zdPS{rc^N=!JbzvK_1~lOI5>d#K({_$0`*N?KK%lnXV*FrG*cVx{;3BWf2Ecdl{oTGJ>a5vu<=((an4dOr{!RY zP~$65r=aoC|NsB~^S9mu@5%!&$!zrIU;tmL>7!!N`nEzAv}Flo4|wf6$Zn{G0<8y1 zq&*ssfINoMk$|?BJi4nTJX-&kgnRUwCKT~9`1CFV?I#B{P9f>I`Iv~O<(Cq3kIqk^ zQ^wXTWMcp=7=7;1TLLpl(|k!RpSi_%fuqbe5=?bglt! zfN}vHS7_qVJsGt7-t*vN7N>3=Dc{a}jX!hK3)1*o>OfbD{wzo>D&TJcjVd+%1RYSv z-{Qv%S~uvTV#3J3y+*|(%^K{Gq7B^;W4nD+5Z!1ypbK&0>qT=hq zzb!_^->0_=bZO^n(Fq>Sha^0k53qPzUgU29jovwSbGWu#D&=$O)^crqTgujakkPS| z!?ophDZfj15{GN+6POri=`U}0l|bu%m`L+a=F)Yq%RuD<$k&WJAA-i=K{kO#_60%C z>0P37g@J*=@U2&`%`xzF0_aLM2L_MkV=Nxc$0a;1zwoz!4yA?$O1D3Y5923GFP_r7 zp!y*f)RYjj)GuXiKE&85*8GdP^eEKRpcDkU2O4y6B4}xj!>)?llniiwOgHfC`~hAY z20FZq7ql&``4>BXyE*74UuTZaW6jSP`CCBSNI^NB0W>RH0Xo$r6THtcM8(3R^X7{~ z>%qC1!=?|iJ|Ap{59rXoU7*MUuhIY|9#CB+4I0}%-n;|4oENdg7fBN+R#7yCLo}U$ zYBKzWSPzWqtacU#hHht$gKq`C9bqitXno7y+6i)LFYCTJpaGL+&@Cz+y{ruNU>+#^ zJ$hLeEdcXC^X(qJtR}m`JkTx19=)v3Ao@0dj$i%oaxQob1yY`Zi-oR#pu?q3`gAvg z8t2_YAZLSaa&84}>-Xqx2Blt~?%g0sr*0Pm9#AXu5NN9Oh3^MQF#=k~3fgeo{DZkn z)v@y^JU@ZjW6f__UTpdF>p$aB$L7DxM6&RY|GV*UbaQT5F<8c?ux1|qVI{$it_BGA{ zZ;b^t!aYBNx}D&x`f>xfE9Jrf&YPgyI(9x`Vqkdb2cO?K=Az=yxbsLm0|TT5@X{Ep zgTbeFH)v6~N9Rx9&L1zfeE>ICV?aFS$3e+CBrcJT4(y)G&-uALvj-E5!E zhoBSjKqt?^+ZCV%ekLzM@E9mc;K}xto&>~!05wx%G2_6k+e@Y*eoB$lP>(*gj_pB7+k=o z`+q3C3A)C~rL)!|cCh+)vcd$SwcuRmwZxN&Ap(0L4%VYelCqTsyXj3WJ z6TQvgT?9Mdfzx=)rQiSmzf1(3w)F~>CX2xBWd2rv(71HxO~Y?5Hmv#o|7F-8@NhHe z>LieN!DU3}WY89X7X?s*uK)i3A5_YSg3eMs1?uR65&<{`fV+5@iQq-3>~HWJv9M$FUq=2GWsu^|FOGW|K`oEw zV~j4A-%HOsg0gihJ4mke34beSO-Z*iNArV!oz5IDKmYpw-}e81Muu|9i!WX}L5^HZ z0L3YIjQOQDT!axa>ikmf-~a!hzT)=9pbFfhdo!p6bG-Zv97di8pRl}m^77YzPsT5u z2YoD`6~}{G_5c6>uXhATLbn@-=84t=bpnv_U764WF37{od;Pmuz4|o*DN5$er!^>a)Upj)hE-Dt?4ji4JLeoU^ z)axVNV709WN|<{q{&!Xjylev=?Hau+tVtp#~Bv+5lv*6>td_lJxfflWK zHrJ?dFz~l50>wwSiHhZC4}Q1L4SPWYWDKSDt=~!n9Xmf5Uh?St2_C>aG=q)7@-uj- z(W94VyWu6x&+wtfWi!}7H*ABiV*=eEdw4?Yw~|Y~-7YE|ogcyDmX6&b4V@zGpm9sk zOxTClTOj>V!%Ht3?|~}d(t|$TOF_+gsJmJ-Ky6?6{wr{M8rEHX`Qq;jkRJXP&>5pI zTR?rEkkD{&pH_id{=GCEw|}=y$K_uE!v39j7vy%*{L72(Ur_hmz^C)HN9PF_{%xJ0 zRcL9J6G5YyWhrScmW`lVzAOs9p0NQ`u!0t?^KZZ8)ys3xqgMp73X@TrsXK_p1+?7q zkmf~4&Qm3>j?E7l`CC8+xM&{gJji(wa(^oP+H8a9!=U@u!Ruoom1oJb;|}26KQ5i1 zd$kRs4^P+yy3Nd^*GEO8GekuLRGI0#STXk(s4&xjEg%GKD>(Rrsr6D?Co^P8p{wD6 zgFl$kI-Qx|COLMV>OAy%t7GS(*Bg)~K%lYh;n67w-r#o4r_+(c7gXedR#G~4H-Hvx zfIF49T@6oucI40ZNCA-%B_MJIs72h_=m44~=xzY@4LciMARN$&&(22hSybH(pr&JI zV+a#y+gJmr8RXH~=mFt@Cfq$b8zUgPK=ly6Ao#YW&c+JxQkw=)2=WWgTmc&T=xhYd zRCsnfIDF>MSKt?1SOXI64iNC@oY(`Zd>kY?8>fI;)!hxC-7lSu2@r$#fL6~nrZ6!u z@C&YNfQW$>0)l+e0g6-*V+N?9;n_W*gOPy sjFxA6;hPGExYSAeFFKoSk0rHK53 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

    %5_D2MWDW`<>&kc$ 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