Compare commits

...

332 Commits

Author SHA1 Message Date
gingerBill 2cca005056 Merge branch 'master' of https://github.com/odin-lang/Odin 2023-10-02 20:59:49 +01:00
gingerBill d27109640e Partial pseudo-revert 2023-10-02 20:59:43 +01:00
Jeroen van Rijn 1287e8c734 Merge pull request #2839 from Tetralux/aprintf-ally
[fmt] Add allocator parameter to `fmt.aprintf`
2023-10-02 11:23:26 +02:00
Tetralux 7a6ac3ea92 [fmt] Add allocator parameter to fmt.aprintf
This allows you to do `fmt.aprintf("Hello, %v!", name, allocator = ally)`.
2023-10-02 02:46:26 +00:00
Jeroen van Rijn 81fe93127d Make core:net test os.exit(1) on failure. 2023-09-30 22:47:49 +02:00
Jeroen van Rijn aa5716d3f9 Allow any order of query strings in net.join_url tests. 2023-09-30 22:36:50 +02:00
gingerBill f9c6f6856b Fix #2261 2023-09-30 20:32:24 +01:00
gingerBill b9cc2606f2 Remove default value 2023-09-30 20:26:52 +01:00
gingerBill 5023313c03 Minor cleanups to the core library 2023-09-30 20:26:04 +01:00
gingerBill 3e0fd63682 Fix or_break code generation issue 2023-09-30 18:58:28 +01:00
gingerBill 1f643b5816 Remove -vet-extra 2023-09-30 18:29:18 +01:00
gingerBill 14adcb9db8 Use or_break and or_continue where appropriate in the core library 2023-09-30 15:34:39 +01:00
gingerBill 41a22bd83d or_break and or_continue to core:odin packages 2023-09-30 15:09:59 +01:00
gingerBill 648b83d6ea Add or_break and or_continue constructs 2023-09-30 15:04:17 +01:00
Jeroen van Rijn 4e97b83312 Merge pull request #2832 from Kelimion/big_int_literal_hex
Change large math/big test literals to hex.
2023-09-30 11:30:31 +02:00
Jeroen van Rijn 07cd6cd670 Change large math/big test literals to hex.
In September 2022, the Python team addressed a possible DoS issue converting big integers to and from base 10 strings: https://github.com/python/cpython/issues/95778

Converting to/from base 10 is a quadratic operation, so they limited it to 4300 digits: https://discuss.python.org/t/int-str-conversions-broken-in-latest-python-bugfix-releases/18889/83

Github CI still uses an old Python version which parsed our test suite just fine. This patch converts them to hex literals to ensure our test doesn't break when Github does update to a non-vulnerable Python version released after September 2022.
2023-09-30 11:16:36 +02:00
gingerBill 3fae38a2f8 Correct get_file_line_as_string to fix #2829 2023-09-29 12:17:15 +01:00
gingerBill 23054138c2 Remove debug message 2023-09-29 12:12:14 +01:00
gingerBill 63f755554b Rename simd bitwise operations from intrinsics.simd_and to intrinsics.simd_bit_and etc 2023-09-28 16:42:08 +01:00
gingerBill 2ac463f003 Rename bitwise operations to bit_or etc 2023-09-28 16:40:01 +01:00
gingerBill 77227c2ff5 Merge pull request #2805 from odin-lang/llvm-17
Support LLVM 17.0.1
2023-09-28 16:01:26 +01:00
gingerBill 2afccd7fbd Revert llvm@17 to llvm@13 on macOS 2023-09-27 14:09:08 +01:00
gingerBill 991181104b Update CI macOS to use llvm@17 2023-09-27 14:06:51 +01:00
gingerBill 70aff9fbb2 Update src/build_settings.cpp
Co-authored-by: Laytan Laats <laytanlaats@hotmail.com>
2023-09-27 14:01:45 +01:00
gingerBill 2370884722 Merge pull request #2827 from Lperlind/fixup-bad-rand-merge
Fixed up missing output for rand
2023-09-27 11:45:00 +01:00
gingerBill c529b1b73a Generate the global type info member values even if the count is 0 2023-09-27 11:44:29 +01:00
gingerBill acc29fbceb Merge branch 'master' into llvm-17 2023-09-27 11:38:11 +01:00
Lucas Perlind 7cc5177078 Fixed up missing output for rand examples 2023-09-27 16:34:19 +10:00
gingerBill fc93ea7aa3 Fix #2820 2023-09-26 15:15:31 +01:00
gingerBill 4c22982732 Rename files to not start with _ 2023-09-26 13:15:21 +01:00
gingerBill fb935541c9 Fix #2809 - disallow files to start with _ 2023-09-26 13:10:18 +01:00
gingerBill 47023b2e6c Fix #2812 2023-09-26 13:04:47 +01:00
gingerBill f4a390201c Fix #2819 2023-09-26 13:02:40 +01:00
gingerBill d358ebd7e6 Potentially fix race condition #2463 #2814 2023-09-26 12:57:26 +01:00
gingerBill 9711dd1381 Fix #2816 2023-09-26 12:41:33 +01:00
gingerBill 4c328d83ba Fix #2817 2023-09-26 12:40:35 +01:00
gingerBill 9911b132d2 Fix #2818 (enforce #partial label: switch) 2023-09-26 12:35:24 +01:00
gingerBill 534e5978d8 Merge branch 'master' of https://github.com/odin-lang/Odin 2023-09-26 12:21:49 +01:00
gingerBill c08bf1204f Add cstring specific comparison procedures to fix comparisons like cstring("") != cstring(nil) 2023-09-26 12:21:43 +01:00
gingerBill 94d68c1f22 Fix ptr != ptr type cast problem in LLVM 17 2023-09-26 11:58:12 +01:00
gingerBill 0ca379ed03 Fix typo 2023-09-25 17:06:00 +01:00
gingerBill 0ed2d8b127 Merge pull request #2813 from mtarik34b/fix-mismatches-with-max-error-count-flag
Fix various mismatches with the specified -max-error-count flag
2023-09-25 16:44:05 +01:00
gingerBill 3bee571e1f Use giant struct only in 17 2023-09-25 16:43:28 +01:00
Tarık B 0b78544796 Fix various mismatches with the specified -max-error-count flag 2023-09-22 17:12:16 +02:00
gingerBill 361f71deed Use llvm_const_array wrapper 2023-09-22 15:35:24 +01:00
gingerBill 61f39ae0a0 Use a giant packed struct working for type info table 2023-09-22 15:32:32 +01:00
gingerBill 082324d7b9 Begin work on making the type info table be constantly initialized 2023-09-22 14:39:51 +01:00
gingerBill 5e99289d7a Minor clean up 2023-09-22 12:11:39 +01:00
gingerBill e14a4e79ae Merge pull request #2808 from karl-zylinski/write-128-bit-int-buf-size
Fix for crash when using io.write_u128/io.write_i128 due to buffer being too small
2023-09-22 11:38:07 +01:00
Karl Zylinski 39c85cafa2 Fix for crash when using io.write_u128/io.write_i128 due to buffer being too small 2023-09-22 08:26:41 +02:00
gingerBill fa6be4ec58 Revert build.bat 2023-09-21 17:27:17 +01:00
gingerBill 25b8461bfb Update LLVM-C.dll 2023-09-21 17:09:00 +01:00
gingerBill ac43dd0777 Remove debug text 2023-09-21 17:08:45 +01:00
gingerBill 963559676e Fix build times for -o:<string> in LLVM-17 2023-09-21 16:48:00 +01:00
gingerBill 20ce8c4c51 Allow for zero passes 2023-09-21 12:45:11 +01:00
gingerBill 098c09835b Add ODIN_SANITIZER_FLAGS global constant 2023-09-21 11:34:40 +01:00
gingerBill 4aa9d34b3d Add attributes for sanitize_memory and sanitize_thread 2023-09-21 11:20:13 +01:00
gingerBill 38d2a0ddb9 Add sanitize_address attribute to all normal packages 2023-09-21 11:13:26 +01:00
gingerBill 735bb147e2 Add asan lib for Windows 2023-09-21 11:03:25 +01:00
gingerBill 7a511308ef Re-configure the new pass system 2023-09-21 10:54:02 +01:00
gingerBill bc401fa392 Fix wrong import due to grep-replace 2023-09-21 10:41:42 +01:00
gingerBill 96fbafe359 Update ABI breaking changes for f16 types (due to LLVM 15+) 2023-09-21 10:38:44 +01:00
gingerBill e82b0ea4cd Add -o:aggressive for LLVM 17 2023-09-21 09:48:53 +01:00
gingerBill 2160484b62 Support -sanitize:<string> for address, memory, thread for LLVM 17 2023-09-21 09:40:33 +01:00
gingerBill f0ab58dfbb Begin work with adding the new pass system 2023-09-20 10:39:48 +01:00
gingerBill c23b5825bb Merge pull request #2804 from bytesiz3d/fix-unquote-string
Fix bug with index increment in `core:encoding/json.unquote_string`
2023-09-20 10:16:51 +01:00
Abdelrahman Farid f1872f495a Fix bug with index increment in unquote_string 2023-09-19 22:19:05 +03:00
Abdelrahman Farid 9ed36445b9 Add test for utf8 multibyte strings 2023-09-19 22:18:23 +03:00
gingerBill 5043c10d70 Check for LLVM versions 2023-09-19 16:21:34 +01:00
gingerBill e748d2f2af Update to LLVM-17 2023-09-19 16:15:26 +01:00
gingerBill ecde06e3a3 Merge branch 'master' of https://github.com/odin-lang/Odin 2023-09-19 15:12:50 +01:00
gingerBill 3505c1d790 Fix constant literals using the wrong type 2023-09-19 15:12:44 +01:00
gingerBill 150a72f75e Merge pull request #2769 from RLGingerBiscuit/json-marshal-stuff
json.marshal: Don't output spaces if pretty=false
2023-09-18 10:47:02 +01:00
gingerBill f96579824b Merge pull request #2791 from ftphikari/master
[core:sys/windows] Added couple of procedures
2023-09-15 11:22:30 +01:00
gingerBill 2aa3cabd85 Merge pull request #2782 from AbdelHameed-Hamed/dxc-unix-bindings
Add unix bindings for DXC.
2023-09-14 20:08:49 +01:00
AbdelHameed-Hamed 06d26df046 Move API into one file and use "system" calling convention, and move data definitions into platform specific files. 2023-09-14 19:24:44 +02:00
gingerBill 6e49b1cad7 Merge pull request #2784 from laytan/fmt-memory-sizes
Add formatting of bytes into the best unit of measurement
2023-09-14 11:00:48 +01:00
gingerBill d928f425ec Merge pull request #2789 from fabiansperber/fix-odin-parser
Fix issues with core:odin parser
2023-09-14 11:00:11 +01:00
gingerBill ed3a9aed12 Merge pull request #2790 from Lperlind/master
Further improve on NSBlock
2023-09-14 10:59:48 +01:00
hikari aaccaa19bf [vendor:directx/d3d11] Added CalcSubresource helper macro 2023-09-13 23:47:18 +03:00
gingerBill 35857d3103 Fix wrong type 2023-09-12 23:01:49 +01:00
Laytan Laats d47b0eeee7 update doc 2023-09-12 16:51:21 +02:00
Laytan Laats 287beaff35 use KiB etc. instead of KB 2023-09-12 16:49:42 +02:00
gingerBill 8e9d1c7ebf Make procedures contextless where possible 2023-09-12 11:52:05 +01:00
gingerBill 53380632a1 Swap order of prev and next 2023-09-12 11:44:54 +01:00
gingerBill 984a95b8c7 Update Tilde 2023-09-11 23:36:39 +01:00
gingerBill 72118fcc6a Fix #2794 (Fix typo for IsWindowState) 2023-09-11 16:14:28 +01:00
hikari 1b06f809de [core:sys/windows] Added SuspendThread 2023-09-08 00:02:27 +03:00
hikari 19fe508fb2 [core:sys/windows] Added couple of procedures 2023-09-07 23:58:19 +03:00
gingerBill aaaff9b66c Fix bug: Disallow non-specialized polymorphic in typeid assignment 2023-09-06 17:33:38 +01:00
gingerBill c660b43105 Merge branch 'master' of https://github.com/odin-lang/Odin 2023-09-06 16:55:50 +01:00
Lucas Perlind 92b24fd02d Further improve on NSBlock
* Correct setting the isa of the NSBlock
* Make global blocks managed by the odin runtime
* Make local blocks copy to a malloc block that is managed by the objc runtime
* Add method to create blocks that take a paramater
2023-09-06 15:03:17 +10:00
Fabian Sperber 886d0de040 Remove auto_cast from field_flags
- auto_cast is parsed as its own expression
2023-09-05 23:14:55 +02:00
Fabian Sperber 16d797cb01 Add #const field flag 2023-09-05 22:57:40 +02:00
Fabian Sperber bbf9678756 Fix parsing #force_inline call expression with or_return 2023-09-05 22:35:30 +02:00
gingerBill d60c619c44 Merge pull request #2785 from DanielGavin/odin-core-reverse
Add #reverse to `odin/parser`.
2023-09-05 18:57:08 +01:00
gingerBill e7abc05931 Merge pull request #2787 from laytan/fix-commonmark
fix commonmark import
2023-09-05 18:56:58 +01:00
Laytan Laats 12dd912ce9 fix commonmark import 2023-09-04 20:48:03 +02:00
DanielGavin 64a63b3879 Add #reverse to odin/parser. 2023-09-03 16:15:03 +02:00
Laytan Laats 93caf5b311 use memory formatting in tracking allocator doc 2023-09-01 22:05:04 +02:00
Laytan Laats aab2fa1af9 fix test case 2023-09-01 19:53:24 +02:00
Laytan Laats 4cf176de0b actually run the test 2023-09-01 19:51:53 +02:00
Laytan Laats 735cfcd290 Add formatting of bytes into the best unit of measurement 2023-09-01 19:17:07 +02:00
gingerBill 4aa4317c28 Merge pull request #2780 from laytan/fix-ternary-with-union-of-enum
fix #2779 ternary with a union of enum
2023-08-31 15:19:27 +01:00
AbdelHameed-Hamed d0ef6d2a9b Add unix bindings for DXC. 2023-08-31 11:50:29 +02:00
Jeroen van Rijn 434c84043d Merge pull request #2781 from Lperlind/master
Add more darwin bindings
2023-08-31 10:08:02 +02:00
Lucas Perlind 747116aeb0 Add more darwin bindings 2023-08-31 17:37:32 +10:00
Laytan Laats a182dc78f4 fix #2779 ternary with a union of enum 2023-08-31 02:31:11 +02:00
gingerBill 1a316c8a18 Merge pull request #2776 from Lperlind/master
Add more NS bindings and correctly link NS block
2023-08-30 01:48:06 +01:00
Lucas Perlind 46e7fa52b3 Add more NS bindings and correctly link NS block 2023-08-30 10:18:17 +10:00
Jeroen van Rijn 52ea3748b4 Merge pull request #2775 from laytan/fix-overlapped-entry-type
Fix the OVERLAPPED_ENTRY type definition
2023-08-29 10:56:01 +02:00
Laytan Laats 0a2678973b Fix the OVERLAPPED_ENTRY type definition 2023-08-29 10:44:21 +02:00
gingerBill 04129c5bd5 Update Tilde 2023-08-27 23:45:39 +01:00
Jeroen van Rijn 6f363dcae3 Merge pull request #2774 from Pix-xiP/master
Updating to be the correct function name in documentation.
2023-08-27 16:47:45 +02:00
Pix 8c4bd76280 Updating to be the correct function name in documentation. 2023-08-27 21:03:49 +08:00
Jeroen van Rijn 92f385e7b5 Merge pull request #2773 from Tetralux/minor-net-cleanup
[net] Assorted cleanup
2023-08-27 13:37:56 +02:00
Jeroen van Rijn ac4e259e29 Merge pull request #2771 from laytan/fix-queue-reserve
fix queue reserve always doubling in size when there is enough space
2023-08-26 19:23:17 +02:00
Laytan Laats 076b20a9a5 fix queue reserve always doubling in size when there is enough space 2023-08-26 19:09:04 +02:00
gingerBill 0b0230adce Update Tilde 2023-08-26 13:14:49 +01:00
Tetralux e51915a529 [net] Assorted cleanup
- Remove some old comments

- Fix some doc comments

- Improve some doc comments

- Unify name of the errors related to UDP packet sizes
   (i.e: recv buffer too small, and message too big to send)
2023-08-26 11:47:03 +00:00
RLGingerBiscuit 187a475b84 json.marshal: Don't output spaces if pretty=false 2023-08-25 17:33:41 +01:00
gingerBill 39c0a619eb Merge pull request #2767 from Lperlind/master
Correct run loop linking
2023-08-25 11:20:07 +01:00
Lucas Perlind 29f7eaad78 Correct run loop linking 2023-08-25 13:46:03 +10:00
gingerBill 8f086a6957 Add NSSet 2023-08-24 23:31:21 +01:00
gingerBill 8f512001b6 Shut up the type checker 2023-08-24 16:49:56 +01:00
gingerBill 1d25522a3b Update vendor:darwin/Foundation to implement Event, Color, Screen, and other fixes 2023-08-24 16:43:13 +01:00
Jeroen van Rijn fdb538538a Merge pull request #2765 from Despacito696969/master
Commit `a040be9` but for `core:sort`
2023-08-23 16:24:59 +02:00
Despacito696969 2feb1bf847 Commit a040be9 but for core:sort 2023-08-23 15:46:32 +02:00
Jeroen van Rijn 74bbb1167f Fix #2763
Fixes #2763
2023-08-22 20:18:54 +02:00
gingerBill 515163864f Add optional flush := true to many of the core:fmt procedures 2023-08-22 17:24:12 +01:00
gingerBill 1cdb975c91 Add attribute @(require) import "foo" to replace/supplement _ :: foo 2023-08-22 12:05:25 +01:00
gingerBill cd42d26eb3 Fix variadic parapoly bug 2023-08-21 12:19:38 +01:00
gingerBill 8bc96652cd Merge branch 'master' of https://github.com/odin-lang/Odin 2023-08-21 11:15:22 +01:00
gingerBill 1631a2bac1 Update Tilde 2023-08-21 11:15:16 +01:00
Jeroen van Rijn 501635ca26 Merge pull request #2760 from Lperlind/cocoa-import
Always include Cocoa for NSFoundation
2023-08-21 07:20:35 +02:00
Lucas Perlind edcd335b90 Always include Cocoa for NSFoundation 2023-08-21 11:36:39 +10:00
gingerBill 0cb9908f27 Update Tilde 2023-08-19 12:26:59 +01:00
gingerBill 61858f5899 Merge pull request #2755 from Lperlind/improve-float-rand
Better guarantee boundaries of floating point rand
2023-08-19 11:07:28 +01:00
Jeroen van Rijn c5911679d1 Merge pull request #2757 from Kelimion/fix_2756
`_buffer_grow`: Preserve allocator if already set via init_buffer_allocator
2023-08-18 22:27:03 +02:00
Jeroen van Rijn 99d6a077fe _buffer_grow: Preserve allocator if already set via init_buffer_allocator
Fixes #2756
2023-08-18 22:16:59 +02:00
Lucas Perlind 8b680254ee Better guarantee boundaries of floating point rand 2023-08-18 11:19:01 +10:00
gingerBill b873651da7 Merge pull request #2748 from Caedo/js-events-fix
Fix issues with js events not being initialized properly
2023-08-17 16:40:54 +01:00
Caedo b185d9e701 Remove pointer magic when creating strings 2023-08-16 20:33:17 +02:00
Jeroen van Rijn b635622cac Merge pull request #2751 from Lperlind/rand-doc-float
Update rand documentation about floats
2023-08-16 13:48:01 +02:00
Lucas Perlind b31d8b1ad0 Update rand documentation about floats 2023-08-16 21:13:56 +10:00
gingerBill 2153cb7e0a Merge pull request #2721 from Kartoffelsaft/dynamic-pool-alloc
Return .Invalid_Argument in pool allocator to avoid potential segfaults
2023-08-16 12:02:21 +01:00
gingerBill 15033eab28 Fix comparison of two nil unions against each other 2023-08-16 11:52:40 +01:00
gingerBill 8b4c530062 Disable HAS_VALGRIND logic for BlockingMutex (fixes #2703) 2023-08-16 11:02:09 +01:00
gingerBill 9ff9587b7b Remove unused code in gb.h; Minimize use of heap_allocator() in parser 2023-08-16 00:41:49 +01:00
gingerBill d8acbda548 Update to llvm@13 for Mac
Brew has broke llvm@11
2023-08-15 21:25:14 +01:00
Benjamin Findley 7e4a65114a fix whitespace 2023-08-15 08:49:27 -07:00
gingerBill d9a2d29d00 Update demo.odin to #align(N) style 2023-08-15 15:59:38 +01:00
gingerBill 27931249ce Scale by 3/2 rather than 5/4 2023-08-15 15:45:12 +01:00
gingerBill 52318d0e0e Improve heuristic for committing memory with virtual.alloc_from_memory_block 2023-08-15 15:42:28 +01:00
gingerBill 8d673789be Align committed to a page size 2023-08-15 15:20:23 +01:00
gingerBill 646c4c7458 alloc_from_memory_block to commit amounts equal to multiples of the DEFAULT_PAGE_SIZE 2023-08-15 15:12:12 +01:00
gingerBill 2cc22d118d Require parentheses for #align(N) 2023-08-15 14:55:02 +01:00
Caedo 1182f41f99 Fix issues with js events not being initialized properly 2023-08-15 14:56:04 +02:00
gingerBill 098d1d2b5e Merge pull request #2716 from laytan/add-libraygui-macos-arm64
add libraygui.a for macos-arm64
2023-08-15 11:19:20 +01:00
gingerBill 31c85f0ec5 Merge pull request #2719 from laytan/add-waitgroup-to-wait-proc-group
add wait group to wait proc group
2023-08-15 11:19:09 +01:00
gingerBill 091d1f8c75 Merge pull request #2747 from Pix-xiP/loc-into-strings
#caller_location into the strings package
2023-08-15 11:16:12 +01:00
gingerBill 6c50e6ef34 Use or_return on resize/reserve 2023-08-15 11:13:43 +01:00
gingerBill 67f48aca96 Fix _random_u64 2023-08-15 11:06:12 +01:00
gingerBill fc64e787a3 Change to LLVM@13 for ci.yml on Mac 2023-08-15 10:55:37 +01:00
gingerBill d13bed9a0a Change algorithm to work on 64-bit integers rather than 32-bit integers internally 2023-08-15 10:53:59 +01:00
gingerBill 904c48b11a Fix range comment from (0, n] to [0, n) 2023-08-15 10:36:00 +01:00
Pix 2ab5eb7213 Strings makes added caller function 2023-08-15 12:31:06 +08:00
Pix 5ce541e9ef Intern add location to init. 2023-08-15 12:30:50 +08:00
Pix 0cf9c22033 Builder makes added caller location 2023-08-15 12:30:40 +08:00
Benjamin Findley 38e06f13d6 prevent potential segfaults when using large allocations from dynamic pool 2023-08-11 11:49:31 -07:00
Laytan Laats ccc94f6832 add wait group to wait proc group 2023-08-11 20:21:42 +02:00
gingerBill 589820639c Correct lb_run_function_pass_manager behaviour 2023-08-10 14:35:09 +01:00
Laytan Laats 68b9260c9b add libraygui.a for macos-arm64 2023-08-09 00:36:21 +02:00
gingerBill 49b2447113 Merge pull request #2710 from guifes/raygui
raygui bindings
2023-08-08 16:13:51 +01:00
gingerBill 89c50bbd82 Adhere to -vet-style 2023-08-08 16:01:22 +01:00
gingerBill 2b3f3e11d3 Make trailing commas followed by a closing token on the same an error with -vet-style 2023-08-08 16:01:08 +01:00
gingerBill 4100cfec86 Fix typo 2023-08-08 15:31:17 +01:00
gingerBill cad3a50e4e Add ODIN_PLATFORM_SUBTARGET 2023-08-08 15:28:21 +01:00
gingerBill 4d9ee55468 Fix add_constant_switch_case 2023-08-08 15:23:01 +01:00
gingerBill b72f009d87 Disallow aliasing of any and typeid 2023-08-08 15:10:57 +01:00
gingerBill 2181e0fc27 Make for init; ; {} an error without an explicit cond or post 2023-08-08 15:07:00 +01:00
gingerBill cd74cdfdaf Remove switch in in favour of switch _ in 2023-08-08 14:57:25 +01:00
gingerBill 49ab935ae9 Disallow for in in favour of for _ in 2023-08-08 14:56:12 +01:00
Guilherme Fernandes 6879c9d8df Tabs for identation and spaces for aligment 2023-08-08 13:22:26 +01:00
gingerBill 939bf4bb5d Add experimental -subtarget:ios 2023-08-08 11:35:51 +01:00
gingerBill 7861dfd667 Fix tilde extension when trying to build as assembly (unsupported currently) 2023-08-08 11:16:14 +01:00
gingerBill c5fc28de7d Merge pull request #2714 from wjlroe/fix-cycle-count-intrinsic-on-darwin
Fix read_cycle_counter intrinsic on arm64
2023-08-07 23:18:55 +01:00
Guilherme Fernandes 535d290293 Removing contextual comment 2023-08-07 22:35:30 +01:00
Guilherme Fernandes a0dd975686 Adjusting identation 2023-08-07 22:35:30 +01:00
Guilherme Fernandes f48531efaf Removing unecessary line
Not sure what the context is for it, grabbed it from raylib's bindings. Tested without it, everything works fine.
2023-08-07 22:35:30 +01:00
Guilherme Fernandes c6a4116082 Fixing return value missing 2023-08-07 22:35:30 +01:00
Guilherme Fernandes aecd6b85e6 Improving style
minValue: c.int, maxValue: c.int
minValue, maxValue: c.int
2023-08-07 22:35:30 +01:00
Guilherme Fernandes 55439ef293 Fixing minor typo: minValu -> minValue 2023-08-07 22:35:17 +01:00
Guilherme Fernandes d4cf103676 Adding whitespaces to detach procedure declaration from category comments 2023-08-07 22:26:19 +01:00
Guilherme Fernandes 489fb087a4 Fixing identation to use tabs 2023-08-07 22:26:18 +01:00
Guilherme Fernandes ff904ae174 Fixing Error: Redeclaration of 'VERSION' in this scope 2023-08-07 22:26:18 +01:00
Guilherme Fernandes d8db5ec7b6 Moving raygui to vendor/raylib
Removing raylib import and raylib package references
2023-08-07 22:25:04 +01:00
William Roe 5d8b78cb88 Fix read_cycle_counter intrinsic on arm64
Running this code with the hard-coded x9 register results in not 
returning the cycle count, but some other value.

This code (using $0 as the register), works on arm64 Linux and Darwin.
2023-08-07 21:18:56 +01:00
gingerBill 9736402dfd Fix docs typo 2023-08-07 15:34:28 +01:00
gingerBill 0600054ad4 Remove temporary assert 2023-08-07 15:21:18 +01:00
gingerBill b782fca75b Fix using bug 2023-08-07 15:18:45 +01:00
gingerBill 0230b88078 Tilde: #soa pointers 2023-08-07 15:11:15 +01:00
gingerBill 55c9fb7c5c Tilde: Begin work on #soa 2023-08-07 15:04:03 +01:00
gingerBill 8201a9ce6e Tilde: for in for enum types 2023-08-07 14:53:31 +01:00
gingerBill 561a94cc50 Tilde: Fix type info for enums 2023-08-07 14:50:06 +01:00
gingerBill 0636887931 Tilde: Add in/not_in for maps 2023-08-07 14:43:11 +01:00
gingerBill 0c1b39d881 Mock out map get/set functionality 2023-08-07 14:40:42 +01:00
gingerBill 67ffae7e32 Merge pull request #2655 from hchac/stdlib-parser-fixes
Match C++ parser allowing named arguments after variadic
2023-08-07 11:45:14 +01:00
gingerBill 488a38a96d Merge pull request #2649 from hchac/allow-newline-field-list-separator
Match C++ parser behavior in allowing newlines before a closing brace.
2023-08-07 11:45:08 +01:00
gingerBill 77e5854a16 Merge branch 'master' into stdlib-parser-fixes 2023-08-07 11:02:01 +01:00
gingerBill 2a42dab108 Merge pull request #2661 from Beefster09/fixed-f64-conversion
Fix conversions between fixed point numbers and f64
2023-08-07 11:00:42 +01:00
Guilherme Fernandes 092d103d24 Adding raygui bindings
Including binaries for Windows only at the moment.
2023-08-07 09:44:55 +01:00
gingerBill 12b7df550f Merge pull request #2701 from Alkamist/nanovg-leak-fix
Fix small memory leak in nanovg.
2023-08-05 17:07:35 +01:00
gingerBill 006bd2fe17 Merge pull request #2696 from hwchen/hwchen/fix-parse-call-expr-ellipses
core:odin/parser allow args after varargs in parse_call_expr
2023-08-05 17:07:28 +01:00
gingerBill d252768ac5 Merge pull request #2652 from ftphikari/master
[vendor:directx/d3d_compiler] Added default include file handler
2023-08-05 16:59:43 +01:00
gingerBill dd7c2c0574 Update demo for #relative multi-pointers 2023-08-05 16:09:19 +01:00
gingerBill c91898a888 Remove #relative slices; Replace with #relative multi-pointers 2023-08-05 16:05:39 +01:00
gingerBill afa8eb2d6f Fix #2699 2023-08-05 15:04:14 +01:00
gingerBill 1481015dc4 Fix #2690 2023-08-05 15:01:21 +01:00
gingerBill 8cdedd4cd2 Add raw_data(^matrix[R, C]T) -> [^]T 2023-08-05 12:35:27 +01:00
gingerBill 985e4eed60 Fix #2697 2023-08-04 16:00:10 +01:00
gingerBill 9d0583e0d2 Add missing import 2023-08-04 15:57:50 +01:00
gingerBill 9aed26a234 Remove the use of import within when 2023-08-04 15:54:44 +01:00
gingerBill 3323d5c76c Disallow import declarations within a when statement 2023-08-04 15:45:25 +01:00
Walther Chen 4b9afd787c core:odin/parser allow args after varargs in parse_call_expr 2023-08-03 22:45:21 -04:00
Alkamist cedf01d094 Fix small memory leak in nanovg. 2023-08-03 18:36:12 -04:00
gingerBill 4a71603a77 Add hasher proc generation 2023-08-03 14:46:22 +01:00
gingerBill aadc8477b9 Generate equal proc for unions 2023-08-03 13:42:14 +01:00
gingerBill 9bf111bd3d Add comments for tilde building 2023-08-03 13:26:42 +01:00
gingerBill 8060da2132 Toggle tilde backend in the build script 2023-08-03 13:16:23 +01:00
gingerBill b495a302b0 Merge branch 'master' into tilde 2023-08-03 13:14:09 +01:00
gingerBill c39a360372 Update Tilde for the new TB_Passes approach 2023-07-28 14:57:04 +01:00
gingerBill f6d1724835 BODGE for finding procedure symbols
Related to a dependency graph race condition bug (THIS NEEDS TO BE FIXED)
2023-07-28 12:12:06 +01:00
gingerBill 0f217c715e Fix dependency issue; Allow polymorphic procedures in tilde 2023-07-25 15:15:35 +01:00
gingerBill c4033c215e Support non-constant global slices 2023-07-25 14:37:19 +01:00
gingerBill e914d551e7 Basic support for global variables 2023-07-25 13:56:28 +01:00
gingerBill c6e4b8ed5c Move mutable value decl stuff to a separate procedure 2023-07-25 13:49:19 +01:00
gingerBill ab398f3704 Implement @(static) local variables 2023-07-25 13:46:40 +01:00
ftphikari 699aec331d Merge branch 'odin-lang:master' into master 2023-07-25 15:32:18 +03:00
gingerBill baea6a1da8 Generate anonymous procedure literals 2023-07-25 13:31:22 +01:00
hikari d2375a79f2 [vendor:directx/d3d11] Added missing UUIDs for shader reflection 2023-07-25 14:42:08 +03:00
gingerBill ba48093666 Fill out type information data 2023-07-25 12:19:59 +01:00
gingerBill d4b87f1672 Continue filling in the global type info data 2023-07-25 11:46:53 +01:00
gingerBill e4006eb583 Update tilde 2023-07-25 01:11:57 +01:00
gingerBill b934e4b564 Implement basic runtime type information
This allows for `runtime.println_any` to work!
2023-07-25 00:33:43 +01:00
gingerBill 28c97a9467 Begin work on setting up type information table 2023-07-24 17:12:23 +01:00
gingerBill 28fca190ee Fix transmute(uintptr)ptr etc 2023-07-24 16:09:01 +01:00
gingerBill 78116e0ea2 Implement for in statements for array-like values 2023-07-24 15:46:54 +01:00
gingerBill 5a50afa1fd Implement for in interval statements 2023-07-24 15:28:51 +01:00
gingerBill cf77a0e2b4 Update Tilde to fix reg alloc bug 2023-07-24 15:18:20 +01:00
gingerBill e2593a6883 Update Tilde for testing reg spill stuff 2023-07-24 14:01:10 +01:00
gingerBill 00a44d1ddb Mock out type info initialize stuff 2023-07-24 13:06:01 +01:00
gingerBill d8445fd9df Multithread tilde backend 2023-07-24 12:53:16 +01:00
gingerBill 304db907f5 Generate object name for them module 2023-07-24 12:19:22 +01:00
gingerBill b09cdc0f25 Hook up Tilde to the linker code 2023-07-24 12:01:23 +01:00
gingerBill bd81c6f5b4 Move linker code into separate file 2023-07-24 11:53:18 +01:00
gingerBill 4051dd9522 Update Tilde to get basic "Hello World" working with runtime.print_string 2023-07-24 11:30:07 +01:00
gingerBill 360cb9eb9a Add tb.lib to build.bat 2023-07-24 10:28:56 +01:00
gingerBill 241a939c29 Update Tilde 2023-07-24 10:27:55 +01:00
gingerBill 2f9c5d2d0b Minor clean up to builtin procs 2023-07-23 22:07:21 +01:00
gingerBill 99c812b02d Begin working on a minimum build 2023-07-23 21:44:50 +01:00
gingerBill d82c2ce50f Update Tilde; Add min and max 2023-07-22 12:21:29 +01:00
gingerBill 6c12156b1a Simplify procedure argument handling 2023-07-22 11:16:29 +01:00
gingerBill eec3b3009f Begin work on builtin procedures 2023-07-22 10:16:28 +01:00
gingerBill 4654b41c3e Implement call expressions 2023-07-22 09:06:44 +01:00
gingerBill b09ea17f0e Support multiple return values for non-odin calling conventions 2023-07-22 08:48:13 +01:00
gingerBill 99ebfc337e Support multiple return values 2023-07-22 08:33:30 +01:00
gingerBill e5f9458905 Update Tilde to get procedure passing rules 2023-07-22 07:56:13 +01:00
gingerBill ec0a9a5f8a Copy lvalues on multi-valued assignments to allow for a, b = b, a on large types (minor bodge) 2023-07-21 13:05:39 +01:00
gingerBill 47b924990f Count extra stuff 2023-07-20 02:04:59 +01:00
gingerBill 215bebb01a Remove dead code 2023-07-20 02:00:20 +01:00
gingerBill 9fffa19c51 Mock out more global stuff 2023-07-20 01:58:46 +01:00
gingerBill b54f3d4ee9 Mock out more global value stuff 2023-07-20 01:54:36 +01:00
gingerBill bcdcad5847 Add global string constants 2023-07-20 01:24:19 +01:00
gingerBill 737b8e42e4 Global constants for arrays 2023-07-20 00:48:52 +01:00
gingerBill c61e7c05da Begin working on global constants 2023-07-20 00:34:24 +01:00
gingerBill a919828003 Add complex and quaternion global stuff 2023-07-19 23:27:06 +01:00
gingerBill 0bd33882b6 Basic constant compound literal support 2023-07-19 21:43:42 +01:00
gingerBill e0e55a649c Rename tilde_backend* files to tilde* 2023-07-19 20:50:15 +01:00
gingerBill f32d71eca0 Mock out any type switch statement 2023-07-19 20:44:37 +01:00
gingerBill 5fb98609cd Implement type switch statement for unions 2023-07-19 18:03:42 +01:00
gingerBill 19633ece80 Simplification of the ValueDecl code 2023-07-19 15:51:56 +01:00
gingerBill fb04103352 Add defer statements; add implicit context pointer to context stack 2023-07-19 15:37:33 +01:00
gingerBill 9abf43b0d2 Mock out defer handling logic (before handling defer statements) 2023-07-19 15:24:07 +01:00
gingerBill 7f97274ecc Wrap Tilde's goto pseudo-instruction 2023-07-19 14:31:32 +01:00
gingerBill b2edab193f Support branch statements break/continue/fallthrough 2023-07-19 14:19:01 +01:00
gingerBill 184563bbe1 Add trivial switch statement check to use a jump table 2023-07-19 13:58:56 +01:00
gingerBill 73f25ed182 Add basic switch statement
Implement as naive if-else chain
2023-07-19 13:37:56 +01:00
gingerBill 533f6a552c Add for and += assignments 2023-07-19 13:15:13 +01:00
gingerBill 32ac319525 Implement if statements 2023-07-19 12:55:44 +01:00
gingerBill 569397bd7e Update TB 2023-07-19 11:39:37 +01:00
gingerBill 3535d16c3a Implement Ternary If Expression 2023-07-18 18:58:56 +01:00
gingerBill 7f4efa90c8 Mock out cg_emit_comp 2023-07-18 16:51:37 +01:00
gingerBill bab3cd988e Mock out cg_emit_unary_arith 2023-07-18 13:42:37 +01:00
gingerBill feda213c0c Mock out cg_append_tuple_values 2023-07-18 13:30:59 +01:00
gingerBill c6593e8cde Mock out binary expressions and variable declarations 2023-07-18 13:27:47 +01:00
gingerBill 4d8d3919c0 Update tilde; procedure type determination from debug types 2023-07-18 13:16:35 +01:00
hikari 20dc8b222d [vendor:directx/dxgi] Removed GetDebugInterface
Since Windows 8.1 `DXGIGetDebugInterface1` is present, which eliminates the need for `GetDebugInterface`. Odin does not support Windows versions that Microsoft doesn't support, so anything Windows 7 and earlier is basically useless anyway.
2023-07-18 02:35:05 +03:00
gingerBill 55733171c1 Planning for multi-valued expressions in the tilde backend 2023-07-17 23:16:50 +01:00
gingerBill 988926b59d Flesh out debug procedure type 2023-07-17 22:51:18 +01:00
gingerBill d72f8da6d7 Move debug type code its own file 2023-07-17 22:37:40 +01:00
gingerBill 0b697b24bd Implement debug type for procs 2023-07-17 22:33:13 +01:00
gingerBill b2c75dc3a2 Mostly fill in cg_debug_type 2023-07-17 22:18:15 +01:00
gingerBill b5b3f1fb42 Mock out struct_ep calls 2023-07-17 17:28:12 +01:00
gingerBill bd73834e19 Update Tilde; mock out cg_build_return_stmt
128-bit types are broken
2023-07-17 16:56:10 +01:00
gingerBill 7f43c24297 Merge branch 'master' into tilde 2023-07-17 16:23:01 +01:00
hikari 6ac2c5c6dc [core:sys/windows] Added a couple of procedures 2023-07-17 02:40:49 +03:00
gingerBill 45b3ae31af Mock out more of the ep procedures 2023-07-17 00:31:44 +01:00
gingerBill 66a20264ab Mock out cg_emit_arith 2023-07-17 00:06:03 +01:00
gingerBill d2d243cca8 Mock out cg_emit_conv 2023-07-16 23:41:51 +01:00
Justin Snyder d4194962b0 Update fixed.odin 2023-07-15 23:43:14 -06:00
gingerBill ee8372145d Begin working on proper expressions 2023-07-15 14:26:47 +01:00
gingerBill ccb736411b Basic context creation 2023-07-15 13:30:31 +01:00
gingerBill e2e5641a45 Update TB; Fix calling nullptr TB_Node* problems 2023-07-15 13:15:50 +01:00
ftphikari 7ca0b256eb [core:sys/windows] Added missing MONITORINFOEXW type 2023-07-14 23:02:56 +03:00
gingerBill ca442defbb Mocking out call related stuff 2023-07-14 17:34:00 +01:00
gingerBill b17ebeb6f6 Mock out more of the addr related stuff 2023-07-14 17:03:28 +01:00
gingerBill a8afcf1ca9 cg_emit_load/cg_emit_store 2023-07-14 16:03:21 +01:00
gingerBill 6545cc2d48 Stub out expr and const files 2023-07-14 14:54:49 +01:00
gingerBill 2a10c8fe5c Begin work on building statements 2023-07-14 13:01:17 +01:00
gingerBill 7cd2d14b64 Very start of working on Tilde Backend for Odin 2023-07-14 11:58:18 +01:00
gingerBill fc5abfd68b Update Tilde 2023-07-14 11:56:13 +01:00
hchac cb5c821989 Matching C++ parser changes from commit 67ca9166d3.
Without these changes the core library parser fails to parse:

 - core/fmt/fmt.odin:

     Line 126 (and others):
       sbprint(&str, ..args, sep=sep)

 - core/fmt/fmt_os.odin:

     Line 17 (and others):
       return wprint(w, ..args, sep=sep)

 - core/log/log.odin:

     Line 79 (and others):
       logf(.Debug,   fmt_str, ..args, location=location)

 - core/runtime/core_builtin.odin:

     Line 475 (and others):
       return append_elems(array, ..args, loc=loc)
2023-07-13 15:38:10 -04:00
ftphikari ab7652010b [vendor:directx/dxgi] Rename debug_interface_init to InitDebugInterface 2023-07-13 17:41:21 +03:00
ftphikari 7990566f6b Code review fixes 2023-07-13 17:16:32 +03:00
ftphikari b6baee5f77 [vendor:directx/dxgi] Added GetDebugInterface 2023-07-13 02:11:46 +03:00
ftphikari 24c3ec235a [vendor:directx/d3d_compiler] Added default include file handler 2023-07-12 00:56:01 +03:00
hchac 4c0e9f1f89 Match CPP parser behavior in allowing newlines before a closing brace. 2023-07-11 16:15:06 -04:00
gingerBill 8ebb84ad1e Basic global struct example 2023-07-08 13:02:17 +01:00
gingerBill f0e77a309d Hellope World! with Tilde 2023-07-08 12:43:20 +01:00
gingerBill 7ab531bd21 Add -tilde for working on the new compiler 2023-07-08 12:07:11 +01:00
gingerBill d7af6de9b9 Add tilde 2023-07-08 11:54:44 +01:00
219 changed files with 22907 additions and 4292 deletions
+2 -2
View File
@@ -58,8 +58,8 @@ jobs:
- uses: actions/checkout@v1
- name: Download LLVM, botan and setup PATH
run: |
brew install llvm@11 botan
echo "/usr/local/opt/llvm@11/bin" >> $GITHUB_PATH
brew install llvm@13 botan
echo "/usr/local/opt/llvm@13/bin" >> $GITHUB_PATH
TMP_PATH=$(xcrun --show-sdk-path)/user/include
echo "CPATH=$TMP_PATH" >> $GITHUB_ENV
- name: build odin
+2 -2
View File
@@ -69,8 +69,8 @@ jobs:
- uses: actions/checkout@v1
- name: Download LLVM and setup PATH
run: |
brew install llvm@11
echo "/usr/local/opt/llvm@11/bin" >> $GITHUB_PATH
brew install llvm@13
echo "/usr/local/opt/llvm@13/bin" >> $GITHUB_PATH
TMP_PATH=$(xcrun --show-sdk-path)/user/include
echo "CPATH=$TMP_PATH" >> $GITHUB_ENV
- name: build odin
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
+11 -1
View File
@@ -80,6 +80,16 @@ set libs= ^
Synchronization.lib ^
bin\llvm\windows\LLVM-C.lib
rem DO NOT TOUCH!
rem THIS TILDE STUFF IS FOR DEVELOPMENT ONLY!
set tilde_backend=0
if %tilde_backend% EQU 1 (
set libs=%libs% src\tilde\tb.lib
set compiler_defines=%compiler_defines% -DODIN_TILDE_BACKEND
)
rem DO NOT TOUCH!
set linker_flags= -incremental:no -opt:ref -subsystem:console
if %release_mode% EQU 0 ( rem Debug
@@ -104,4 +114,4 @@ if %release_mode% EQU 0 odin run examples/demo
del *.obj > NUL 2> NUL
:end_of_build
:end_of_build
+13 -31
View File
@@ -118,9 +118,7 @@ reader_peek :: proc(b: ^Reader, n: int) -> (data: []byte, err: io.Error) {
b.last_rune_size = -1
for b.w-b.r < n && b.w-b.r < len(b.buf) && b.err == nil {
if fill_err := _reader_read_new_chunk(b); fill_err != nil {
return nil, fill_err
}
_reader_read_new_chunk(b) or_return
}
if n > len(b.buf) {
@@ -156,9 +154,7 @@ reader_discard :: proc(b: ^Reader, n: int) -> (discarded: int, err: io.Error) {
for {
skip := reader_buffered(b)
if skip == 0 {
if fill_err := _reader_read_new_chunk(b); fill_err != nil {
return 0, fill_err
}
_reader_read_new_chunk(b) or_return
skip = reader_buffered(b)
}
skip = min(skip, remaining)
@@ -223,20 +219,18 @@ reader_read :: proc(b: ^Reader, p: []byte) -> (n: int, err: io.Error) {
// reader_read_byte reads and returns a single byte
// If no byte is available, it return an error
reader_read_byte :: proc(b: ^Reader) -> (byte, io.Error) {
reader_read_byte :: proc(b: ^Reader) -> (c: byte, err: io.Error) {
b.last_rune_size = -1
for b.r == b.w {
if b.err != nil {
return 0, _reader_consume_err(b)
}
if err := _reader_read_new_chunk(b); err != nil {
return 0, err
}
_reader_read_new_chunk(b) or_return
}
c := b.buf[b.r]
c = b.buf[b.r]
b.r += 1
b.last_byte = int(c)
return c, nil
return
}
// reader_unread_byte unreads the last byte. Only the most recently read byte can be unread
@@ -264,15 +258,12 @@ reader_read_rune :: proc(b: ^Reader) -> (r: rune, size: int, err: io.Error) {
!utf8.full_rune(b.buf[b.r:b.w]) &&
b.err == nil &&
b.w-b.w < len(b.buf) {
if err = _reader_read_new_chunk(b); err != nil {
return
}
_reader_read_new_chunk(b) or_return
}
b.last_rune_size = -1
if b.r == b.w {
err = _reader_consume_err(b)
return
return 0, 0, _reader_consume_err(b)
}
r, size = rune(b.buf[b.r]), 1
if r >= utf8.RUNE_SELF {
@@ -305,27 +296,20 @@ reader_write_to :: proc(b: ^Reader, w: io.Writer) -> (n: i64, err: io.Error) {
return i64(n), err
}
n, err = write_buf(b, w)
if err != nil {
return
}
n = write_buf(b, w) or_return
m: i64
if b.w-b.r < len(b.buf) {
if err = _reader_read_new_chunk(b); err != nil {
return
}
_reader_read_new_chunk(b) or_return
}
for b.r < b.w {
m, err = write_buf(b, w)
n += m
n += m // this needs to be done before returning
if err != nil {
return
}
if err = _reader_read_new_chunk(b); err != nil {
return
}
_reader_read_new_chunk(b) or_return
}
if b.err == .EOF {
@@ -403,9 +387,7 @@ reader_read_slice :: proc(b: ^Reader, delim: byte) -> (line: []byte, err: io.Err
s = b.w - b.r
if err = _reader_read_new_chunk(b); err != nil {
break
}
_reader_read_new_chunk(b) or_break
}
if i := len(line)-1; i >= 0 {
+1 -1
View File
@@ -159,7 +159,7 @@ writer_write_rune :: proc(b: ^Writer, r: rune) -> (size: int, err: io.Error) {
return
}
// writer_write writes a string into the buffer
// writer_write_string writes a string into the buffer
// It returns the number of bytes written
// If n < len(p), it will return an error explaining why the write is short
writer_write_string :: proc(b: ^Writer, s: string) -> (int, io.Error) {
+4 -1
View File
@@ -113,8 +113,11 @@ _buffer_grow :: proc(b: ^Buffer, n: int) -> int {
if i, ok := _buffer_try_grow(b, n); ok {
return i
}
if b.buf == nil && n <= SMALL_BUFFER_SIZE {
b.buf = make([dynamic]byte, n, SMALL_BUFFER_SIZE)
// Fixes #2756 by preserving allocator if already set on Buffer via init_buffer_allocator
reserve(&b.buf, SMALL_BUFFER_SIZE)
resize(&b.buf, n)
return 0
}
+1 -1
View File
@@ -127,7 +127,7 @@ advance_rune :: proc(t: ^Tokenizer) {
}
advance_rune_n :: proc(t: ^Tokenizer, n: int) {
for in 0..<n {
for _ in 0..<n {
advance_rune(t)
}
}
+1 -1
View File
@@ -63,4 +63,4 @@ foreign libc {
// strictly conformant C implementation is 16 on the platforms we care about.
// The choice of 4096 bytes for storage of this type is more than enough on all
// relevant platforms.
jmp_buf :: struct #align 16 { _: [4096]char, }
jmp_buf :: struct #align(16) { _: [4096]char, }
+1 -1
View File
@@ -18,7 +18,7 @@ foreign _ {
// strictly conformant C implementation is 16 on the platforms we care about.
// The choice of 4096 bytes for storage of this type is more than enough on all
// relevant platforms.
va_list :: struct #align 16 {
va_list :: struct #align(16) {
_: [4096]u8,
}
+2 -2
View File
@@ -35,12 +35,12 @@ when ODIN_OS == .Windows {
clock_t :: distinct long
time_t :: distinct i64
timespec :: struct #align 8 {
timespec :: struct #align(8) {
tv_sec: time_t,
tv_nsec: long,
}
tm :: struct #align 8 {
tm :: struct #align(8) {
tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year, tm_wday, tm_yday, tm_isdst: int,
}
}
+1 -1
View File
@@ -98,7 +98,7 @@ foreign libc {
}
// Large enough and aligned enough for any wide-spread in-use libc.
mbstate_t :: struct #align 16 { _: [32]char, }
mbstate_t :: struct #align(16) { _: [32]char, }
// Odin does not have default argument promotion so the need for a separate type
// here isn't necessary, though make it distinct just to be safe.
+17 -39
View File
@@ -216,24 +216,16 @@ read_slice_from_stream :: #force_inline proc(z: ^Context_Stream_Input, size: int
// TODO: REMOVE ALL USE OF context.temp_allocator here
// the is literally no need for it
b := make([]u8, size, context.temp_allocator)
_, e := io.read(z.input, b[:])
if e == .None {
return b, .None
}
return []u8{}, e
_ = io.read(z.input, b[:]) or_return
return b, nil
}
read_slice :: proc{read_slice_from_memory, read_slice_from_stream}
@(optimization_mode="speed")
read_data :: #force_inline proc(z: ^$C, $T: typeid) -> (res: T, err: io.Error) {
b, e := read_slice(z, size_of(T))
if e == .None {
return (^T)(&b[0])^, .None
}
return T{}, e
b := read_slice(z, size_of(T)) or_return
return (^T)(&b[0])^, nil
}
@(optimization_mode="speed")
@@ -250,12 +242,8 @@ read_u8_from_memory :: #force_inline proc(z: ^Context_Memory_Input) -> (res: u8,
@(optimization_mode="speed")
read_u8_from_stream :: #force_inline proc(z: ^Context_Stream_Input) -> (res: u8, err: io.Error) {
b, e := read_slice_from_stream(z, 1)
if e == .None {
return b[0], .None
}
return 0, e
b := read_slice_from_stream(z, 1) or_return
return b[0], nil
}
read_u8 :: proc{read_u8_from_memory, read_u8_from_stream}
@@ -320,12 +308,9 @@ peek_data_from_stream :: #force_inline proc(z: ^Context_Stream_Input, $T: typeid
size :: size_of(T)
// Get current position to read from.
curr, e1 := z.input->impl_seek(0, .Current)
if e1 != .None {
return T{}, e1
}
r, e2 := io.to_reader_at(z.input)
if !e2 {
curr := z.input->impl_seek(0, .Current) or_return
r, e1 := io.to_reader_at(z.input)
if !e1 {
return T{}, .Empty
}
when size <= 128 {
@@ -333,8 +318,8 @@ peek_data_from_stream :: #force_inline proc(z: ^Context_Stream_Input, $T: typeid
} else {
b := make([]u8, size, context.temp_allocator)
}
_, e3 := io.read_at(r, b[:], curr)
if e3 != .None {
_, e2 := io.read_at(r, b[:], curr)
if e2 != .None {
return T{}, .Empty
}
@@ -347,16 +332,9 @@ peek_data_at_offset_from_stream :: #force_inline proc(z: ^Context_Stream_Input,
size :: size_of(T)
// Get current position to return to.
cur_pos, e1 := z.input->impl_seek(0, .Current)
if e1 != .None {
return T{}, e1
}
cur_pos := z.input->impl_seek(0, .Current) or_return
// Seek to offset.
pos, e2 := z.input->impl_seek(offset, .Start)
if e2 != .None {
return T{}, e2
}
pos := z.input->impl_seek(offset, .Start) or_return
r, e3 := io.to_reader_at(z.input)
if !e3 {
@@ -465,7 +443,7 @@ peek_bits_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width:
if z.num_bits < u64(width) {
refill_lsb(z)
}
return u32(z.code_buffer & ~(~u64(0) << width))
return u32(z.code_buffer &~ (~u64(0) << width))
}
@(optimization_mode="speed")
@@ -473,7 +451,7 @@ peek_bits_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width:
if z.num_bits < u64(width) {
refill_lsb(z)
}
return u32(z.code_buffer & ~(~u64(0) << width))
return u32(z.code_buffer &~ (~u64(0) << width))
}
peek_bits_lsb :: proc{peek_bits_lsb_from_memory, peek_bits_lsb_from_stream}
@@ -481,13 +459,13 @@ peek_bits_lsb :: proc{peek_bits_lsb_from_memory, peek_bits_lsb_from_stream}
@(optimization_mode="speed")
peek_bits_no_refill_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width: u8) -> u32 {
assert(z.num_bits >= u64(width))
return u32(z.code_buffer & ~(~u64(0) << width))
return u32(z.code_buffer &~ (~u64(0) << width))
}
@(optimization_mode="speed")
peek_bits_no_refill_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width: u8) -> u32 {
assert(z.num_bits >= u64(width))
return u32(z.code_buffer & ~(~u64(0) << width))
return u32(z.code_buffer &~ (~u64(0) << width))
}
peek_bits_no_refill_lsb :: proc{peek_bits_no_refill_lsb_from_memory, peek_bits_no_refill_lsb_from_stream}
+2 -4
View File
@@ -335,10 +335,8 @@ load_from_context :: proc(z: ^$C, buf: ^bytes.Buffer, known_gzip_size := -1, exp
// fmt.printf("GZIP: Expected Payload Size: %v\n", expected_output_size);
zlib_error := zlib.inflate_raw(z, expected_output_size=expected_output_size)
if zlib_error != nil {
return zlib_error
}
zlib.inflate_raw(z, expected_output_size=expected_output_size) or_return
/*
Read CRC32 using the ctx bit reader because zlib may leave bytes in there.
*/
+8 -16
View File
@@ -147,15 +147,7 @@ grow_buffer :: proc(buf: ^[dynamic]u8) -> (err: compress.Error) {
Double until we reach the maximum allowed.
*/
new_size := min(len(buf) << 1, compress.COMPRESS_OUTPUT_ALLOCATE_MAX)
resize(buf, new_size)
if len(buf) != new_size {
/*
Resize failed.
*/
return .Resize_Failed
}
return nil
return resize(buf, new_size)
}
/*
@@ -182,7 +174,7 @@ write_byte :: #force_inline proc(z: ^$C, c: u8) -> (err: io.Error) #no_bounds_ch
}
@(optimization_mode="speed")
repl_byte :: proc(z: ^$C, count: u16, c: u8) -> (err: io.Error) #no_bounds_check {
repl_byte :: proc(z: ^$C, count: u16, c: u8) -> (err: io.Error) #no_bounds_check {
/*
TODO(Jeroen): Once we have a magic ring buffer, we can just peek/write into it
without having to worry about wrapping, so no need for a temp allocation to give to
@@ -306,10 +298,10 @@ decode_huffman_slowpath :: proc(z: ^$C, t: ^Huffman_Table) -> (r: u16, err: Erro
code := u16(compress.peek_bits_lsb(z,16))
k := int(z_bit_reverse(code, 16))
s: u8
#no_bounds_check for s = HUFFMAN_FAST_BITS+1; ; {
if k < t.maxcode[s] {
s: u8 = HUFFMAN_FAST_BITS+1
for {
#no_bounds_check if k < t.maxcode[s] {
break
}
s += 1
@@ -510,8 +502,8 @@ inflate_raw :: proc(z: ^$C, expected_output_size := -1, allocator := context.all
/*
Try to pre-allocate the output buffer.
*/
reserve(&z.output.buf, expected_output_size)
resize (&z.output.buf, expected_output_size)
reserve(&z.output.buf, expected_output_size) or_return
resize (&z.output.buf, expected_output_size) or_return
}
if len(z.output.buf) != expected_output_size {
@@ -654,7 +646,7 @@ inflate_raw :: proc(z: ^$C, expected_output_size := -1, allocator := context.all
}
if int(z.bytes_written) != len(z.output.buf) {
resize(&z.output.buf, int(z.bytes_written))
resize(&z.output.buf, int(z.bytes_written)) or_return
}
return nil
@@ -20,10 +20,10 @@ List :: struct {
Node :: struct {
next, prev: ^Node,
prev, next: ^Node,
}
push_front :: proc(list: ^List, node: ^Node) {
push_front :: proc "contextless" (list: ^List, node: ^Node) {
if list.head != nil {
list.head.prev = node
node.prev, node.next = nil, list.head
@@ -34,7 +34,7 @@ push_front :: proc(list: ^List, node: ^Node) {
}
}
push_back :: proc(list: ^List, node: ^Node) {
push_back :: proc "contextless" (list: ^List, node: ^Node) {
if list.tail != nil {
list.tail.next = node
node.prev, node.next = list.tail, nil
@@ -45,7 +45,7 @@ push_back :: proc(list: ^List, node: ^Node) {
}
}
remove :: proc(list: ^List, node: ^Node) {
remove :: proc "contextless" (list: ^List, node: ^Node) {
if node != nil {
if node.next != nil {
node.next.prev = node.prev
@@ -83,12 +83,34 @@ remove_by_proc :: proc(list: ^List, to_erase: proc(^Node) -> bool) {
}
}
remove_by_proc_contextless :: proc(list: ^List, to_erase: proc "contextless" (^Node) -> bool) {
for node := list.head; node != nil; {
next := node.next
if to_erase(node) {
if node.next != nil {
node.next.prev = node.prev
}
if node.prev != nil {
node.prev.next = node.next
}
if list.head == node {
list.head = node.next
}
if list.tail == node {
list.tail = node.prev
}
}
node = next
}
}
is_empty :: proc(list: ^List) -> bool {
is_empty :: proc "contextless" (list: ^List) -> bool {
return list.head == nil
}
pop_front :: proc(list: ^List) -> ^Node {
pop_front :: proc "contextless" (list: ^List) -> ^Node {
link := list.head
if link == nil {
return nil
@@ -108,7 +130,7 @@ pop_front :: proc(list: ^List) -> ^Node {
return link
}
pop_back :: proc(list: ^List) -> ^Node {
pop_back :: proc "contextless" (list: ^List) -> ^Node {
link := list.tail
if link == nil {
return nil
@@ -134,25 +156,25 @@ Iterator :: struct($T: typeid) {
offset: uintptr,
}
iterator_head :: proc(list: List, $T: typeid, $field_name: string) -> Iterator(T)
iterator_head :: proc "contextless" (list: List, $T: typeid, $field_name: string) -> Iterator(T)
where intrinsics.type_has_field(T, field_name),
intrinsics.type_field_type(T, field_name) == Node {
return {list.head, offset_of_by_string(T, field_name)}
}
iterator_tail :: proc(list: List, $T: typeid, $field_name: string) -> Iterator(T)
iterator_tail :: proc "contextless" (list: List, $T: typeid, $field_name: string) -> Iterator(T)
where intrinsics.type_has_field(T, field_name),
intrinsics.type_field_type(T, field_name) == Node {
return {list.tail, offset_of_by_string(T, field_name)}
}
iterator_from_node :: proc(node: ^Node, $T: typeid, $field_name: string) -> Iterator(T)
iterator_from_node :: proc "contextless" (node: ^Node, $T: typeid, $field_name: string) -> Iterator(T)
where intrinsics.type_has_field(T, field_name),
intrinsics.type_field_type(T, field_name) == Node {
return {node, offset_of_by_string(T, field_name)}
}
iterate_next :: proc(it: ^Iterator($T)) -> (ptr: ^T, ok: bool) {
iterate_next :: proc "contextless" (it: ^Iterator($T)) -> (ptr: ^T, ok: bool) {
node := it.curr
if node == nil {
return nil, false
@@ -162,7 +184,7 @@ iterate_next :: proc(it: ^Iterator($T)) -> (ptr: ^T, ok: bool) {
return (^T)(uintptr(node) - it.offset), true
}
iterate_prev :: proc(it: ^Iterator($T)) -> (ptr: ^T, ok: bool) {
iterate_prev :: proc "contextless" (it: ^Iterator($T)) -> (ptr: ^T, ok: bool) {
node := it.curr
if node == nil {
return nil, false
+1 -1
View File
@@ -56,7 +56,7 @@ space :: proc(q: $Q/Queue($T)) -> int {
// Reserve enough space for at least the specified capacity
reserve :: proc(q: ^$Q/Queue($T), capacity: int) -> runtime.Allocator_Error {
if uint(capacity) > q.len {
if capacity > space(q^) {
return _grow(q, uint(capacity))
}
return nil
+1 -1
View File
@@ -248,7 +248,7 @@ _read_record :: proc(r: ^Reader, dst: ^[dynamic]string, allocator := context.all
field_length += 1
case '\n', '\r':
if !is_quoted { break read_loop }
is_quoted or_break read_loop
case r.comma:
field_length = 0
+11 -12
View File
@@ -207,7 +207,7 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
case runtime.Type_Info_Relative_Pointer:
return .Unsupported_Type
case runtime.Type_Info_Relative_Slice:
case runtime.Type_Info_Relative_Multi_Pointer:
return .Unsupported_Type
case runtime.Type_Info_Matrix:
@@ -265,9 +265,8 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
i := 0
for bucket_index in 0..<map_cap {
if !runtime.map_hash_is_valid(hs[bucket_index]) {
continue
}
runtime.map_hash_is_valid(hs[bucket_index]) or_continue
opt_write_iteration(w, opt, i) or_return
i += 1
@@ -284,8 +283,8 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
#partial switch info in ti.variant {
case runtime.Type_Info_String:
switch s in a {
case string: name = s
case cstring: name = string(s)
case string: name = s
case cstring: name = string(s)
}
opt_write_key(w, opt, name) or_return
@@ -404,7 +403,7 @@ opt_write_key :: proc(w: io.Writer, opt: ^Marshal_Options, name: string) -> (err
switch opt.spec {
case .JSON, .JSON5:
io.write_quoted_string(w, name) or_return
io.write_string(w, ": ") or_return
io.write_string(w, ": " if opt.pretty else ":") or_return
case .MJSON:
if opt.mjson_keys_use_quotes {
@@ -412,11 +411,11 @@ opt_write_key :: proc(w: io.Writer, opt: ^Marshal_Options, name: string) -> (err
} else {
io.write_string(w, name) or_return
}
if opt.mjson_keys_use_equal_sign {
io.write_string(w, " = ") or_return
io.write_string(w, " = " if opt.pretty else "=") or_return
} else {
io.write_string(w, ": ") or_return
io.write_string(w, ": " if opt.pretty else ":") or_return
}
}
@@ -446,7 +445,7 @@ opt_write_iteration :: proc(w: io.Writer, opt: ^Marshal_Options, iteration: int)
switch opt.spec {
case .JSON, .JSON5:
if iteration > 0 {
io.write_string(w, ", ") or_return
io.write_byte(w, ',') or_return
if opt.pretty {
io.write_byte(w, '\n') or_return
@@ -462,7 +461,7 @@ opt_write_iteration :: proc(w: io.Writer, opt: ^Marshal_Options, iteration: int)
io.write_byte(w, '\n') or_return
} else {
// comma separation necessary for non pretty output!
io.write_string(w, ", ") or_return
io.write_byte(w, ',') or_return
}
}
+1 -1
View File
@@ -343,7 +343,7 @@ unquote_string :: proc(token: Token, spec: Specification, allocator := context.a
i += 1
continue
}
r, w := utf8.decode_rune_in_string(s)
r, w := utf8.decode_rune_in_string(s[i:])
if r == utf8.RUNE_ERROR && w == 1 {
break
}
+2 -2
View File
@@ -21,13 +21,13 @@ find_child_by_ident :: proc(doc: ^Document, parent_id: Element_ID, ident: string
/*
Skip commments. They have no name.
*/
if child.kind != .Element { continue }
if child.kind != .Element { continue }
/*
If the ident matches and it's the nth such child, return it.
*/
if child.ident == ident {
if count == nth { return child_id, true }
if count == nth { return child_id, true }
count += 1
}
}
+3
View File
@@ -35,6 +35,8 @@ Floating-point, complex numbers, and quaternions:
%F synonym for %f
%h hexadecimal (lower-case) representation with 0h prefix (0h01234abcd)
%H hexadecimal (upper-case) representation with 0H prefix (0h01234ABCD)
%m number of bytes in the best unit of measurement, e.g. 123.45mib
%M number of bytes in the best unit of measurement, e.g. 123.45MiB
String and slice of bytes
%s the uninterpreted bytes of the string or slice
%q a double-quoted string safely escaped with Odin syntax
@@ -85,6 +87,7 @@ Other flags:
add leading 0z for dozenal (%#z)
add leading 0x or 0X for hexadecimal (%#x or %#X)
remove leading 0x for %p (%#p)
add a space between bytes and the unit of measurement (%#m or %#M)
' ' (space) leave a space for elided sign in numbers (% d)
0 pad with leading zeros rather than spaces
+96 -50
View File
@@ -152,9 +152,9 @@ aprintln :: proc(args: ..any, sep := " ") -> string {
//
// Returns: A formatted string. The returned string must be freed accordingly.
//
aprintf :: proc(fmt: string, args: ..any) -> string {
aprintf :: proc(fmt: string, args: ..any, allocator := context.allocator) -> string {
str: strings.Builder
strings.builder_init(&str)
strings.builder_init(&str, allocator)
sbprintf(&str, fmt, ..args)
return strings.to_string(str)
}
@@ -327,7 +327,7 @@ ctprintf :: proc(format: string, args: ..any) -> cstring {
// Returns: A formatted string
//
sbprint :: proc(buf: ^strings.Builder, args: ..any, sep := " ") -> string {
wprint(strings.to_writer(buf), ..args, sep=sep)
wprint(strings.to_writer(buf), ..args, sep=sep, flush=true)
return strings.to_string(buf^)
}
// Formats and writes to a strings.Builder buffer using the default print settings
@@ -340,7 +340,7 @@ sbprint :: proc(buf: ^strings.Builder, args: ..any, sep := " ") -> string {
// Returns: The resulting formatted string
//
sbprintln :: proc(buf: ^strings.Builder, args: ..any, sep := " ") -> string {
wprintln(strings.to_writer(buf), ..args, sep=sep)
wprintln(strings.to_writer(buf), ..args, sep=sep, flush=true)
return strings.to_string(buf^)
}
// Formats and writes to a strings.Builder buffer according to the specified format string
@@ -353,7 +353,7 @@ sbprintln :: proc(buf: ^strings.Builder, args: ..any, sep := " ") -> string {
// Returns: The resulting formatted string
//
sbprintf :: proc(buf: ^strings.Builder, fmt: string, args: ..any) -> string {
wprintf(strings.to_writer(buf), fmt, ..args)
wprintf(strings.to_writer(buf), fmt, ..args, flush=true)
return strings.to_string(buf^)
}
// Formats and writes to an io.Writer using the default print settings
@@ -365,7 +365,7 @@ sbprintf :: proc(buf: ^strings.Builder, fmt: string, args: ..any) -> string {
//
// Returns: The number of bytes written
//
wprint :: proc(w: io.Writer, args: ..any, sep := " ") -> int {
wprint :: proc(w: io.Writer, args: ..any, sep := " ", flush := true) -> int {
fi: Info
fi.writer = w
@@ -391,7 +391,9 @@ wprint :: proc(w: io.Writer, args: ..any, sep := " ") -> int {
fmt_value(&fi, args[i], 'v')
}
io.flush(auto_cast w)
if flush {
io.flush(w)
}
return fi.n
}
@@ -404,7 +406,7 @@ wprint :: proc(w: io.Writer, args: ..any, sep := " ") -> int {
//
// Returns: The number of bytes written
//
wprintln :: proc(w: io.Writer, args: ..any, sep := " ") -> int {
wprintln :: proc(w: io.Writer, args: ..any, sep := " ", flush := true) -> int {
fi: Info
fi.writer = w
@@ -416,7 +418,9 @@ wprintln :: proc(w: io.Writer, args: ..any, sep := " ") -> int {
fmt_value(&fi, args[i], 'v')
}
io.write_byte(fi.writer, '\n', &fi.n)
io.flush(auto_cast w)
if flush {
io.flush(w)
}
return fi.n
}
// Formats and writes to an io.Writer according to the specified format string
@@ -428,7 +432,7 @@ wprintln :: proc(w: io.Writer, args: ..any, sep := " ") -> int {
//
// Returns: The number of bytes written
//
wprintf :: proc(w: io.Writer, fmt: string, args: ..any) -> int {
wprintf :: proc(w: io.Writer, fmt: string, args: ..any, flush := true) -> int {
fi: Info
arg_index: int = 0
end := len(fmt)
@@ -698,8 +702,9 @@ wprintf :: proc(w: io.Writer, fmt: string, args: ..any) -> int {
}
io.write_string(fi.writer, ")", &fi.n)
}
io.flush(auto_cast w)
if flush {
io.flush(w)
}
return fi.n
}
@@ -711,9 +716,11 @@ wprintf :: proc(w: io.Writer, fmt: string, args: ..any) -> int {
//
// Returns: The number of bytes written and an io.Error if encountered
//
wprint_type :: proc(w: io.Writer, info: ^runtime.Type_Info) -> (int, io.Error) {
wprint_type :: proc(w: io.Writer, info: ^runtime.Type_Info, flush := true) -> (int, io.Error) {
n, err := reflect.write_type(w, info)
io.flush(auto_cast w)
if flush {
io.flush(w)
}
return n, err
}
// Writes a typeid value to an io.Writer
@@ -724,9 +731,11 @@ wprint_type :: proc(w: io.Writer, info: ^runtime.Type_Info) -> (int, io.Error) {
//
// Returns: The number of bytes written and an io.Error if encountered
//
wprint_typeid :: proc(w: io.Writer, id: typeid) -> (int, io.Error) {
wprint_typeid :: proc(w: io.Writer, id: typeid, flush := true) -> (int, io.Error) {
n, err := reflect.write_type(w, type_info_of(id))
io.flush(auto_cast w)
if flush {
io.flush(w)
}
return n, err
}
// Parses an integer from a given string starting at a specified offset
@@ -746,9 +755,8 @@ _parse_int :: proc(s: string, offset: int) -> (result: int, new_offset: int, ok:
new_offset = offset
for new_offset < len(s) {
c := s[new_offset]
if !is_digit(c) {
break
}
is_digit(c) or_break
new_offset += 1
result *= 10
@@ -1039,6 +1047,65 @@ _fmt_int_128 :: proc(fi: ^Info, u: u128, base: int, is_signed: bool, bit_size: i
fi.zero = false
_pad(fi, s)
}
// Units of measurements:
__MEMORY_LOWER := " b kib mib gib tib pib eib"
__MEMORY_UPPER := " B KiB MiB GiB TiB PiB EiB"
// Formats an integer value as bytes with the best representation.
//
// Inputs:
// - fi: A pointer to an Info structure
// - u: The integer value to format
// - is_signed: A boolean indicating if the integer is signed
// - bit_size: The bit size of the integer
// - digits: A string containing the digits for formatting
//
_fmt_memory :: proc(fi: ^Info, u: u64, is_signed: bool, bit_size: int, units: string) {
abs, neg := strconv.is_integer_negative(u, is_signed, bit_size)
// Default to a precision of 2, but if less than a kb, 0
prec := fi.prec if (fi.prec_set || abs < mem.Kilobyte) else 2
div, off, unit_len := 1, 0, 1
for n := abs; n >= mem.Kilobyte; n /= mem.Kilobyte {
div *= mem.Kilobyte
off += 4
// First iteration is slightly different because you go from
// units of length 1 to units of length 2.
if unit_len == 1 {
off = 2
unit_len = 3
}
}
// If hash, we add a space between the value and the suffix.
if fi.hash {
unit_len += 1
} else {
off += 1
}
amt := f64(abs) / f64(div)
if neg {
amt = -amt
}
buf: [256]byte
str := strconv.append_float(buf[:], amt, 'f', prec, 64)
// Add the unit at the end.
copy(buf[len(str):], units[off:off+unit_len])
str = string(buf[:len(str)+unit_len])
if !fi.plus {
// Strip sign from "+<value>" but not "+Inf".
if str[0] == '+' && str[1] != 'I' {
str = str[1:]
}
}
_pad(fi, str)
}
// Hex Values:
__DIGITS_LOWER := "0123456789abcdefx"
__DIGITS_UPPER := "0123456789ABCDEFX"
@@ -1087,6 +1154,8 @@ fmt_int :: proc(fi: ^Info, u: u64, is_signed: bool, bit_size: int, verb: rune) {
io.write_string(fi.writer, "U+", &fi.n)
_fmt_int(fi, u, 16, false, bit_size, __DIGITS_UPPER)
}
case 'm': _fmt_memory(fi, u, is_signed, bit_size, __MEMORY_LOWER)
case 'M': _fmt_memory(fi, u, is_signed, bit_size, __MEMORY_UPPER)
case:
fmt_bad_verb(fi, verb)
@@ -1565,7 +1634,7 @@ fmt_bit_set :: proc(fi: ^Info, v: any, name: string = "") {
// - fi: A pointer to the Info structure where the indents will be written.
//
fmt_write_indent :: proc(fi: ^Info) {
for in 0..<fi.indent {
for _ in 0..<fi.indent {
io.write_byte(fi.writer, '\t', &fi.n)
}
}
@@ -1720,7 +1789,7 @@ fmt_struct :: proc(fi: ^Info, v: any, the_verb: rune, info: runtime.Type_Info_St
}
defer {
if hash {
for in 0..<indent { io.write_byte(fi.writer, '\t', &fi.n) }
for _ in 0..<indent { io.write_byte(fi.writer, '\t', &fi.n) }
}
io.write_byte(fi.writer, ']' if is_soa else '}', &fi.n)
}
@@ -1956,7 +2025,7 @@ fmt_named :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Named)
for x := i; x >= 10; x /= 10 {
n -= 1
}
for in 0..<n {
for _ in 0..<n {
io.write_byte(fi.writer, '0', &fi.n)
}
io.write_i64(fi.writer, i, 10, &fi.n)
@@ -1989,7 +2058,7 @@ fmt_named :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Named)
v := v
w := len(buf)
print := false
for in 0..<prec {
for _ in 0..<prec {
digit := v % 10
print = print || digit != 0
if print {
@@ -2485,9 +2554,7 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
ks, vs, hs, _, _ := runtime.map_kvh_data_dynamic(m^, info.map_info)
j := 0
for bucket_index in 0..<map_cap {
if !runtime.map_hash_is_valid(hs[bucket_index]) {
continue
}
runtime.map_hash_is_valid(hs[bucket_index]) or_continue
if j > 0 {
io.write_string(fi.writer, ", ", &fi.n)
@@ -2535,32 +2602,11 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
fmt_value(fi, absolute_ptr, verb)
case runtime.Type_Info_Relative_Slice:
case runtime.Type_Info_Relative_Multi_Pointer:
ptr := reflect.relative_pointer_to_absolute_raw(v.data, info.base_integer.id)
absolute_ptr := any{ptr, info.pointer.id}
if verb == 'p' {
fmt_pointer(fi, ptr, 'p')
} else if ptr == nil {
io.write_string(fi.writer, "[]", &fi.n)
} else {
len_ptr := uintptr(v.data) + uintptr(info.base_integer.size)
len_any := any{rawptr(len_ptr), info.base_integer.id}
len, _ := reflect.as_int(len_any)
slice_type := reflect.type_info_base(info.slice).variant.(runtime.Type_Info_Slice)
fi.record_level += 1
defer fi.record_level -= 1
io.write_byte(fi.writer, '[', &fi.n)
defer io.write_byte(fi.writer, ']', &fi.n)
for i in 0..<len {
if i > 0 { io.write_string(fi.writer, ", ", &fi.n) }
data := uintptr(ptr) + uintptr(i*slice_type.elem_size)
fmt_arg(fi, any{rawptr(data), slice_type.elem.id}, verb)
}
}
fmt_value(fi, absolute_ptr, verb)
case runtime.Type_Info_Matrix:
fmt_matrix(fi, v, verb, info)
+6 -6
View File
@@ -32,15 +32,15 @@ stderr := io.Writer{
}
// 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) }
print :: proc(args: ..any, sep := " ", flush := true) -> int { return wprint(w=stdout, args=args, sep=sep, flush=flush) }
// 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) }
println :: proc(args: ..any, sep := " ", flush := true) -> int { return wprintln(w=stdout, args=args, sep=sep, flush=flush) }
// printf formats according to the specififed format string and writes to stdout
printf :: proc(fmt: string, args: ..any) -> int { return wprintf(stdout, fmt, ..args) }
printf :: proc(fmt: string, args: ..any, flush := true) -> int { return wprintf(stdout, fmt, ..args, flush=flush) }
// 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) }
eprint :: proc(args: ..any, sep := " ", flush := true) -> int { return wprint(w=stderr, args=args, sep=sep, flush=flush) }
// 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) }
eprintln :: proc(args: ..any, sep := " ", flush := true) -> int { return wprintln(w=stderr, args=args, sep=sep, flush=flush) }
// eprintf formats according to the specififed format string and writes to stderr
eprintf :: proc(fmt: string, args: ..any) -> int { return wprintf(stderr, fmt, ..args) }
eprintf :: proc(fmt: string, args: ..any, flush := true) -> int { return wprintf(stderr, fmt, ..args, flush=flush) }
+16 -16
View File
@@ -7,18 +7,18 @@ import "core:io"
import "core:bufio"
// fprint formats using the default print settings and writes to fd
fprint :: proc(fd: os.Handle, args: ..any, sep := " ") -> int {
fprint :: proc(fd: os.Handle, args: ..any, sep := " ", flush := true) -> int {
buf: [1024]byte
b: bufio.Writer
defer bufio.writer_flush(&b)
bufio.writer_init_with_buf(&b, os.stream_from_handle(fd), buf[:])
w := bufio.writer_to_writer(&b)
return wprint(w, ..args, sep=sep)
return wprint(w, ..args, sep=sep, flush=flush)
}
// fprintln formats using the default print settings and writes to fd
fprintln :: proc(fd: os.Handle, args: ..any, sep := " ") -> int {
fprintln :: proc(fd: os.Handle, args: ..any, sep := " ", flush := true) -> int {
buf: [1024]byte
b: bufio.Writer
defer bufio.writer_flush(&b)
@@ -26,10 +26,10 @@ fprintln :: proc(fd: os.Handle, args: ..any, sep := " ") -> int {
bufio.writer_init_with_buf(&b, os.stream_from_handle(fd), buf[:])
w := bufio.writer_to_writer(&b)
return wprintln(w, ..args, sep=sep)
return wprintln(w, ..args, sep=sep, flush=flush)
}
// fprintf formats according to the specified format string and writes to fd
fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int {
fprintf :: proc(fd: os.Handle, fmt: string, args: ..any, flush := true) -> int {
buf: [1024]byte
b: bufio.Writer
defer bufio.writer_flush(&b)
@@ -37,9 +37,9 @@ fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int {
bufio.writer_init_with_buf(&b, os.stream_from_handle(fd), buf[:])
w := bufio.writer_to_writer(&b)
return wprintf(w, fmt, ..args)
return wprintf(w, fmt, ..args, flush=flush)
}
fprint_type :: proc(fd: os.Handle, info: ^runtime.Type_Info) -> (n: int, err: io.Error) {
fprint_type :: proc(fd: os.Handle, info: ^runtime.Type_Info, flush := true) -> (n: int, err: io.Error) {
buf: [1024]byte
b: bufio.Writer
defer bufio.writer_flush(&b)
@@ -47,9 +47,9 @@ fprint_type :: proc(fd: os.Handle, info: ^runtime.Type_Info) -> (n: int, err: io
bufio.writer_init_with_buf(&b, os.stream_from_handle(fd), buf[:])
w := bufio.writer_to_writer(&b)
return wprint_type(w, info)
return wprint_type(w, info, flush=flush)
}
fprint_typeid :: proc(fd: os.Handle, id: typeid) -> (n: int, err: io.Error) {
fprint_typeid :: proc(fd: os.Handle, id: typeid, flush := true) -> (n: int, err: io.Error) {
buf: [1024]byte
b: bufio.Writer
defer bufio.writer_flush(&b)
@@ -57,19 +57,19 @@ fprint_typeid :: proc(fd: os.Handle, id: typeid) -> (n: int, err: io.Error) {
bufio.writer_init_with_buf(&b, os.stream_from_handle(fd), buf[:])
w := bufio.writer_to_writer(&b)
return wprint_typeid(w, id)
return wprint_typeid(w, id, flush=flush)
}
// print formats using the default print settings and writes to os.stdout
print :: proc(args: ..any, sep := " ") -> int { return fprint(os.stdout, ..args, sep=sep) }
print :: proc(args: ..any, sep := " ", flush := true) -> int { return fprint(os.stdout, ..args, sep=sep, flush=flush) }
// println formats using the default print settings and writes to os.stdout
println :: proc(args: ..any, sep := " ") -> int { return fprintln(os.stdout, ..args, sep=sep) }
println :: proc(args: ..any, sep := " ", flush := true) -> int { return fprintln(os.stdout, ..args, sep=sep, flush=flush) }
// printf formats according to the specified format string and writes to os.stdout
printf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stdout, fmt, ..args) }
printf :: proc(fmt: string, args: ..any, flush := true) -> int { return fprintf(os.stdout, fmt, ..args, flush=flush) }
// eprint formats using the default print settings and writes to os.stderr
eprint :: proc(args: ..any, sep := " ") -> int { return fprint(os.stderr, ..args, sep=sep) }
eprint :: proc(args: ..any, sep := " ", flush := true) -> int { return fprint(os.stderr, ..args, sep=sep, flush=flush) }
// eprintln formats using the default print settings and writes to os.stderr
eprintln :: proc(args: ..any, sep := " ") -> int { return fprintln(os.stderr, ..args, sep=sep) }
eprintln :: proc(args: ..any, sep := " ", flush := true) -> int { return fprintln(os.stderr, ..args, sep=sep, flush=flush) }
// eprintf formats according to the specified format string and writes to os.stderr
eprintf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stderr, fmt, ..args) }
eprintf :: proc(fmt: string, args: ..any, flush := true) -> int { return fprintf(os.stderr, fmt, ..args, flush=flush) }
+1 -1
View File
@@ -299,7 +299,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
if length := int(data & 63) + 1; (length * img.channels) > len(pixels) {
return img, .Corrupt
} else {
#no_bounds_check for in 0..<length {
#no_bounds_check for _ in 0..<length {
copy(pixels, pix[:img.channels])
pixels = pixels[img.channels:]
}
+4 -4
View File
@@ -215,10 +215,10 @@ simd_shr_masked :: proc(a: #simd[N]T, b: #simd[N]Unsigned_Integer) -> #simd[N]T
simd_add_sat :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_sub_sat :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_and :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_or :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_xor :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_and_not :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_bit_and :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_bit_or :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_bit_xor :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_bit_and_not :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_neg :: proc(a: #simd[N]T) -> #simd[N]T ---
+2 -2
View File
@@ -39,12 +39,12 @@ write_int :: proc(w: Writer, i: int, base: int = 10, n_written: ^int = nil) -> (
}
write_u128 :: proc(w: Writer, i: u128, base: int = 10, n_written: ^int = nil) -> (n: int, err: Error) {
buf: [32]byte
buf: [39]byte
s := strconv.append_bits_128(buf[:], i, base, false, 128, strconv.digits, nil)
return write_string(w, s, n_written)
}
write_i128 :: proc(w: Writer, i: i128, base: int = 10, n_written: ^int = nil) -> (n: int, err: Error) {
buf: [32]byte
buf: [40]byte
s := strconv.append_bits_128(buf[:], u128(i), base, true, 128, strconv.digits, nil)
return write_string(w, s, n_written)
}
+8 -8
View File
@@ -22,43 +22,43 @@ package math_big
/*
2's complement `and`, returns `dest = a & b;`
*/
int_and :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
int_bit_and :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
assert_if_nil(dest, a, b)
context.allocator = allocator
internal_clear_if_uninitialized(a, b) or_return
return #force_inline internal_int_and(dest, a, b)
}
and :: proc { int_and, }
bit_and :: proc { int_bit_and, }
/*
2's complement `or`, returns `dest = a | b;`
*/
int_or :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
int_bit_or :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
assert_if_nil(dest, a, b)
context.allocator = allocator
internal_clear_if_uninitialized(a, b) or_return
return #force_inline internal_int_or(dest, a, b)
}
or :: proc { int_or, }
bit_or :: proc { int_bit_or, }
/*
2's complement `xor`, returns `dest = a ^ b;`
*/
int_xor :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
int_bit_xor :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
assert_if_nil(dest, a, b)
context.allocator = allocator
internal_clear_if_uninitialized(a, b) or_return
return #force_inline internal_int_xor(dest, a, b)
}
xor :: proc { int_xor, }
bit_xor :: proc { int_bit_xor, }
/*
dest = ~src
*/
int_complement :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) {
int_bit_complement :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) {
/*
Check that `src` and `dest` are usable.
*/
@@ -68,7 +68,7 @@ int_complement :: proc(dest, src: ^Int, allocator := context.allocator) -> (err:
internal_clear_if_uninitialized(dest, src) or_return
return #force_inline internal_int_complement(dest, src)
}
complement :: proc { int_complement, }
bit_complement :: proc { int_bit_complement, }
/*
quotient, remainder := numerator >> bits;
+7 -7
View File
@@ -1163,7 +1163,7 @@ internal_int_prime_next_prime :: proc(a: ^Int, trials: int, bbs_style: bool, all
/*
If we didn't pass the sieve and step == MP_MAX then skip test */
if (y && (step >= ((1 << _DIGIT_BITS) - kstep))) { continue }
if y && (step >= ((1 << _DIGIT_BITS) - kstep)) { continue }
if internal_int_is_prime(a, trials) or_return { break }
}
@@ -1214,7 +1214,6 @@ internal_random_prime :: proc(a: ^Int, size_in_bits: int, trials: int, flags :=
trials = number_of_rabin_miller_trials(size_in_bits)
}
res: bool
RANDOM_PRIME_ITERATIONS_USED = 0
for {
@@ -1251,9 +1250,8 @@ internal_random_prime :: proc(a: ^Int, size_in_bits: int, trials: int, flags :=
/*
Is it prime?
*/
res = internal_int_is_prime(a, trials) or_return
if (!res) {
res := internal_int_is_prime(a, trials) or_return
if !res {
continue
}
@@ -1267,9 +1265,11 @@ internal_random_prime :: proc(a: ^Int, size_in_bits: int, trials: int, flags :=
/*
Is it prime?
*/
res = internal_int_is_prime(a, trials) or_return
res = internal_int_is_prime(a, trials) or_return
}
if res {
break
}
if res { break }
}
if .Safe in flags {
+1 -1
View File
@@ -1089,7 +1089,7 @@ _private_int_div_school :: proc(quotient, remainder, numerator, denominator: ^In
Step 3. for i from n down to (t + 1).
*/
#no_bounds_check for i := n; i >= (t + 1); i -= 1 {
if (i > x.used) { continue }
if i > x.used { continue }
/*
step 3.1 if xi == yt then set q{i-t-1} to b-1, otherwise set q{i-t-1} to (xi*b + x{i-1})/yt
+7 -5
View File
@@ -29,13 +29,13 @@ Fixed52_12 :: distinct Fixed(i64, 12)
init_from_f64 :: proc(x: ^$T/Fixed($Backing, $Fraction_Width), val: f64) {
i, f := math.modf(val)
i, f := math.modf(math.abs(val))
x.i = Backing(f * (1<<Fraction_Width))
x.i &= 1<<Fraction_Width - 1
x.i |= Backing(i) << Fraction_Width
if val < 0 do x.i *= -1
}
init_from_parts :: proc(x: ^$T/Fixed($Backing, $Fraction_Width), integer, fraction: Backing) {
i, f := math.modf(val)
x.i = fraction
@@ -44,9 +44,11 @@ init_from_parts :: proc(x: ^$T/Fixed($Backing, $Fraction_Width), integer, fracti
}
to_f64 :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> f64 {
res := f64(x.i >> Fraction_Width)
res += f64(x.i & (1<<Fraction_Width-1)) / f64(1<<Fraction_Width)
return res
sign := -1.0 if x.i < 0 else 1.0
num := math.abs(x.i)
res := f64(num >> Fraction_Width)
res += f64(num & (1<<Fraction_Width-1)) / f64(1<<Fraction_Width)
return res * sign
}
+60 -40
View File
@@ -1,9 +1,11 @@
/*
Package core:math/rand implements various random number generators
*/
package rand
import "core:intrinsics"
import "core:math"
import "core:mem"
Rand :: struct {
@@ -70,6 +72,7 @@ create :: proc(seed: u64) -> (res: Rand) {
return r
}
/*
Initialises a random number generator.
@@ -95,9 +98,9 @@ Possible Output:
init :: proc(r: ^Rand, seed: u64) {
r.state = 0
r.inc = (seed << 1) | 1
_random(r)
_random_u64(r)
r.state += seed
_random(r)
_random_u64(r)
}
/*
@@ -107,7 +110,7 @@ On `linux` refer to the `getrandom` syscall.
On `darwin` refer to `getentropy`.
On `windows` refer to `BCryptGenRandom`.
All other platforms wi
All other platforms are not supported
Inputs:
- r: The random number generator to use the system random number generator
@@ -139,11 +142,9 @@ init_as_system :: proc(r: ^Rand) {
}
@(private)
_random :: proc(r: ^Rand) -> u32 {
_random_u64 :: proc(r: ^Rand) -> u64 {
r := r
if r == nil {
// NOTE(bill, 2020-09-07): Do this so that people can
// enforce the global random state if necessary with `nil`
r = &global_rand
}
when #defined(_system_random) {
@@ -152,11 +153,12 @@ _random :: proc(r: ^Rand) -> u32 {
}
}
old_state := r.state
r.state = old_state * 6364136223846793005 + (r.inc|1)
xor_shifted := u32(((old_state>>18) ~ old_state) >> 27)
rot := u32(old_state >> 59)
return (xor_shifted >> rot) | (xor_shifted << ((-rot) & 31))
xor_shifted := (((old_state >> 59) + 5) ~ old_state) * 12605985483714917081
rot := (old_state >> 59)
return (xor_shifted >> rot) | (xor_shifted << ((-rot) & 63))
}
/*
@@ -187,7 +189,7 @@ Possible Output:
*/
@(require_results)
uint32 :: proc(r: ^Rand = nil) -> (val: u32) { return _random(r) }
uint32 :: proc(r: ^Rand = nil) -> (val: u32) { return u32(_random_u64(r)) }
/*
Generates a random 64 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
@@ -217,11 +219,7 @@ Possible Output:
*/
@(require_results)
uint64 :: proc(r: ^Rand = nil) -> (val: u64) {
a := u64(_random(r))
b := u64(_random(r))
return (a<<32) | b
}
uint64 :: proc(r: ^Rand = nil) -> (val: u64) { return _random_u64(r) }
/*
Generates a random 128 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
@@ -252,11 +250,9 @@ Possible Output:
*/
@(require_results)
uint128 :: proc(r: ^Rand = nil) -> (val: u128) {
a := u128(_random(r))
b := u128(_random(r))
c := u128(_random(r))
d := u128(_random(r))
return (a<<96) | (b<<64) | (c<<32) | d
a := u128(_random_u64(r))
b := u128(_random_u64(r))
return (a<<64) | b
}
/*
@@ -288,6 +284,7 @@ Possible Output:
*/
@(require_results) int31 :: proc(r: ^Rand = nil) -> (val: i32) { return i32(uint32(r) << 1 >> 1) }
/*
Generates a random 63 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
The sign bit will always be set to 0, thus all generated numbers will be positive.
@@ -317,6 +314,7 @@ Possible Output:
*/
@(require_results) int63 :: proc(r: ^Rand = nil) -> (val: i64) { return i64(uint64(r) << 1 >> 1) }
/*
Generates a random 127 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
The sign bit will always be set to 0, thus all generated numbers will be positive.
@@ -348,14 +346,14 @@ Possible Output:
@(require_results) int127 :: proc(r: ^Rand = nil) -> (val: i128) { return i128(uint128(r) << 1 >> 1) }
/*
Generates a random 31 bit value in the range `(0, n]` using the provided random number generator. If no generator is provided the global random number generator will be used.
Generates a random 31 bit value in the range `[0, n)` using the provided random number generator. If no generator is provided the global random number generator will be used.
Inputs:
- n: The upper bound of the generated number, this value is exclusive
- r: The random number generator to use, or nil for the global generator
Returns:
- val: A random 31 bit value in the range `(0, n]`
- val: A random 31 bit value in the range `[0, n)`
WARNING: Panics if n is less than 0
@@ -392,15 +390,16 @@ int31_max :: proc(n: i32, r: ^Rand = nil) -> (val: i32) {
}
return v % n
}
/*
Generates a random 63 bit value in the range `(0, n]` using the provided random number generator. If no generator is provided the global random number generator will be used.
Generates a random 63 bit value in the range `[0, n)` using the provided random number generator. If no generator is provided the global random number generator will be used.
Inputs:
- n: The upper bound of the generated number, this value is exclusive
- r: The random number generator to use, or nil for the global generator
Returns:
- val: A random 63 bit value in the range `(0, n]`
- val: A random 63 bit value in the range `[0, n)`
WARNING: Panics if n is less than 0
@@ -437,15 +436,16 @@ int63_max :: proc(n: i64, r: ^Rand = nil) -> (val: i64) {
}
return v % n
}
/*
Generates a random 127 bit value in the range `(0, n]` using the provided random number generator. If no generator is provided the global random number generator will be used.
Generates a random 127 bit value in the range `[0, n)` using the provided random number generator. If no generator is provided the global random number generator will be used.
Inputs:
- n: The upper bound of the generated number, this value is exclusive
- r: The random number generator to use, or nil for the global generator
Returns:
- val: A random 127 bit value in the range `(0, n]`
- val: A random 127 bit value in the range `[0, n)`
WARNING: Panics if n is less than 0
@@ -482,15 +482,16 @@ int127_max :: proc(n: i128, r: ^Rand = nil) -> (val: i128) {
}
return v % n
}
/*
Generates a random integer value in the range `(0, n]` using the provided random number generator. If no generator is provided the global random number generator will be used.
Generates a random integer value in the range `[0, n)` using the provided random number generator. If no generator is provided the global random number generator will be used.
Inputs:
- n: The upper bound of the generated number, this value is exclusive
- r: The random number generator to use, or nil for the global generator
Returns:
- val: A random integer value in the range `(0, n]`
- val: A random integer value in the range `[0, n)`
WARNING: Panics if n is less than 0
@@ -525,13 +526,13 @@ int_max :: proc(n: int, r: ^Rand = nil) -> (val: int) {
}
/*
Generates a random double floating point value in the range `(0, 1]` using the provided random number generator. If no generator is provided the global random number generator will be used.
Generates a random double floating point value in the range `[0, 1)` using the provided random number generator. If no generator is provided the global random number generator will be used.
Inputs:
- r: The random number generator to use, or nil for the global generator
Returns:
- val: A random double floating point value in the range `(0, 1]`
- val: A random double floating point value in the range `[0, 1)`
Example:
import "core:math/rand"
@@ -554,13 +555,13 @@ Possible Output:
@(require_results) float64 :: proc(r: ^Rand = nil) -> (val: f64) { return f64(int63_max(1<<53, r)) / (1 << 53) }
/*
Generates a random single floating point value in the range `(0, 1]` using the provided random number generator. If no generator is provided the global random number generator will be used.
Generates a random single floating point value in the range `[0, 1)` using the provided random number generator. If no generator is provided the global random number generator will be used.
Inputs:
- r: The random number generator to use, or nil for the global generator
Returns:
- val: A random single floating point value in the range `(0, 1]`
- val: A random single floating point value in the range `[0, 1)`
Example:
import "core:math/rand"
@@ -580,10 +581,12 @@ Possible Output:
0.511
*/
@(require_results) float32 :: proc(r: ^Rand = nil) -> (val: f32) { return f32(float64(r)) }
@(require_results) float32 :: proc(r: ^Rand = nil) -> (val: f32) { return f32(int31_max(1<<24, r)) / (1 << 24) }
/*
Generates a random double floating point value in the range `(low, high]` using the provided random number generator. If no generator is provided the global random number generator will be used.
Generates a random double floating point value in the range `[low, high)` using the provided random number generator. If no generator is provided the global random number generator will be used.
WARNING: Panics if `high < low`
Inputs:
- low: The lower bounds of the value, this value is inclusive
@@ -591,7 +594,7 @@ Inputs:
- r: The random number generator to use, or nil for the global generator
Returns:
- val: A random double floating point value in the range `(low, high]`
- val: A random double floating point value in the range [low, high)
Example:
import "core:math/rand"
@@ -611,9 +614,17 @@ Possible Output:
673.130
*/
@(require_results) float64_range :: proc(low, high: f64, r: ^Rand = nil) -> (val: f64) { return (high-low)*float64(r) + low }
@(require_results) float64_range :: proc(low, high: f64, r: ^Rand = nil) -> (val: f64) {
assert(low <= high, "low must be lower than or equal to high")
val = (high-low)*float64(r) + low
if val >= high {
val = max(low, high * (1 - math.F64_EPSILON))
}
return
}
/*
Generates a random single floating point value in the range `(low, high]` using the provided random number generator. If no generator is provided the global random number generator will be used.
Generates a random single floating point value in the range `[low, high)` using the provided random number generator. If no generator is provided the global random number generator will be used.
Inputs:
- low: The lower bounds of the value, this value is inclusive
@@ -621,7 +632,9 @@ Inputs:
- r: The random number generator to use, or nil for the global generator
Returns:
- val: A random single floating point value in the range `(low, high]`
- val: A random single floating point value in the range [low, high)
WARNING: Panics if `high < low`
Example:
import "core:math/rand"
@@ -641,10 +654,18 @@ Possible Output:
673.130
*/
@(require_results) float32_range :: proc(low, high: f32, r: ^Rand = nil) -> (val: f32) { return (high-low)*float32(r) + low }
@(require_results) float32_range :: proc(low, high: f32, r: ^Rand = nil) -> (val: f32) {
assert(low <= high, "low must be lower than or equal to high")
val = (high-low)*float32(r) + low
if val >= high {
val = max(low, high * (1 - math.F32_EPSILON))
}
return
}
/*
Fills a byte slice with random values using the provided random number generator. If no generator is provided the global random number generator will be used.
Due to floating point precision there is no guarantee if the upper and lower bounds are inclusive/exclusive with the exact floating point value.
Inputs:
- p: The byte slice to fill
@@ -797,7 +818,6 @@ Example:
fmt.println(rand.choice(data[:]))
}
Possible Output:
3
+3 -3
View File
@@ -3,10 +3,10 @@ package rand
import "core:sys/darwin"
@(require_results)
_system_random :: proc() -> u32 {
_system_random :: proc() -> u64 {
for {
value: u32
ret := darwin.syscall_getentropy(([^]u8)(&value), 4)
value: u64
ret := darwin.syscall_getentropy(([^]u8)(&value), size_of(value))
if ret < 0 {
switch ret {
case -4: // EINTR
+3 -3
View File
@@ -3,10 +3,10 @@ package rand
import "core:sys/unix"
@(require_results)
_system_random :: proc() -> u32 {
_system_random :: proc() -> u64 {
for {
value: u32
ret := unix.sys_getrandom(([^]u8)(&value), 4, 0)
value: u64
ret := unix.sys_getrandom(([^]u8)(&value), size_of(value), 0)
if ret < 0 {
switch ret {
case -4: // EINTR
+3 -3
View File
@@ -3,9 +3,9 @@ package rand
import win32 "core:sys/windows"
@(require_results)
_system_random :: proc() -> u32 {
value: u32
status := win32.BCryptGenRandom(nil, ([^]u8)(&value), 4, win32.BCRYPT_USE_SYSTEM_PREFERRED_RNG)
_system_random :: proc() -> u64 {
value: u64
status := win32.BCryptGenRandom(nil, ([^]u8)(&value), size_of(value), win32.BCRYPT_USE_SYSTEM_PREFERRED_RNG)
if status < 0 {
panic("BCryptGenRandom failed")
}
+1
View File
@@ -749,6 +749,7 @@ dynamic_pool_alloc_bytes :: proc(p: ^Dynamic_Pool, bytes: int) -> ([]byte, Alloc
n := bytes
extra := p.alignment - (n % p.alignment)
n += extra
if n > p.block_size do return nil, .Invalid_Argument
if n >= p.out_band_size {
assert(p.block_allocator.procedure != nil)
memory, err := p.block_allocator.procedure(p.block_allocator.data, Allocator_Mode.Alloc,
+1 -1
View File
@@ -24,7 +24,7 @@ main :: proc() {
_main()
for _, leak in track.allocation_map {
fmt.printf("%v leaked %v bytes\n", leak.location, leak.size)
fmt.printf("%v leaked %m\n", leak.location, leak.size)
}
for bad_free in track.bad_free_array {
fmt.printf("%v allocation %p was freed badly\n", bad_free.location, bad_free.memory)
+2
View File
@@ -8,6 +8,8 @@ Kilobyte :: runtime.Kilobyte
Megabyte :: runtime.Megabyte
Gigabyte :: runtime.Gigabyte
Terabyte :: runtime.Terabyte
Petabyte :: runtime.Petabyte
Exabyte :: runtime.Exabyte
set :: proc "contextless" (data: rawptr, value: byte, len: int) -> rawptr {
return runtime.memset(data, i32(value), len)
+1 -1
View File
@@ -133,7 +133,7 @@ arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_l
return
}
// Resets the memory of a Static or Buffer arena to a specific `pos`ition (offset) and zeroes the previously used memory.
// Resets the memory of a Static or Buffer arena to a specific `position` (offset) and zeroes the previously used memory.
arena_static_reset_to :: proc(arena: ^Arena, pos: uint, loc := #caller_location) -> bool {
sync.mutex_guard(&arena.mutex)
+25 -10
View File
@@ -2,6 +2,8 @@ package mem_virtual
import "core:mem"
import "core:intrinsics"
import "core:runtime"
_ :: runtime
DEFAULT_PAGE_SIZE := uint(4096)
@@ -59,16 +61,22 @@ Memory_Block_Flag :: enum u32 {
Memory_Block_Flags :: distinct bit_set[Memory_Block_Flag; u32]
@(private="file", require_results)
align_formula :: #force_inline proc "contextless" (size, align: uint) -> uint {
result := size + align-1
return result - result%align
}
@(require_results)
memory_block_alloc :: proc(committed, reserved: uint, flags: Memory_Block_Flags) -> (block: ^Memory_Block, err: Allocator_Error) {
align_formula :: proc "contextless" (size, align: uint) -> uint {
result := size + align-1
return result - result%align
}
page_size := DEFAULT_PAGE_SIZE
assert(mem.is_power_of_two(uintptr(page_size)))
committed := committed
reserved := reserved
committed = align_formula(committed, page_size)
reserved = align_formula(reserved, page_size)
committed = clamp(committed, 0, reserved)
total_size := uint(reserved + size_of(Platform_Memory_Block))
@@ -77,7 +85,7 @@ memory_block_alloc :: proc(committed, reserved: uint, flags: Memory_Block_Flags)
do_protection := false
if .Overflow_Protection in flags { // overflow protection
rounded_size := align_formula(uint(reserved), page_size)
rounded_size := reserved
total_size = uint(rounded_size + 2*page_size)
base_offset = uintptr(page_size + rounded_size - uint(reserved))
protect_offset = uintptr(page_size + rounded_size)
@@ -86,14 +94,14 @@ memory_block_alloc :: proc(committed, reserved: uint, flags: Memory_Block_Flags)
pmblock := platform_memory_alloc(0, total_size) or_return
pmblock.block.base = ([^]byte)(uintptr(pmblock) + base_offset)
pmblock.block.base = ([^]byte)(pmblock)[base_offset:]
platform_memory_commit(pmblock, uint(base_offset) + committed) or_return
// Should be zeroed
assert(pmblock.block.used == 0)
assert(pmblock.block.prev == nil)
if do_protection {
protect(rawptr(uintptr(pmblock) + protect_offset), page_size, Protect_No_Access)
protect(([^]byte)(pmblock)[protect_offset:], page_size, Protect_No_Access)
}
pmblock.block.committed = committed
@@ -119,7 +127,13 @@ alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: uint)
if block.committed - block.used < size {
pmblock := (^Platform_Memory_Block)(block)
base_offset := uint(uintptr(pmblock.block.base) - uintptr(pmblock))
platform_total_commit := base_offset + block.used + size
// NOTE(bill): [Heuristic] grow the commit size larger than needed
// TODO(bill): determine a better heuristic for this behaviour
extra_size := max(size, block.committed>>1)
platform_total_commit := base_offset + block.used + extra_size
platform_total_commit = align_formula(platform_total_commit, DEFAULT_PAGE_SIZE)
platform_total_commit = min(platform_total_commit, pmblock.reserved)
assert(pmblock.committed <= pmblock.reserved)
assert(pmblock.committed < platform_total_commit)
@@ -128,8 +142,9 @@ alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: uint)
pmblock.committed = platform_total_commit
block.committed = pmblock.committed - base_offset
}
return nil
return
}
if block == nil {
+3 -3
View File
@@ -471,7 +471,7 @@ join_port :: proc(address_or_host: string, port: int, allocator := context.alloc
// hostname
fmt.sbprintf(&b, "%v:%v", addr_or_host, port)
} else {
switch in addr {
switch _ in addr {
case IP4_Address:
fmt.sbprintf(&b, "%v:%v", address_to_string(addr), port)
case IP6_Address:
@@ -587,7 +587,7 @@ address_to_string :: proc(addr: Address, allocator := context.temp_allocator) ->
}
// Returns a temporarily-allocated string representation of the endpoint.
// If there's a port, uses the `[address]:port` format.
// If there's a port, uses the `ip4address:port` or `[ip6address]:port` format, respectively.
endpoint_to_string :: proc(ep: Endpoint, allocator := context.temp_allocator) -> string {
if ep.port == 0 {
return address_to_string(ep.address, allocator)
@@ -606,7 +606,7 @@ to_string :: proc{address_to_string, endpoint_to_string}
family_from_address :: proc(addr: Address) -> Address_Family {
switch in addr {
switch _ in addr {
case IP4_Address: return .IP4
case IP6_Address: return .IP6
case:
+20 -32
View File
@@ -96,7 +96,7 @@ resolve :: proc(hostname_and_maybe_port: string) -> (ep4, ep6: Endpoint, err: Ne
switch t in target {
case Endpoint:
// NOTE(tetra): The hostname was actually an IP address; nothing to resolve, so just return it.
switch in t.address {
switch _ in t.address {
case IP4_Address: ep4 = t
case IP6_Address: ep6 = t
case: unreachable()
@@ -122,7 +122,7 @@ resolve_ip4 :: proc(hostname_and_maybe_port: string) -> (ep4: Endpoint, err: Net
switch t in target {
case Endpoint:
// NOTE(tetra): The hostname was actually an IP address; nothing to resolve, so just return it.
switch in t.address {
switch _ in t.address {
case IP4_Address:
return t, nil
case IP6_Address:
@@ -149,7 +149,7 @@ resolve_ip6 :: proc(hostname_and_maybe_port: string) -> (ep6: Endpoint, err: Net
switch t in target {
case Endpoint:
// NOTE(tetra): The hostname was actually an IP address; nothing to resolve, so just return it.
switch in t.address {
switch _ in t.address {
case IP4_Address:
err = .Unable_To_Resolve
return
@@ -247,23 +247,19 @@ get_dns_records_from_nameservers :: proc(hostname: string, type: DNS_Record_Type
}
defer close(conn)
_, send_err := send(conn, dns_packet[:], name_server)
if send_err != nil {
continue
}
_ = send(conn, dns_packet[:], name_server) or_continue
set_err := set_option(conn, .Receive_Timeout, time.Second * 1)
if set_err != nil {
if set_option(conn, .Receive_Timeout, time.Second * 1) != nil {
return nil, .Connection_Error
}
recv_sz, _, recv_err := recv_udp(conn, dns_response_buf[:])
if recv_err == UDP_Recv_Error.Timeout {
continue
} else if recv_err != nil {
continue
}
// recv_sz, _, recv_err := recv_udp(conn, dns_response_buf[:])
// if recv_err == UDP_Recv_Error.Timeout {
// continue
// } else if recv_err != nil {
// continue
// }
recv_sz, _ := recv_udp(conn, dns_response_buf[:]) or_continue
if recv_sz == 0 {
continue
}
@@ -429,11 +425,9 @@ load_hosts :: proc(hosts_file_path: string, allocator := context.allocator) -> (
}
for hostname in splits[1:] {
if len(hostname) == 0 {
continue
if len(hostname) != 0 {
append(&_hosts, DNS_Host_Entry{hostname, addr})
}
append(&_hosts, DNS_Host_Entry{hostname, addr})
}
}
@@ -833,11 +827,9 @@ parse_response :: proc(response: []u8, filter: DNS_Record_Type = nil, allocator
}
rec := parse_record(response, &cur_idx, filter) or_return
if rec == nil {
continue
if rec != nil {
append(&_records, rec)
}
append(&_records, rec)
}
for _ in 0..<authority_count {
@@ -846,11 +838,9 @@ parse_response :: proc(response: []u8, filter: DNS_Record_Type = nil, allocator
}
rec := parse_record(response, &cur_idx, filter) or_return
if rec == nil {
continue
if rec != nil {
append(&_records, rec)
}
append(&_records, rec)
}
for _ in 0..<additional_count {
@@ -859,11 +849,9 @@ parse_response :: proc(response: []u8, filter: DNS_Record_Type = nil, allocator
}
rec := parse_record(response, &cur_idx, filter) or_return
if rec == nil {
continue
if rec != nil {
append(&_records, rec)
}
append(&_records, rec)
}
return _records[:], true
+10 -3
View File
@@ -45,15 +45,22 @@ _get_dns_records_os :: proc(hostname: string, type: DNS_Record_Type, allocator :
count := 0
for r := rec; r != nil; r = r.pNext {
if r.wType != u16(type) do continue // NOTE(tetra): Should never happen, but...
if r.wType != u16(type) {
// NOTE(tetra): Should never happen, but...
continue
}
count += 1
}
recs := make([dynamic]DNS_Record, 0, count)
if recs == nil do return nil, .System_Error // return no results if OOM.
if recs == nil {
return nil, .System_Error // return no results if OOM.
}
for r := rec; r != nil; r = r.pNext {
if r.wType != u16(type) do continue // NOTE(tetra): Should never happen, but...
if r.wType != u16(type) {
continue // NOTE(tetra): Should never happen, but...
}
base_record := DNS_Record_Base{
record_name = strings.clone(string(r.pName)),
+7 -9
View File
@@ -109,12 +109,12 @@ TCP_Recv_Error :: enum c.int {
}
UDP_Recv_Error :: enum c.int {
None = 0,
Truncated = c.int(os.EMSGSIZE), // The buffer is too small to fit the entire message, and the message was truncated.
Not_Socket = c.int(os.ENOTSOCK), // The so-called socket is not an open socket.
Not_Descriptor = c.int(os.EBADF), // The so-called socket is, in fact, not even a valid descriptor.
Bad_Buffer = c.int(os.EFAULT), // The buffer did not point to a valid location in memory.
Interrupted = c.int(os.EINTR), // A signal occurred before any data was transmitted. See signal(7).
None = 0,
Buffer_Too_Small = c.int(os.EMSGSIZE), // The buffer is too small to fit the entire message, and the message was truncated. When this happens, the rest of message is lost.
Not_Socket = c.int(os.ENOTSOCK), // The so-called socket is not an open socket.
Not_Descriptor = c.int(os.EBADF), // The so-called socket is, in fact, not even a valid descriptor.
Bad_Buffer = c.int(os.EFAULT), // The buffer did not point to a valid location in memory.
Interrupted = c.int(os.EINTR), // A signal occurred before any data was transmitted. See signal(7).
// The send timeout duration passed before all data was sent. See Socket_Option.Send_Timeout.
// NOTE: No, really. Presumably this means something different for nonblocking sockets...
@@ -122,11 +122,9 @@ UDP_Recv_Error :: enum c.int {
Socket_Not_Bound = c.int(os.EINVAL), // The socket must be bound for this operation, but isn't.
}
// TODO
TCP_Send_Error :: enum c.int {
None = 0,
// TODO: merge with other errors?
Aborted = c.int(os.ECONNABORTED),
Connection_Closed = c.int(os.ECONNRESET),
Not_Connected = c.int(os.ENOTCONN),
@@ -151,7 +149,7 @@ TCP_Send_Error :: enum c.int {
// TODO
UDP_Send_Error :: enum c.int {
None = 0,
Truncated = c.int(os.EMSGSIZE), // The message is too big. No data was sent.
Message_Too_Long = c.int(os.EMSGSIZE), // The message is larger than the maximum UDP packet size. No data was sent.
// TODO: not sure what the exact circumstances for this is yet
Network_Unreachable = c.int(os.ENETUNREACH),
+5 -9
View File
@@ -105,9 +105,7 @@ TCP_Recv_Error :: enum c.int {
UDP_Recv_Error :: enum c.int {
None = 0,
// The buffer is too small to fit the entire message, and the message was truncated.
// When this happens, the rest of message is lost.
Buffer_Too_Small = c.int(os.EMSGSIZE),
Buffer_Too_Small = c.int(os.EMSGSIZE), // The buffer is too small to fit the entire message, and the message was truncated. When this happens, the rest of message is lost.
Not_Socket = c.int(os.ENOTSOCK), // The so-called socket is not an open socket.
Not_Descriptor = c.int(os.EBADF), // The so-called socket is, in fact, not even a valid descriptor.
Bad_Buffer = c.int(os.EFAULT), // The buffer did not point to a valid location in memory.
@@ -119,10 +117,8 @@ UDP_Recv_Error :: enum c.int {
Socket_Not_Bound = c.int(os.EINVAL), // The socket must be bound for this operation, but isn't.
}
// TODO
TCP_Send_Error :: enum c.int {
None = 0,
// TODO(tetra): merge with other errors?
Aborted = c.int(os.ECONNABORTED),
Connection_Closed = c.int(os.ECONNRESET),
Not_Connected = c.int(os.ENOTCONN),
@@ -135,16 +131,16 @@ TCP_Send_Error :: enum c.int {
// doesn't fit in the send queue.
No_Buffer_Space_Available = c.int(os.ENOBUFS),
Offline = c.int(os.ENETDOWN),
Host_Unreachable = c.int(os.EHOSTUNREACH), // A signal occurred before any data was transmitted. See signal(7).
Interrupted = c.int(os.EINTR), // The send timeout duration passed before all data was sent. See Socket_Option.Send_Timeout.
Timeout = c.int(os.EWOULDBLOCK), // NOTE: No, really. Presumably this means something different for nonblocking sockets...
Host_Unreachable = c.int(os.EHOSTUNREACH),
Interrupted = c.int(os.EINTR), // A signal occurred before any data was transmitted. See signal(7).
Timeout = c.int(os.EWOULDBLOCK), // The send timeout duration passed before all data was sent. See Socket_Option.Send_Timeout.
Not_Socket = c.int(os.ENOTSOCK), // The so-called socket is not an open socket.
}
// TODO
UDP_Send_Error :: enum c.int {
None = 0,
Message_Too_Long = c.int(os.EMSGSIZE), // The message is too big. No data was sent.
Message_Too_Long = c.int(os.EMSGSIZE), // The message is larger than the maximum UDP packet size. No data was sent.
// TODO: not sure what the exact circumstances for this is yet
Network_Unreachable = c.int(os.ENETUNREACH),
+5 -12
View File
@@ -92,8 +92,6 @@ TCP_Recv_Error :: enum c.int {
Not_Socket = win.WSAENOTSOCK,
Shutdown = win.WSAESHUTDOWN,
Would_Block = win.WSAEWOULDBLOCK,
// TODO: not functionally different from Reset; merge?
Aborted = win.WSAECONNABORTED,
Timeout = win.WSAETIMEDOUT,
@@ -107,11 +105,8 @@ TCP_Recv_Error :: enum c.int {
UDP_Recv_Error :: enum c.int {
None = 0,
Network_Subsystem_Failure = win.WSAENETDOWN,
// TODO: not functionally different from Reset; merge?
// UDP packets are limited in size, and the length of the incoming message exceeded it.
Aborted = win.WSAECONNABORTED,
Truncated = win.WSAEMSGSIZE,
Aborted = win.WSAECONNABORTED,
Buffer_Too_Small = win.WSAEMSGSIZE, // The buffer is too small to fit the entire message, and the message was truncated. When this happens, the rest of message is lost.
Remote_Not_Listening = win.WSAECONNRESET, // The machine at the remote endpoint doesn't have the given port open to receiving UDP data.
Shutdown = win.WSAESHUTDOWN,
Broadcast_Disabled = win.WSAEACCES, // A broadcast address was specified, but the .Broadcast socket option isn't set.
@@ -133,7 +128,6 @@ UDP_Recv_Error :: enum c.int {
TCP_Send_Error :: enum c.int {
None = 0,
// TODO: not functionally different from Reset; merge?
Aborted = win.WSAECONNABORTED,
Not_Connected = win.WSAENOTCONN,
Shutdown = win.WSAESHUTDOWN,
@@ -159,10 +153,9 @@ UDP_Send_Error :: enum c.int {
None = 0,
Network_Subsystem_Failure = win.WSAENETDOWN,
// TODO: not functionally different from Reset; merge?
Aborted = win.WSAECONNABORTED, // UDP packets are limited in size, and len(buf) exceeded it.
Message_Too_Long = win.WSAEMSGSIZE, // The machine at the remote endpoint doesn't have the given port open to receiving UDP data.
Remote_Not_Listening = win.WSAECONNRESET,
Aborted = win.WSAECONNABORTED,
Message_Too_Long = win.WSAEMSGSIZE, // The message is larger than the maximum UDP packet size.
Remote_Not_Listening = win.WSAECONNRESET, // The machine at the remote endpoint doesn't have the given port open to receiving UDP data.
Shutdown = win.WSAESHUTDOWN, // A broadcast address was specified, but the .Broadcast socket option isn't set.
Broadcast_Disabled = win.WSAEACCES,
Bad_Buffer = win.WSAEFAULT, // Connection is broken due to keepalive activity detecting a failure during the operation.
+39 -5
View File
@@ -284,6 +284,13 @@ Or_Return_Expr :: struct {
token: tokenizer.Token,
}
Or_Branch_Expr :: struct {
using node: Expr,
expr: ^Expr,
token: tokenizer.Token,
label: ^Expr,
}
Type_Assertion :: struct {
using node: Expr,
expr: ^Expr,
@@ -419,6 +426,7 @@ Range_Stmt :: struct {
in_pos: tokenizer.Pos,
expr: ^Expr,
body: ^Stmt,
reverse: bool,
}
Inline_Range_Stmt :: struct {
@@ -543,8 +551,8 @@ unparen_expr :: proc(expr: ^Expr) -> (val: ^Expr) {
return
}
for {
e, ok := val.derived.(^Paren_Expr)
if !ok || e.expr == nil {
e := val.derived.(^Paren_Expr) or_break
if e.expr == nil {
break
}
val = e.expr
@@ -552,6 +560,29 @@ unparen_expr :: proc(expr: ^Expr) -> (val: ^Expr) {
return
}
strip_or_return_expr :: proc(expr: ^Expr) -> (val: ^Expr) {
val = expr
if expr == nil {
return
}
for {
inner: ^Expr
#partial switch e in val.derived {
case ^Or_Return_Expr:
inner = e.expr
case ^Or_Branch_Expr:
inner = e.expr
case ^Paren_Expr:
inner = e.expr
}
if inner == nil {
break
}
val = inner
}
return
}
Field_Flags :: distinct bit_set[Field_Flag]
Field_Flag :: enum {
@@ -562,7 +593,7 @@ Field_Flag :: enum {
Using,
No_Alias,
C_Vararg,
Auto_Cast,
Const,
Any_Int,
Subtype,
By_Ptr,
@@ -581,7 +612,7 @@ field_flag_strings := [Field_Flag]string{
.Using = "using",
.No_Alias = "#no_alias",
.C_Vararg = "#c_vararg",
.Auto_Cast = "auto_cast",
.Const = "#const",
.Any_Int = "#any_int",
.Subtype = "#subtype",
.By_Ptr = "#by_ptr",
@@ -595,6 +626,7 @@ field_flag_strings := [Field_Flag]string{
field_hash_flag_strings := []struct{key: string, flag: Field_Flag}{
{"no_alias", .No_Alias},
{"c_vararg", .C_Vararg},
{"const", .Const},
{"any_int", .Any_Int},
{"subtype", .Subtype},
{"by_ptr", .By_Ptr},
@@ -615,7 +647,7 @@ Field_Flags_Signature :: Field_Flags{
.Using,
.No_Alias,
.C_Vararg,
.Auto_Cast,
.Const,
.Any_Int,
.By_Ptr,
.Default_Parameters,
@@ -837,6 +869,7 @@ Any_Node :: union {
^Ternary_When_Expr,
^Or_Else_Expr,
^Or_Return_Expr,
^Or_Branch_Expr,
^Type_Assertion,
^Type_Cast,
^Auto_Cast,
@@ -920,6 +953,7 @@ Any_Expr :: union {
^Ternary_When_Expr,
^Or_Else_Expr,
^Or_Return_Expr,
^Or_Branch_Expr,
^Type_Assertion,
^Type_Cast,
^Auto_Cast,
+6 -3
View File
@@ -77,7 +77,7 @@ clone_node :: proc(node: ^Node) -> ^Node {
align = elem.align
}
#partial switch in node.derived {
#partial switch _ in node.derived {
case ^Package, ^File:
panic("Cannot clone this node type")
}
@@ -147,8 +147,8 @@ clone_node :: proc(node: ^Node) -> ^Node {
r.expr = clone(r.expr)
r.index = clone(r.index)
case ^Matrix_Index_Expr:
r.expr = clone(r.expr)
r.row_index = clone(r.row_index)
r.expr = clone(r.expr)
r.row_index = clone(r.row_index)
r.column_index = clone(r.column_index)
case ^Deref_Expr:
r.expr = clone(r.expr)
@@ -175,6 +175,9 @@ clone_node :: proc(node: ^Node) -> ^Node {
r.y = clone(r.y)
case ^Or_Return_Expr:
r.expr = clone(r.expr)
case ^Or_Branch_Expr:
r.expr = clone(r.expr)
r.label = clone(r.label)
case ^Type_Assertion:
r.expr = clone(r.expr)
r.type = clone(r.type)
+5
View File
@@ -146,6 +146,11 @@ walk :: proc(v: ^Visitor, node: ^Node) {
walk(v, n.y)
case ^Or_Return_Expr:
walk(v, n.expr)
case ^Or_Branch_Expr:
walk(v, n.expr)
if n.label != nil {
walk(v, n.label)
}
case ^Type_Assertion:
walk(v, n.expr)
if n.type != nil {
+25 -25
View File
@@ -162,31 +162,31 @@ Attribute :: struct {
}
Type_Kind :: enum u32le {
Invalid = 0,
Basic = 1,
Named = 2,
Generic = 3,
Pointer = 4,
Array = 5,
Enumerated_Array = 6,
Slice = 7,
Dynamic_Array = 8,
Map = 9,
Struct = 10,
Union = 11,
Enum = 12,
Tuple = 13,
Proc = 14,
Bit_Set = 15,
Simd_Vector = 16,
SOA_Struct_Fixed = 17,
SOA_Struct_Slice = 18,
SOA_Struct_Dynamic = 19,
Relative_Pointer = 20,
Relative_Slice = 21,
Multi_Pointer = 22,
Matrix = 23,
Soa_Pointer = 24,
Invalid = 0,
Basic = 1,
Named = 2,
Generic = 3,
Pointer = 4,
Array = 5,
Enumerated_Array = 6,
Slice = 7,
Dynamic_Array = 8,
Map = 9,
Struct = 10,
Union = 11,
Enum = 12,
Tuple = 13,
Proc = 14,
Bit_Set = 15,
Simd_Vector = 16,
SOA_Struct_Fixed = 17,
SOA_Struct_Slice = 18,
SOA_Struct_Dynamic = 19,
Relative_Pointer = 20,
Relative_Multi_Pointer = 21,
Multi_Pointer = 22,
Matrix = 23,
Soa_Pointer = 24,
}
Type_Elems_Cap :: 4
+50 -33
View File
@@ -420,7 +420,7 @@ expect_closing_brace_of_field_list :: proc(p: ^Parser) -> tokenizer.Token {
if allow_token(p, .Close_Brace) {
return token
}
if allow_token(p, .Semicolon) {
if allow_token(p, .Semicolon) && !tokenizer.is_newline(token) {
str := tokenizer.token_to_string(token)
error(p, end_of_line_pos(p, p.prev_tok), "expected a comma, got %s", str)
}
@@ -1053,9 +1053,7 @@ parse_attribute :: proc(p: ^Parser, tok: tokenizer.Token, open_kind, close_kind:
}
append(&elems, elem)
if !allow_token(p, .Comma) {
break
}
allow_token(p, .Comma) or_break
}
p.expr_level -= 1
close = expect_token_after(p, close_kind, "attribute")
@@ -1091,7 +1089,7 @@ parse_attribute :: proc(p: ^Parser, tok: tokenizer.Token, open_kind, close_kind:
parse_foreign_block_decl :: proc(p: ^Parser) -> ^ast.Stmt {
decl := parse_stmt(p)
#partial switch in decl.derived_stmt {
#partial switch _ in decl.derived_stmt {
case ^ast.Empty_Stmt, ^ast.Bad_Stmt, ^ast.Bad_Decl:
// Ignore
return nil
@@ -1174,9 +1172,7 @@ parse_foreign_decl :: proc(p: ^Parser) -> ^ast.Decl {
path := expect_token(p, .String)
append(&fullpaths, path.text)
if !allow_token(p, .Comma) {
break
}
allow_token(p, .Comma) or_break
}
expect_token(p, .Close_Brace)
} else {
@@ -1431,6 +1427,18 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt {
return es
case "unroll":
return parse_unrolled_for_loop(p, tag)
case "reverse":
stmt := parse_for_stmt(p)
if range, is_range := stmt.derived.(^ast.Range_Stmt); is_range {
if range.reverse {
error(p, range.pos, "#reverse already applied to a 'for in' statement")
}
range.reverse = true
} else {
error(p, range.pos, "#reverse can only be applied to a 'for in' statement")
}
return stmt
case "include":
error(p, tag.pos, "#include is not a valid import declaration kind. Did you meant 'import'?")
return ast.new(ast.Bad_Stmt, tok.pos, end_pos(tag))
@@ -1654,9 +1662,6 @@ is_token_field_prefix :: proc(p: ^Parser) -> ast.Field_Flag {
case .Using:
advance_token(p)
return .Using
case .Auto_Cast:
advance_token(p)
return .Auto_Cast
case .Hash:
tok: tokenizer.Token
advance_token(p)
@@ -1836,7 +1841,9 @@ parse_field_list :: proc(p: ^Parser, follow: tokenizer.Token_Kind, allowed_flags
return true
}
if allow_token(p, .Semicolon) {
error(p, tok.pos, "expected a comma, got a semicolon")
if !tokenizer.is_newline(tok) {
error(p, tok.pos, "expected a comma, got a semicolon")
}
return true
}
return false
@@ -1950,9 +1957,7 @@ parse_field_list :: proc(p: ^Parser, follow: tokenizer.Token_Kind, allowed_flags
eaf := Expr_And_Flags{param, prefix_flags}
append(&list, eaf)
if !allow_token(p, .Comma) {
break
}
allow_token(p, .Comma) or_break
}
if p.curr_tok.kind != .Colon {
@@ -2000,10 +2005,7 @@ parse_field_list :: proc(p: ^Parser, follow: tokenizer.Token_Kind, allowed_flags
names = parse_ident_list(p, allow_poly_names)
total_name_count += len(names)
ok := handle_field(p, &seen_ellipsis, &fields, docs, names, allowed_flags, set_flags)
if !ok {
break
}
handle_field(p, &seen_ellipsis, &fields, docs, names, allowed_flags, set_flags) or_break
}
}
@@ -2139,7 +2141,7 @@ parse_inlining_operand :: proc(p: ^Parser, lhs: bool, tok: tokenizer.Token) -> ^
}
}
#partial switch e in ast.unparen_expr(expr).derived_expr {
#partial switch e in ast.strip_or_return_expr(expr).derived_expr {
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")
@@ -2350,9 +2352,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
elem := parse_expr(p, false)
append(&args, elem)
if !allow_token(p, .Comma) {
break
}
allow_token(p, .Comma) or_break
}
close := expect_token(p, .Close_Brace)
@@ -2685,9 +2685,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
if _, ok := type.derived.(^ast.Bad_Expr); !ok {
append(&variants, type)
}
if !allow_token(p, .Comma) {
break
}
allow_token(p, .Comma) or_break
}
close := expect_closing_brace_of_field_list(p)
@@ -2905,9 +2903,7 @@ parse_elem_list :: proc(p: ^Parser) -> []^ast.Expr {
append(&elems, elem)
if !allow_token(p, .Comma) {
break
}
allow_token(p, .Comma) or_break
}
return elems[:]
@@ -2941,9 +2937,9 @@ parse_call_expr :: proc(p: ^Parser, operand: ^ast.Expr) -> ^ast.Expr {
p.expr_level += 1
open := expect_token(p, .Open_Paren)
seen_ellipsis := false
for p.curr_tok.kind != .Close_Paren &&
p.curr_tok.kind != .EOF &&
ellipsis.pos.line == 0 {
p.curr_tok.kind != .EOF {
if p.curr_tok.kind == .Comma {
error(p, p.curr_tok.pos, "expected an expression not ,")
@@ -2972,13 +2968,17 @@ parse_call_expr :: proc(p: ^Parser, operand: ^ast.Expr) -> ^ast.Expr {
fv.value = value
arg = fv
} else if seen_ellipsis {
error(p, arg.pos, "Positional arguments are not allowed after '..'")
}
append(&args, arg)
if !allow_token(p, .Comma) {
break
if ellipsis.pos.line != 0 {
seen_ellipsis = true
}
allow_token(p, .Comma) or_break
}
close := expect_token_after(p, .Close_Paren, "argument list")
@@ -3173,6 +3173,23 @@ parse_atom_expr :: proc(p: ^Parser, value: ^ast.Expr, lhs: bool) -> (operand: ^a
operand = oe
case .Or_Break, .Or_Continue:
token := advance_token(p)
label: ^ast.Ident
end := end_pos(token)
if p.curr_tok.kind == .Ident {
end = end_pos(p.curr_tok)
label = parse_ident(p)
}
oe := ast.new(ast.Or_Branch_Expr, operand.pos, end)
oe.expr = operand
oe.token = token
oe.label = label
operand = oe
case .Open_Brace:
if !is_lhs && is_literal_type(operand) && p.expr_level >= 0 {
operand = parse_literal_value(p, operand)
+7
View File
@@ -972,6 +972,13 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, options := List_Options{}) {
case ^ast.Or_Return_Expr:
visit_expr(p, v.expr)
push_generic_token(p, v.token.kind, 1)
case ^ast.Or_Branch_Expr:
visit_expr(p, v.expr)
push_generic_token(p, v.token.kind, 1)
if v.label != nil {
visit_expr(p, v.label)
}
case ^ast.Selector_Call_Expr:
visit_expr(p, v.call.expr)
push_generic_token(p, .Open_Paren, 1)
+4
View File
@@ -147,6 +147,8 @@ Token_Kind :: enum u32 {
Context, // context
Or_Else, // or_else
Or_Return, // or_return
Or_Break, // or_break
Or_Continue, // or_continue
Asm, // asm
Inline, // inline
No_Inline, // no_inline
@@ -278,6 +280,8 @@ tokens := [Token_Kind.COUNT]string {
"context",
"or_else",
"or_return",
"or_break",
"or_continue",
"asm",
"inline",
"no_inline",
+1 -1
View File
@@ -124,7 +124,7 @@ Allocation_Header :: struct #raw_union {
requested: u64,
}
Region_Header :: struct #align 16 {
Region_Header :: struct #align(16) {
next_region: ^Region, // points to next region in global_heap (linked list)
local_addr: ^^Region, // tracks region ownership via address of _local_region
reset_addr: ^^Region, // tracks old local addr for reset
+2 -2
View File
@@ -441,7 +441,7 @@ pollfd :: struct {
sigset_t :: distinct u64
foreign libc {
@(link_name="__errno_location") __errno_location :: proc() -> ^int ---
@(link_name="__errno_location") __errno_location :: proc() -> ^c.int ---
@(link_name="getpagesize") _unix_getpagesize :: proc() -> c.int ---
@(link_name="get_nprocs") _unix_get_nprocs :: proc() -> c.int ---
@@ -488,7 +488,7 @@ _get_errno :: proc(res: int) -> Errno {
// get errno from libc
get_last_error :: proc "contextless" () -> int {
return __errno_location()^
return int(__errno_location()^)
}
personality :: proc(persona: u64) -> (Errno) {
+1 -3
View File
@@ -99,9 +99,7 @@ scan_chunk :: proc(pattern: string) -> (star: bool, chunk, rest: string) {
case ']':
in_range = false
case '*':
if !in_range {
break scan_loop
}
in_range or_break scan_loop
}
}
+3 -4
View File
@@ -392,9 +392,8 @@ rel :: proc(base_path, target_path: string, allocator := context.allocator) -> (
for ti < tl && target[ti] != SEPARATOR {
ti += 1
}
if !strings.equal_fold(target[t0:ti], base[b0:bi]) {
break
}
strings.equal_fold(target[t0:ti], base[b0:bi]) or_break
if bi < bl {
bi += 1
}
@@ -416,7 +415,7 @@ rel :: proc(base_path, target_path: string, allocator := context.allocator) -> (
}
buf := make([]byte, size)
n := copy(buf, "..")
for in 0..<seps {
for _ in 0..<seps {
buf[n] = SEPARATOR
copy(buf[n+1:], "..")
n += 3
+1 -4
View File
@@ -93,10 +93,7 @@ scan_chunk :: proc(pattern: string) -> (star: bool, chunk, rest: string) {
case ']':
in_range = false
case '*':
if !in_range {
break scan_loop
}
in_range or_break scan_loop
}
}
return star, pattern[:i], pattern[i:]
+59 -60
View File
@@ -8,35 +8,35 @@ _ :: intrinsics
Type_Info :: runtime.Type_Info
Type_Info_Named :: runtime.Type_Info_Named
Type_Info_Integer :: runtime.Type_Info_Integer
Type_Info_Rune :: runtime.Type_Info_Rune
Type_Info_Float :: runtime.Type_Info_Float
Type_Info_Complex :: runtime.Type_Info_Complex
Type_Info_Quaternion :: runtime.Type_Info_Quaternion
Type_Info_String :: runtime.Type_Info_String
Type_Info_Boolean :: runtime.Type_Info_Boolean
Type_Info_Any :: runtime.Type_Info_Any
Type_Info_Type_Id :: runtime.Type_Info_Type_Id
Type_Info_Pointer :: runtime.Type_Info_Pointer
Type_Info_Multi_Pointer :: runtime.Type_Info_Multi_Pointer
Type_Info_Procedure :: runtime.Type_Info_Procedure
Type_Info_Array :: runtime.Type_Info_Array
Type_Info_Enumerated_Array :: runtime.Type_Info_Enumerated_Array
Type_Info_Dynamic_Array :: runtime.Type_Info_Dynamic_Array
Type_Info_Slice :: runtime.Type_Info_Slice
Type_Info_Parameters :: runtime.Type_Info_Parameters
Type_Info_Tuple :: runtime.Type_Info_Parameters
Type_Info_Struct :: runtime.Type_Info_Struct
Type_Info_Union :: runtime.Type_Info_Union
Type_Info_Enum :: runtime.Type_Info_Enum
Type_Info_Map :: runtime.Type_Info_Map
Type_Info_Bit_Set :: runtime.Type_Info_Bit_Set
Type_Info_Simd_Vector :: runtime.Type_Info_Simd_Vector
Type_Info_Relative_Pointer :: runtime.Type_Info_Relative_Pointer
Type_Info_Relative_Slice :: runtime.Type_Info_Relative_Slice
Type_Info_Matrix :: runtime.Type_Info_Matrix
Type_Info_Soa_Pointer :: runtime.Type_Info_Soa_Pointer
Type_Info_Named :: runtime.Type_Info_Named
Type_Info_Integer :: runtime.Type_Info_Integer
Type_Info_Rune :: runtime.Type_Info_Rune
Type_Info_Float :: runtime.Type_Info_Float
Type_Info_Complex :: runtime.Type_Info_Complex
Type_Info_Quaternion :: runtime.Type_Info_Quaternion
Type_Info_String :: runtime.Type_Info_String
Type_Info_Boolean :: runtime.Type_Info_Boolean
Type_Info_Any :: runtime.Type_Info_Any
Type_Info_Type_Id :: runtime.Type_Info_Type_Id
Type_Info_Pointer :: runtime.Type_Info_Pointer
Type_Info_Multi_Pointer :: runtime.Type_Info_Multi_Pointer
Type_Info_Procedure :: runtime.Type_Info_Procedure
Type_Info_Array :: runtime.Type_Info_Array
Type_Info_Enumerated_Array :: runtime.Type_Info_Enumerated_Array
Type_Info_Dynamic_Array :: runtime.Type_Info_Dynamic_Array
Type_Info_Slice :: runtime.Type_Info_Slice
Type_Info_Parameters :: runtime.Type_Info_Parameters
Type_Info_Tuple :: runtime.Type_Info_Parameters
Type_Info_Struct :: runtime.Type_Info_Struct
Type_Info_Union :: runtime.Type_Info_Union
Type_Info_Enum :: runtime.Type_Info_Enum
Type_Info_Map :: runtime.Type_Info_Map
Type_Info_Bit_Set :: runtime.Type_Info_Bit_Set
Type_Info_Simd_Vector :: runtime.Type_Info_Simd_Vector
Type_Info_Relative_Pointer :: runtime.Type_Info_Relative_Pointer
Type_Info_Relative_Multi_Pointer :: runtime.Type_Info_Relative_Multi_Pointer
Type_Info_Matrix :: runtime.Type_Info_Matrix
Type_Info_Soa_Pointer :: runtime.Type_Info_Soa_Pointer
Type_Info_Enum_Value :: runtime.Type_Info_Enum_Value
@@ -69,7 +69,7 @@ Type_Kind :: enum {
Bit_Set,
Simd_Vector,
Relative_Pointer,
Relative_Slice,
Relative_Multi_Pointer,
Matrix,
Soa_Pointer,
}
@@ -80,34 +80,34 @@ type_kind :: proc(T: typeid) -> Type_Kind {
ti := type_info_of(T)
if ti != nil {
switch _ in ti.variant {
case Type_Info_Named: return .Named
case Type_Info_Integer: return .Integer
case Type_Info_Rune: return .Rune
case Type_Info_Float: return .Float
case Type_Info_Complex: return .Complex
case Type_Info_Quaternion: return .Quaternion
case Type_Info_String: return .String
case Type_Info_Boolean: return .Boolean
case Type_Info_Any: return .Any
case Type_Info_Type_Id: return .Type_Id
case Type_Info_Pointer: return .Pointer
case Type_Info_Multi_Pointer: return .Multi_Pointer
case Type_Info_Procedure: return .Procedure
case Type_Info_Array: return .Array
case Type_Info_Enumerated_Array: return .Enumerated_Array
case Type_Info_Dynamic_Array: return .Dynamic_Array
case Type_Info_Slice: return .Slice
case Type_Info_Parameters: return .Tuple
case Type_Info_Struct: return .Struct
case Type_Info_Union: return .Union
case Type_Info_Enum: return .Enum
case Type_Info_Map: return .Map
case Type_Info_Bit_Set: return .Bit_Set
case Type_Info_Simd_Vector: return .Simd_Vector
case Type_Info_Relative_Pointer: return .Relative_Pointer
case Type_Info_Relative_Slice: return .Relative_Slice
case Type_Info_Matrix: return .Matrix
case Type_Info_Soa_Pointer: return .Soa_Pointer
case Type_Info_Named: return .Named
case Type_Info_Integer: return .Integer
case Type_Info_Rune: return .Rune
case Type_Info_Float: return .Float
case Type_Info_Complex: return .Complex
case Type_Info_Quaternion: return .Quaternion
case Type_Info_String: return .String
case Type_Info_Boolean: return .Boolean
case Type_Info_Any: return .Any
case Type_Info_Type_Id: return .Type_Id
case Type_Info_Pointer: return .Pointer
case Type_Info_Multi_Pointer: return .Multi_Pointer
case Type_Info_Procedure: return .Procedure
case Type_Info_Array: return .Array
case Type_Info_Enumerated_Array: return .Enumerated_Array
case Type_Info_Dynamic_Array: return .Dynamic_Array
case Type_Info_Slice: return .Slice
case Type_Info_Parameters: return .Tuple
case Type_Info_Struct: return .Struct
case Type_Info_Union: return .Union
case Type_Info_Enum: return .Enum
case Type_Info_Map: return .Map
case Type_Info_Bit_Set: return .Bit_Set
case Type_Info_Simd_Vector: return .Simd_Vector
case Type_Info_Relative_Pointer: return .Relative_Pointer
case Type_Info_Relative_Multi_Pointer: return .Relative_Multi_Pointer
case Type_Info_Matrix: return .Matrix
case Type_Info_Soa_Pointer: return .Soa_Pointer
}
}
@@ -1457,8 +1457,6 @@ equal :: proc(a, b: any, including_indirect_array_recursion := false, recursion_
return equal(va, vb, including_indirect_array_recursion, recursion_level+1)
case Type_Info_Map:
return false
case Type_Info_Relative_Slice:
return false
case
Type_Info_Boolean,
Type_Info_Integer,
@@ -1474,6 +1472,7 @@ equal :: proc(a, b: any, including_indirect_array_recursion := false, recursion_
Type_Info_Enum,
Type_Info_Simd_Vector,
Type_Info_Relative_Pointer,
Type_Info_Relative_Multi_Pointer,
Type_Info_Soa_Pointer,
Type_Info_Matrix:
return runtime.memory_compare(a.data, b.data, t.size) == 0
+11 -12
View File
@@ -165,9 +165,9 @@ are_types_identical :: proc(a, b: ^Type_Info) -> bool {
y := b.variant.(Type_Info_Relative_Pointer) or_return
return x.base_integer == y.base_integer && x.pointer == y.pointer
case Type_Info_Relative_Slice:
y := b.variant.(Type_Info_Relative_Slice) or_return
return x.base_integer == y.base_integer && x.slice == y.slice
case Type_Info_Relative_Multi_Pointer:
y := b.variant.(Type_Info_Relative_Multi_Pointer) or_return
return x.base_integer == y.base_integer && x.pointer == y.pointer
case Type_Info_Matrix:
y := b.variant.(Type_Info_Matrix) or_return
@@ -383,9 +383,9 @@ is_relative_pointer :: proc(info: ^Type_Info) -> bool {
return ok
}
@(require_results)
is_relative_slice :: proc(info: ^Type_Info) -> bool {
is_relative_multi_pointer :: proc(info: ^Type_Info) -> bool {
if info == nil { return false }
_, ok := type_info_base(info).variant.(Type_Info_Relative_Slice)
_, ok := type_info_base(info).variant.(Type_Info_Relative_Multi_Pointer)
return ok
}
@@ -395,7 +395,6 @@ is_relative_slice :: proc(info: ^Type_Info) -> bool {
write_typeid_builder :: proc(buf: ^strings.Builder, id: typeid, n_written: ^int = nil) -> (n: int, err: io.Error) {
return write_type_writer(strings.to_writer(buf), type_info_of(id))
}
@@ -581,9 +580,9 @@ write_type_writer :: proc(w: io.Writer, ti: ^Type_Info, n_written: ^int = nil) -
if info.is_packed { io.write_string(w, "#packed ", &n) or_return }
if info.is_raw_union { io.write_string(w, "#raw_union ", &n) or_return }
if info.custom_align {
io.write_string(w, "#align ", &n) or_return
io.write_string(w, "#align(", &n) or_return
io.write_i64(w, i64(ti.align), 10, &n) or_return
io.write_byte(w, ' ', &n) or_return
io.write_string(w, ") ", &n) or_return
}
io.write_byte(w, '{', &n) or_return
for name, i in info.names {
@@ -599,9 +598,9 @@ write_type_writer :: proc(w: io.Writer, ti: ^Type_Info, n_written: ^int = nil) -
if info.no_nil { io.write_string(w, "#no_nil ", &n) or_return }
if info.shared_nil { io.write_string(w, "#shared_nil ", &n) or_return }
if info.custom_align {
io.write_string(w, "#align ", &n) or_return
io.write_string(w, "#align(", &n) or_return
io.write_i64(w, i64(ti.align), 10, &n) or_return
io.write_byte(w, ' ', &n) or_return
io.write_string(w, ") ", &n) or_return
}
io.write_byte(w, '{', &n) or_return
for variant, i in info.variants {
@@ -652,11 +651,11 @@ write_type_writer :: proc(w: io.Writer, ti: ^Type_Info, n_written: ^int = nil) -
io.write_string(w, ") ", &n) or_return
write_type(w, info.pointer, &n) or_return
case Type_Info_Relative_Slice:
case Type_Info_Relative_Multi_Pointer:
io.write_string(w, "#relative(", &n) or_return
write_type(w, info.base_integer, &n) or_return
io.write_string(w, ") ", &n) or_return
write_type(w, info.slice, &n) or_return
write_type(w, info.pointer, &n) or_return
case Type_Info_Matrix:
io.write_string(w, "matrix[", &n) or_return
+32 -6
View File
@@ -162,11 +162,11 @@ Type_Info_Simd_Vector :: struct {
count: int,
}
Type_Info_Relative_Pointer :: struct {
pointer: ^Type_Info,
pointer: ^Type_Info, // ^T
base_integer: ^Type_Info,
}
Type_Info_Relative_Slice :: struct {
slice: ^Type_Info,
Type_Info_Relative_Multi_Pointer :: struct {
pointer: ^Type_Info, // [^]T
base_integer: ^Type_Info,
}
Type_Info_Matrix :: struct {
@@ -219,7 +219,7 @@ Type_Info :: struct {
Type_Info_Bit_Set,
Type_Info_Simd_Vector,
Type_Info_Relative_Pointer,
Type_Info_Relative_Slice,
Type_Info_Relative_Multi_Pointer,
Type_Info_Matrix,
Type_Info_Soa_Pointer,
},
@@ -252,12 +252,13 @@ Typeid_Kind :: enum u8 {
Bit_Set,
Simd_Vector,
Relative_Pointer,
Relative_Slice,
Relative_Multi_Pointer,
Matrix,
Soa_Pointer,
}
#assert(len(Typeid_Kind) < 32)
// Typeid_Bit_Field :: bit_field #align align_of(uintptr) {
// Typeid_Bit_Field :: bit_field #align(align_of(uintptr)) {
// index: 8*size_of(uintptr) - 8,
// kind: 5, // Typeid_Kind
// named: 1,
@@ -337,6 +338,8 @@ Kilobyte :: 1024 * Byte
Megabyte :: 1024 * Kilobyte
Gigabyte :: 1024 * Megabyte
Terabyte :: 1024 * Gigabyte
Petabyte :: 1024 * Terabyte
Exabyte :: 1024 * Petabyte
// Logging stuff
@@ -499,6 +502,29 @@ Odin_Build_Mode_Type :: type_of(ODIN_BUILD_MODE)
Odin_Endian_Type :: type_of(ODIN_ENDIAN)
/*
// Defined internally by the compiler
Odin_Platform_Subtarget_Type :: enum int {
Default,
iOS,
}
*/
Odin_Platform_Subtarget_Type :: type_of(ODIN_PLATFORM_SUBTARGET)
/*
// Defined internally by the compiler
Odin_Sanitizer_Flag :: enum u32 {
Address = 0,
Memory = 1,
Thread = 2,
}
Odin_Sanitizer_Flags :: distinct bitset[Odin_Sanitizer_Flag; u32]
ODIN_SANITIZER_FLAGS // is a constant
*/
Odin_Sanitizer_Flags :: type_of(ODIN_SANITIZER_FLAGS)
/////////////////////////////
// Init Startup Procedures //
/////////////////////////////
+6 -5
View File
@@ -601,14 +601,15 @@ assign_at_elems :: proc(array: ^$T/[dynamic]$E, index: int, args: ..E, loc := #c
@builtin
assign_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, index: int, arg: string, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
if len(args) == 0 {
new_size := index + len(arg)
if len(arg) == 0 {
ok = true
} else if index+len(args) < len(array) {
copy(array[index:], args)
} else if new_size < len(array) {
copy(array[index:], arg)
ok = true
} else {
resize(array, index+1+len(args), loc) or_return
copy(array[index:], args)
resize(array, new_size, loc) or_return
copy(array[index:], arg)
ok = true
}
return
+5 -2
View File
@@ -4,13 +4,16 @@
//+build !js
package runtime
// TODO(bill): reimplement these procedures in the os_specific stuff
import "core:os"
when ODIN_DEFAULT_TO_NIL_ALLOCATOR {
_ :: os
// mem.nil_allocator reimplementation
default_allocator_proc :: nil_allocator_proc
default_allocator :: nil_allocator
} else {
// TODO(bill): reimplement these procedures in the os_specific stuff
import "core:os"
default_allocator_proc :: os.heap_allocator_proc
+1 -1
View File
@@ -87,7 +87,7 @@ MAP_CACHE_LINE_SIZE :: 1 << MAP_CACHE_LINE_LOG2
//
// In the optimal case, len(Map_Cell(T){}.data) = 1 so the cell array can be treated
// as a regular array of T, which is the case for hashes.
Map_Cell :: struct($T: typeid) #align MAP_CACHE_LINE_SIZE {
Map_Cell :: struct($T: typeid) #align(MAP_CACHE_LINE_SIZE) {
data: [MAP_CACHE_LINE_SIZE / size_of(T) when 0 < size_of(T) && size_of(T) < MAP_CACHE_LINE_SIZE else 1]T,
}
+68 -13
View File
@@ -11,7 +11,10 @@ RUNTIME_LINKAGE :: "strong" when (
ODIN_BUILD_MODE == .Dynamic ||
!ODIN_NO_CRT) &&
!IS_WASM) else "internal"
RUNTIME_REQUIRE :: true
RUNTIME_REQUIRE :: !ODIN_TILDE
@(private)
__float16 :: f16 when __ODIN_LLVM_F16_SUPPORTED else u16
@(private)
@@ -218,10 +221,18 @@ memory_equal :: proc "contextless" (x, y: rawptr, n: int) -> bool {
case n == 0: return true
case x == y: return true
}
a, b := ([^]byte)(x), ([^]byte)(y)
length := uint(n)
for i := uint(0); i < length; i += 1 {
if a[i] != b[i] {
return false
}
}
return true
/*
when size_of(uint) == 8 {
if word_length := length >> 3; word_length != 0 {
for _ in 0..<word_length {
@@ -276,6 +287,7 @@ memory_equal :: proc "contextless" (x, y: rawptr, n: int) -> bool {
return true
}
*/
}
memory_compare :: proc "contextless" (a, b: rawptr, n: int) -> int #no_bounds_check {
@@ -401,6 +413,48 @@ cstring_to_string :: proc "contextless" (s: cstring) -> string {
}
cstring_eq :: proc "contextless" (lhs, rhs: cstring) -> bool {
x := ([^]byte)(lhs)
y := ([^]byte)(rhs)
if x == y {
return true
}
if (x == nil) ~ (y == nil) {
return false
}
xn := cstring_len(lhs)
yn := cstring_len(rhs)
if xn != yn {
return false
}
return #force_inline memory_equal(x, y, xn)
}
cstring_cmp :: proc "contextless" (lhs, rhs: cstring) -> int {
x := ([^]byte)(lhs)
y := ([^]byte)(rhs)
if x == y {
return 0
}
if (x == nil) ~ (y == nil) {
return -1 if x == nil else +1
}
xn := cstring_len(lhs)
yn := cstring_len(rhs)
ret := memory_compare(x, y, min(xn, yn))
if ret == 0 && xn != yn {
return -1 if xn < yn else +1
}
return ret
}
cstring_ne :: #force_inline proc "contextless" (a, b: cstring) -> bool { return !cstring_eq(a, b) }
cstring_lt :: #force_inline proc "contextless" (a, b: cstring) -> bool { return cstring_cmp(a, b) < 0 }
cstring_gt :: #force_inline proc "contextless" (a, b: cstring) -> bool { return cstring_cmp(a, b) > 0 }
cstring_le :: #force_inline proc "contextless" (a, b: cstring) -> bool { return cstring_cmp(a, b) <= 0 }
cstring_ge :: #force_inline proc "contextless" (a, b: cstring) -> bool { return cstring_cmp(a, b) >= 0 }
complex32_eq :: #force_inline proc "contextless" (a, b: complex32) -> bool { return real(a) == real(b) && imag(a) == imag(b) }
complex32_ne :: #force_inline proc "contextless" (a, b: complex32) -> bool { return real(a) != real(b) || imag(a) != imag(b) }
@@ -746,7 +800,7 @@ quo_quaternion256 :: proc "contextless" (q, r: quaternion256) -> quaternion256 {
}
@(link_name="__truncsfhf2", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
truncsfhf2 :: proc "c" (value: f32) -> u16 {
truncsfhf2 :: proc "c" (value: f32) -> __float16 {
v: struct #raw_union { i: u32, f: f32 }
i, s, e, m: i32
@@ -760,7 +814,7 @@ truncsfhf2 :: proc "c" (value: f32) -> u16 {
if e <= 0 {
if e < -10 {
return u16(s)
return transmute(__float16)u16(s)
}
m = (m | 0x00800000) >> u32(1 - e)
@@ -768,14 +822,14 @@ truncsfhf2 :: proc "c" (value: f32) -> u16 {
m += 0x00002000
}
return u16(s | (m >> 13))
return transmute(__float16)u16(s | (m >> 13))
} else if e == 0xff - (127 - 15) {
if m == 0 {
return u16(s | 0x7c00) /* NOTE(bill): infinity */
return transmute(__float16)u16(s | 0x7c00) /* NOTE(bill): infinity */
} else {
/* NOTE(bill): NAN */
m >>= 13
return u16(s | 0x7c00 | m | i32(m == 0))
return transmute(__float16)u16(s | 0x7c00 | m | i32(m == 0))
}
} else {
if m & 0x00001000 != 0 {
@@ -795,23 +849,24 @@ truncsfhf2 :: proc "c" (value: f32) -> u16 {
intrinsics.volatile_store(&f, g)
}
return u16(s | 0x7c00)
return transmute(__float16)u16(s | 0x7c00)
}
return u16(s | (e << 10) | (m >> 13))
return transmute(__float16)u16(s | (e << 10) | (m >> 13))
}
}
@(link_name="__truncdfhf2", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
truncdfhf2 :: proc "c" (value: f64) -> u16 {
truncdfhf2 :: proc "c" (value: f64) -> __float16 {
return truncsfhf2(f32(value))
}
@(link_name="__gnu_h2f_ieee", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
gnu_h2f_ieee :: proc "c" (value: u16) -> f32 {
gnu_h2f_ieee :: proc "c" (value_: __float16) -> f32 {
fp32 :: struct #raw_union { u: u32, f: f32 }
value := transmute(u16)value_
v: fp32
magic, inf_or_nan: fp32
magic.u = u32((254 - 15) << 23)
@@ -828,12 +883,12 @@ gnu_h2f_ieee :: proc "c" (value: u16) -> f32 {
@(link_name="__gnu_f2h_ieee", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
gnu_f2h_ieee :: proc "c" (value: f32) -> u16 {
gnu_f2h_ieee :: proc "c" (value: f32) -> __float16 {
return truncsfhf2(value)
}
@(link_name="__extendhfsf2", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
extendhfsf2 :: proc "c" (value: u16) -> f32 {
extendhfsf2 :: proc "c" (value: __float16) -> f32 {
return gnu_h2f_ieee(value)
}
+6 -9
View File
@@ -1,9 +1,6 @@
//+private
//+build windows
package runtime
import "core:intrinsics"
foreign import kernel32 "system:Kernel32.lib"
@(private="file")
@@ -102,12 +99,12 @@ _windows_default_alloc_or_resize :: proc "contextless" (size, alignment: int, ol
allocated_mem: rawptr
if old_ptr != nil {
original_old_ptr := intrinsics.ptr_offset((^rawptr)(old_ptr), -1)^
original_old_ptr := ([^]rawptr)(old_ptr)[-1]
allocated_mem = heap_resize(original_old_ptr, space+size_of(rawptr))
} else {
allocated_mem = heap_alloc(space+size_of(rawptr), zero_memory)
}
aligned_mem := rawptr(intrinsics.ptr_offset((^u8)(allocated_mem), size_of(rawptr)))
aligned_mem := ([^]u8)(allocated_mem)[size_of(rawptr):]
ptr := uintptr(aligned_mem)
aligned_ptr := (ptr - 1 + uintptr(a)) & -uintptr(a)
@@ -116,10 +113,10 @@ _windows_default_alloc_or_resize :: proc "contextless" (size, alignment: int, ol
return nil, .Out_Of_Memory
}
aligned_mem = rawptr(aligned_ptr)
intrinsics.ptr_offset((^rawptr)(aligned_mem), -1)^ = allocated_mem
aligned_mem = ([^]byte)(aligned_ptr)
([^]rawptr)(aligned_mem)[-1] = allocated_mem
return byte_slice(aligned_mem, size), nil
return aligned_mem[:size], nil
}
_windows_default_alloc :: proc "contextless" (size, alignment: int, zero_memory := true) -> ([]byte, Allocator_Error) {
@@ -129,7 +126,7 @@ _windows_default_alloc :: proc "contextless" (size, alignment: int, zero_memory
_windows_default_free :: proc "contextless" (ptr: rawptr) {
if ptr != nil {
heap_free(intrinsics.ptr_offset((^rawptr)(ptr), -1)^)
heap_free(([^]rawptr)(ptr)[-1])
}
}
+15 -6
View File
@@ -8,6 +8,11 @@ _INTEGER_DIGITS_VAR := _INTEGER_DIGITS
when !ODIN_NO_RTTI {
print_any_single :: proc "contextless" (arg: any) {
x := arg
if x.data == nil {
print_string("nil")
return
}
if loc, ok := x.(Source_Code_Location); ok {
print_caller_location(loc)
return
@@ -48,6 +53,7 @@ when !ODIN_NO_RTTI {
case int: print_int(v)
case uint: print_uint(v)
case uintptr: print_uintptr(v)
case rawptr: print_uintptr(uintptr(v))
case bool: print_string("true" if v else "false")
case b8: print_string("true" if v else "false")
@@ -58,7 +64,7 @@ when !ODIN_NO_RTTI {
case:
ti := type_info_of(x.id)
#partial switch v in ti.variant {
case Type_Info_Pointer:
case Type_Info_Pointer, Type_Info_Multi_Pointer:
print_uintptr((^uintptr)(x.data)^)
return
}
@@ -67,7 +73,9 @@ when !ODIN_NO_RTTI {
}
}
println_any :: proc "contextless" (args: ..any) {
context = default_context()
loop: for arg, i in args {
assert(arg.id != nil)
if i != 0 {
print_string(" ")
}
@@ -390,9 +398,9 @@ print_type :: proc "contextless" (ti: ^Type_Info) {
if info.is_packed { print_string("#packed ") }
if info.is_raw_union { print_string("#raw_union ") }
if info.custom_align {
print_string("#align ")
print_string("#align(")
print_u64(u64(ti.align))
print_byte(' ')
print_string(") ")
}
print_byte('{')
for name, i in info.names {
@@ -406,8 +414,9 @@ print_type :: proc "contextless" (ti: ^Type_Info) {
case Type_Info_Union:
print_string("union ")
if info.custom_align {
print_string("#align ")
print_string("#align(")
print_u64(u64(ti.align))
print_string(") ")
}
if info.no_nil {
print_string("#no_nil ")
@@ -463,11 +472,11 @@ print_type :: proc "contextless" (ti: ^Type_Info) {
print_string(") ")
print_type(info.pointer)
case Type_Info_Relative_Slice:
case Type_Info_Relative_Multi_Pointer:
print_string("#relative(")
print_type(info.base_integer)
print_string(") ")
print_type(info.slice)
print_type(info.pointer)
case Type_Info_Matrix:
print_string("matrix[")
+2 -2
View File
@@ -31,7 +31,7 @@ when ODIN_NO_CRT && ODIN_OS == .Windows {
if ptr != nil && len != 0 {
b := byte(val)
p := ([^]byte)(ptr)
for i in 0..<len {
for i := 0; i < len; i += 1 {
p[i] = b
}
}
@@ -75,7 +75,7 @@ when ODIN_NO_CRT && ODIN_OS == .Windows {
if ptr != nil && len != 0 {
b := byte(val)
p := ([^]byte)(ptr)
for i in 0..<len {
for i := 0; i < len; i += 1 {
p[i] = b
}
}
+4 -4
View File
@@ -77,10 +77,10 @@ shr_masked :: intrinsics.simd_shr_masked
add_sat :: intrinsics.simd_add_sat
sub_sat :: intrinsics.simd_sub_sat
and :: intrinsics.simd_and
or :: intrinsics.simd_or
xor :: intrinsics.simd_xor
and_not :: intrinsics.simd_and_not
bit_and :: intrinsics.simd_bit_and
bit_or :: intrinsics.simd_bit_or
bit_xor :: intrinsics.simd_bit_xor
bit_and_not :: intrinsics.simd_bit_and_not
neg :: intrinsics.simd_neg
+1 -1
View File
@@ -259,7 +259,7 @@ _quick_sort :: proc(it: Interface, a, b, max_depth: int) {
a, b, max_depth := a, b, max_depth
if b-a > 12 { // only use shell sort for lengths <= 12
for b-a > 12 { // only use shell sort for lengths <= 12
if max_depth == 0 {
heap_sort(it, a, b)
return
+12 -12
View File
@@ -35,8 +35,8 @@ Returns:
- res: The new Builder
- err: An optional allocator error if one occured, `nil` otherwise
*/
builder_make_none :: proc(allocator := context.allocator) -> (res: Builder, err: mem.Allocator_Error) #optional_allocator_error {
return Builder{buf=make([dynamic]byte, allocator) or_return }, nil
builder_make_none :: proc(allocator := context.allocator, loc := #caller_location) -> (res: Builder, err: mem.Allocator_Error) #optional_allocator_error {
return Builder{buf=make([dynamic]byte, allocator, loc) or_return }, nil
}
/*
Produces a Builder with a specified length and cap of max(16,len) byte buffer
@@ -51,8 +51,8 @@ Returns:
- res: The new Builder
- err: An optional allocator error if one occured, `nil` otherwise
*/
builder_make_len :: proc(len: int, allocator := context.allocator) -> (res: Builder, err: mem.Allocator_Error) #optional_allocator_error {
return Builder{buf=make([dynamic]byte, len, allocator) or_return }, nil
builder_make_len :: proc(len: int, allocator := context.allocator, loc := #caller_location) -> (res: Builder, err: mem.Allocator_Error) #optional_allocator_error {
return Builder{buf=make([dynamic]byte, len, allocator, loc) or_return }, nil
}
/*
Produces a Builder with a specified length and cap
@@ -68,8 +68,8 @@ Returns:
- res: The new Builder
- err: An optional allocator error if one occured, `nil` otherwise
*/
builder_make_len_cap :: proc(len, cap: int, allocator := context.allocator) -> (res: Builder, err: mem.Allocator_Error) #optional_allocator_error {
return Builder{buf=make([dynamic]byte, len, cap, allocator) or_return }, nil
builder_make_len_cap :: proc(len, cap: int, allocator := context.allocator, loc := #caller_location) -> (res: Builder, err: mem.Allocator_Error) #optional_allocator_error {
return Builder{buf=make([dynamic]byte, len, cap, allocator, loc) or_return }, nil
}
/*
Produces a String Builder
@@ -116,8 +116,8 @@ Returns:
- res: A pointer to the initialized Builder
- err: An optional allocator error if one occured, `nil` otherwise
*/
builder_init_none :: proc(b: ^Builder, allocator := context.allocator) -> (res: ^Builder, err: mem.Allocator_Error) #optional_allocator_error {
b.buf = make([dynamic]byte, allocator) or_return
builder_init_none :: proc(b: ^Builder, allocator := context.allocator, loc := #caller_location) -> (res: ^Builder, err: mem.Allocator_Error) #optional_allocator_error {
b.buf = make([dynamic]byte, allocator, loc) or_return
return b, nil
}
/*
@@ -135,8 +135,8 @@ Returns:
- res: A pointer to the initialized Builder
- err: An optional allocator error if one occured, `nil` otherwise
*/
builder_init_len :: proc(b: ^Builder, len: int, allocator := context.allocator) -> (res: ^Builder, err: mem.Allocator_Error) #optional_allocator_error {
b.buf = make([dynamic]byte, len, allocator) or_return
builder_init_len :: proc(b: ^Builder, len: int, allocator := context.allocator, loc := #caller_location) -> (res: ^Builder, err: mem.Allocator_Error) #optional_allocator_error {
b.buf = make([dynamic]byte, len, allocator, loc) or_return
return b, nil
}
/*
@@ -153,8 +153,8 @@ Returns:
- res: A pointer to the initialized Builder
- err: An optional allocator error if one occured, `nil` otherwise
*/
builder_init_len_cap :: proc(b: ^Builder, len, cap: int, allocator := context.allocator) -> (res: ^Builder, err: mem.Allocator_Error) #optional_allocator_error {
b.buf = make([dynamic]byte, len, cap, allocator) or_return
builder_init_len_cap :: proc(b: ^Builder, len, cap: int, allocator := context.allocator, loc := #caller_location) -> (res: ^Builder, err: mem.Allocator_Error) #optional_allocator_error {
b.buf = make([dynamic]byte, len, cap, allocator, loc) or_return
return b, nil
}
// Overload simple `builder_init_*` with or without len / ap parameters
+2 -2
View File
@@ -34,9 +34,9 @@ Inputs:
Returns:
- err: An allocator error if one occured, `nil` otherwise
*/
intern_init :: proc(m: ^Intern, allocator := context.allocator, map_allocator := context.allocator) -> (err: mem.Allocator_Error) {
intern_init :: proc(m: ^Intern, allocator := context.allocator, map_allocator := context.allocator, loc := #caller_location) -> (err: mem.Allocator_Error) {
m.allocator = allocator
m.entries = make(map[string]^Intern_Entry, 16, map_allocator) or_return
m.entries = make(map[string]^Intern_Entry, 16, map_allocator, loc) or_return
return nil
}
/*
+23 -23
View File
@@ -595,7 +595,7 @@ Output:
a...b...c
*/
join :: proc(a: []string, sep: string, allocator := context.allocator) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error {
join :: proc(a: []string, sep: string, allocator := context.allocator, loc := #caller_location) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error {
if len(a) == 0 {
return "", nil
}
@@ -605,7 +605,7 @@ join :: proc(a: []string, sep: string, allocator := context.allocator) -> (res:
n += len(s)
}
b := make([]byte, n, allocator) or_return
b := make([]byte, n, allocator, loc) or_return
i := copy(b, a[0])
for s in a[1:] {
i += copy(b[i:], sep)
@@ -659,7 +659,7 @@ Output:
abc
*/
concatenate :: proc(a: []string, allocator := context.allocator) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error {
concatenate :: proc(a: []string, allocator := context.allocator, loc := #caller_location) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error {
if len(a) == 0 {
return "", nil
}
@@ -668,7 +668,7 @@ concatenate :: proc(a: []string, allocator := context.allocator) -> (res: string
for s in a {
n += len(s)
}
b := make([]byte, n, allocator) or_return
b := make([]byte, n, allocator, loc) or_return
i := 0
for s in a {
i += copy(b[i:], s)
@@ -724,7 +724,7 @@ Output:
example
*/
cut :: proc(s: string, rune_offset := int(0), rune_length := int(0), allocator := context.allocator) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error {
cut :: proc(s: string, rune_offset := int(0), rune_length := int(0), allocator := context.allocator, loc := #caller_location) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error {
s := s; rune_length := rune_length
context.allocator = allocator
@@ -752,7 +752,7 @@ cut :: proc(s: string, rune_offset := int(0), rune_length := int(0), allocator :
// But we do know it's bounded by the number of runes * 4 bytes,
// and can be no more than the size of the input string.
bytes_needed := min(rune_length * 4, len(s))
buf := make([]u8, bytes_needed) or_return
buf := make([]u8, bytes_needed, allocator, loc) or_return
byte_offset := 0
for i := 0; i < rune_count; i += 1 {
@@ -796,7 +796,7 @@ Returns:
- err: An optional allocator error if one occured, `nil` otherwise
*/
@private
_split :: proc(s_, sep: string, sep_save, n_: int, allocator := context.allocator) -> (res: []string, err: mem.Allocator_Error) {
_split :: proc(s_, sep: string, sep_save, n_: int, allocator := context.allocator, loc := #caller_location) -> (res: []string, err: mem.Allocator_Error) {
s, n := s_, n_
if n == 0 {
@@ -809,7 +809,7 @@ _split :: proc(s_, sep: string, sep_save, n_: int, allocator := context.allocato
n = l
}
res := make([]string, n, allocator) or_return
res := make([]string, n, allocator, loc) or_return
for i := 0; i < n-1; i += 1 {
_, w := utf8.decode_rune_in_string(s)
res[i] = s[:w]
@@ -825,7 +825,7 @@ _split :: proc(s_, sep: string, sep_save, n_: int, allocator := context.allocato
n = count(s, sep) + 1
}
res = make([]string, n, allocator) or_return
res = make([]string, n, allocator, loc) or_return
n -= 1
@@ -1965,14 +1965,14 @@ Output:
abcabc
*/
repeat :: proc(s: string, count: int, allocator := context.allocator) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error {
repeat :: proc(s: string, count: int, allocator := context.allocator, loc := #caller_location) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error {
if count < 0 {
panic("strings: negative repeat count")
} else if count > 0 && (len(s)*count)/count != len(s) {
panic("strings: repeat count will cause an overflow")
}
b := make([]byte, len(s)*count, allocator) or_return
b := make([]byte, len(s)*count, allocator, loc) or_return
i := copy(b, s)
for i < len(b) { // 2^N trick to reduce the need to copy
copy(b[i:], b[:i])
@@ -2052,7 +2052,7 @@ Output:
zzzz true
*/
replace :: proc(s, old, new: string, n: int, allocator := context.allocator) -> (output: string, was_allocation: bool) {
replace :: proc(s, old, new: string, n: int, allocator := context.allocator, loc := #caller_location) -> (output: string, was_allocation: bool) {
if old == new || n == 0 {
was_allocation = false
output = s
@@ -2068,7 +2068,7 @@ replace :: proc(s, old, new: string, n: int, allocator := context.allocator) ->
}
t := make([]byte, len(s) + byte_count*(len(new) - len(old)), allocator)
t := make([]byte, len(s) + byte_count*(len(new) - len(old)), allocator, loc)
was_allocation = true
w := 0
@@ -2637,7 +2637,7 @@ Output:
["testing", "this", "out", "nice", "done", "last"]
*/
split_multi :: proc(s: string, substrs: []string, allocator := context.allocator) -> (res: []string, err: mem.Allocator_Error) #optional_allocator_error #no_bounds_check {
split_multi :: proc(s: string, substrs: []string, allocator := context.allocator, loc := #caller_location) -> (res: []string, err: mem.Allocator_Error) #optional_allocator_error #no_bounds_check {
if s == "" || len(substrs) <= 0 {
return nil, nil
}
@@ -2660,7 +2660,7 @@ split_multi :: proc(s: string, substrs: []string, allocator := context.allocator
it = it[i+w:]
}
results := make([dynamic]string, 0, n, allocator) or_return
results := make([dynamic]string, 0, n, allocator, loc) or_return
{
it := s
for len(it) > 0 {
@@ -2825,10 +2825,10 @@ Output:
abcxyz zyxcba
*/
reverse :: proc(s: string, allocator := context.allocator) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error {
reverse :: proc(s: string, allocator := context.allocator, loc := #caller_location) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error {
str := s
n := len(str)
buf := make([]byte, n) or_return
buf := make([]byte, n, allocator, loc) or_return
i := n
for len(str) > 0 {
@@ -3107,7 +3107,7 @@ Returns:
- res: A slice of substrings of the input string, or an empty slice if the input string only contains white space
- err: An optional allocator error if one occured, `nil` otherwise
*/
fields :: proc(s: string, allocator := context.allocator) -> (res: []string, err: mem.Allocator_Error) #optional_allocator_error #no_bounds_check {
fields :: proc(s: string, allocator := context.allocator, loc := #caller_location) -> (res: []string, err: mem.Allocator_Error) #optional_allocator_error #no_bounds_check {
n := 0
was_space := 1
set_bits := u8(0)
@@ -3129,7 +3129,7 @@ fields :: proc(s: string, allocator := context.allocator) -> (res: []string, err
return nil, nil
}
a := make([]string, n, allocator) or_return
a := make([]string, n, allocator, loc) or_return
na := 0
field_start := 0
i := 0
@@ -3171,8 +3171,8 @@ Returns:
- res: A slice of substrings of the input string, or an empty slice if all code points in the input string satisfy the predicate or if the input string is empty
- err: An optional allocator error if one occured, `nil` otherwise
*/
fields_proc :: proc(s: string, f: proc(rune) -> bool, allocator := context.allocator) -> (res: []string, err: mem.Allocator_Error) #optional_allocator_error #no_bounds_check {
substrings := make([dynamic]string, 0, 32, allocator) or_return
fields_proc :: proc(s: string, f: proc(rune) -> bool, allocator := context.allocator, loc := #caller_location) -> (res: []string, err: mem.Allocator_Error) #optional_allocator_error #no_bounds_check {
substrings := make([dynamic]string, 0, 32, allocator, loc) or_return
start, end := -1, -1
for r, offset in s {
@@ -3252,7 +3252,7 @@ Returns:
NOTE: This implementation is a single-row-version of the WagnerFischer algorithm, based on C code by Martin Ettl.
*/
levenshtein_distance :: proc(a, b: string, allocator := context.allocator) -> (res: int, err: mem.Allocator_Error) #optional_allocator_error {
levenshtein_distance :: proc(a, b: string, allocator := context.allocator, loc := #caller_location) -> (res: int, err: mem.Allocator_Error) #optional_allocator_error {
LEVENSHTEIN_DEFAULT_COSTS: []int : {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
@@ -3275,7 +3275,7 @@ levenshtein_distance :: proc(a, b: string, allocator := context.allocator) -> (r
costs: []int
if n + 1 > len(LEVENSHTEIN_DEFAULT_COSTS) {
costs = make([]int, n + 1, allocator) or_return
costs = make([]int, n + 1, allocator, loc) or_return
for k in 0..=n {
costs[k] = k
}
+2
View File
@@ -88,6 +88,7 @@ wait :: proc{
atomic_cond_wait,
atomic_sema_wait,
futex_wait,
wait_group_wait,
}
wait_with_timeout :: proc{
@@ -96,6 +97,7 @@ wait_with_timeout :: proc{
atomic_cond_wait_with_timeout,
atomic_sema_wait_with_timeout,
futex_wait_with_timeout,
wait_group_wait_with_timeout,
}
post :: proc{
+8 -8
View File
@@ -17,42 +17,42 @@ PTHREAD_RWLOCKATTR_SIZE :: 16
pthread_t :: distinct u64
pthread_attr_t :: struct #align 16 {
pthread_attr_t :: struct #align(16) {
sig: c.long,
_: [PTHREAD_ATTR_SIZE] c.char,
}
pthread_cond_t :: struct #align 16 {
pthread_cond_t :: struct #align(16) {
sig: c.long,
_: [PTHREAD_COND_SIZE] c.char,
}
pthread_condattr_t :: struct #align 16 {
pthread_condattr_t :: struct #align(16) {
sig: c.long,
_: [PTHREAD_CONDATTR_SIZE] c.char,
}
pthread_mutex_t :: struct #align 16 {
pthread_mutex_t :: struct #align(16) {
sig: c.long,
_: [PTHREAD_MUTEX_SIZE] c.char,
}
pthread_mutexattr_t :: struct #align 16 {
pthread_mutexattr_t :: struct #align(16) {
sig: c.long,
_: [PTHREAD_MUTEXATTR_SIZE] c.char,
}
pthread_once_t :: struct #align 16 {
pthread_once_t :: struct #align(16) {
sig: c.long,
_: [PTHREAD_ONCE_SIZE] c.char,
}
pthread_rwlock_t :: struct #align 16 {
pthread_rwlock_t :: struct #align(16) {
sig: c.long,
_: [PTHREAD_RWLOCK_SIZE] c.char,
}
pthread_rwlockattr_t :: struct #align 16 {
pthread_rwlockattr_t :: struct #align(16) {
sig: c.long,
_: [PTHREAD_RWLOCKATTR_SIZE] c.char,
}
+10 -10
View File
@@ -4,7 +4,7 @@ package unix
import "core:c"
pthread_t :: distinct u64
// pthread_t :: struct #align 16 { x: u64 }
// pthread_t :: struct #align(16) { x: u64 }
PTHREAD_COND_T_SIZE :: 8
@@ -27,32 +27,32 @@ when size_of(int) == 8 {
PTHREAD_BARRIER_T_SIZE :: 20
}
pthread_cond_t :: struct #align 16 {
pthread_cond_t :: struct #align(16) {
_: [PTHREAD_COND_T_SIZE] c.char,
}
pthread_mutex_t :: struct #align 16 {
pthread_mutex_t :: struct #align(16) {
_: [PTHREAD_MUTEX_T_SIZE] c.char,
}
pthread_rwlock_t :: struct #align 16 {
pthread_rwlock_t :: struct #align(16) {
_: [PTHREAD_RWLOCK_T_SIZE] c.char,
}
pthread_barrier_t :: struct #align 16 {
pthread_barrier_t :: struct #align(16) {
_: [PTHREAD_BARRIER_T_SIZE] c.char,
}
pthread_attr_t :: struct #align 16 {
pthread_attr_t :: struct #align(16) {
_: [PTHREAD_ATTR_T_SIZE] c.char,
}
pthread_condattr_t :: struct #align 16 {
pthread_condattr_t :: struct #align(16) {
_: [PTHREAD_CONDATTR_T_SIZE] c.char,
}
pthread_mutexattr_t :: struct #align 16 {
pthread_mutexattr_t :: struct #align(16) {
_: [PTHREAD_MUTEXATTR_T_SIZE] c.char,
}
pthread_rwlockattr_t :: struct #align 16 {
pthread_rwlockattr_t :: struct #align(16) {
_: [PTHREAD_RWLOCKATTR_T_SIZE] c.char,
}
pthread_barrierattr_t :: struct #align 16 {
pthread_barrierattr_t :: struct #align(16) {
_: [PTHREAD_BARRIERATTR_T_SIZE] c.char,
}
+11 -11
View File
@@ -8,7 +8,7 @@ import "core:c"
// And at the time of writing there is a bug with putting it
// as the only field in a struct.
pthread_t :: distinct u64
// pthread_t :: struct #align 16 { x: u64 };
// pthread_t :: struct #align(16) { x: u64 };
// NOTE(tetra): Got all the size constants from pthreadtypes-arch.h on my
// Linux machine.
@@ -34,32 +34,32 @@ when size_of(int) == 8 {
PTHREAD_BARRIER_T_SIZE :: 20
}
pthread_cond_t :: struct #align 16 {
pthread_cond_t :: struct #align(16) {
_: [PTHREAD_COND_T_SIZE] c.char,
}
pthread_mutex_t :: struct #align 16 {
pthread_mutex_t :: struct #align(16) {
_: [PTHREAD_MUTEX_T_SIZE] c.char,
}
pthread_rwlock_t :: struct #align 16 {
pthread_rwlock_t :: struct #align(16) {
_: [PTHREAD_RWLOCK_T_SIZE] c.char,
}
pthread_barrier_t :: struct #align 16 {
pthread_barrier_t :: struct #align(16) {
_: [PTHREAD_BARRIER_T_SIZE] c.char,
}
pthread_attr_t :: struct #align 16 {
pthread_attr_t :: struct #align(16) {
_: [PTHREAD_ATTR_T_SIZE] c.char,
}
pthread_condattr_t :: struct #align 16 {
pthread_condattr_t :: struct #align(16) {
_: [PTHREAD_CONDATTR_T_SIZE] c.char,
}
pthread_mutexattr_t :: struct #align 16 {
pthread_mutexattr_t :: struct #align(16) {
_: [PTHREAD_MUTEXATTR_T_SIZE] c.char,
}
pthread_rwlockattr_t :: struct #align 16 {
pthread_rwlockattr_t :: struct #align(16) {
_: [PTHREAD_RWLOCKATTR_T_SIZE] c.char,
}
pthread_barrierattr_t :: struct #align 16 {
pthread_barrierattr_t :: struct #align(16) {
_: [PTHREAD_BARRIERATTR_T_SIZE] c.char,
}
@@ -84,7 +84,7 @@ sched_param :: struct {
sched_priority: c.int,
}
sem_t :: struct #align 16 {
sem_t :: struct #align(16) {
_: [SEM_T_SIZE] c.char,
}
+19 -4
View File
@@ -132,6 +132,21 @@ foreign kernel32 {
SetThreadPriority :: proc(thread: HANDLE, priority: c_int) -> BOOL ---
GetExitCodeThread :: proc(thread: HANDLE, exit_code: ^DWORD) -> BOOL ---
TerminateThread :: proc(thread: HANDLE, exit_code: DWORD) -> BOOL ---
SuspendThread :: proc(hThread: HANDLE) -> DWORD ---
GetProcessAffinityMask :: proc(
hProcess: HANDLE,
lpProcessAffinityMask: PDWORD_PTR,
lpSystemAffinityMask: PDWORD_PTR,
) -> BOOL ---
SetProcessAffinityMask :: proc(
hProcess: HANDLE,
dwProcessAffinityMask: DWORD_PTR,
) -> BOOL ---
SetThreadAffinityMask :: proc(
hThread: HANDLE,
dwThreadAffinityMask: DWORD_PTR,
) -> DWORD_PTR ---
CreateSemaphoreW :: proc(attributes: LPSECURITY_ATTRIBUTES, initial_count, maximum_count: LONG, name: LPCWSTR) -> HANDLE ---
ReleaseSemaphore :: proc(semaphore: HANDLE, release_count: LONG, previous_count: ^LONG) -> BOOL ---
@@ -389,9 +404,9 @@ foreign kernel32 {
CreatePipe :: proc(hReadPipe, hWritePipe: ^HANDLE, lpPipeAttributes: LPSECURITY_ATTRIBUTES, nSize: DWORD) -> BOOL ---
ConnectNamedPipe :: proc(hNamedPipe: HANDLE, lpOverlapped: LPOVERLAPPED,) -> BOOL ---
DisconnectNamedPipe :: proc(hNamedPipe: HANDLE,) -> BOOL ---
WaitNamedPipeW :: proc(lpNamedPipeName: LPCWSTR, nTimeOut: DWORD,) -> BOOL ---
ConnectNamedPipe :: proc(hNamedPipe: HANDLE, lpOverlapped: LPOVERLAPPED) -> BOOL ---
DisconnectNamedPipe :: proc(hNamedPipe: HANDLE) -> BOOL ---
WaitNamedPipeW :: proc(lpNamedPipeName: LPCWSTR, nTimeOut: DWORD) -> BOOL ---
SetConsoleCtrlHandler :: proc(HandlerRoutine: PHANDLER_ROUTINE, Add: BOOL) -> BOOL ---
GenerateConsoleCtrlEvent :: proc(dwCtrlEvent: DWORD, dwProcessGroupId: DWORD) -> BOOL ---
@@ -886,7 +901,7 @@ WIN32_MEMORY_REGION_INFORMATION_u_s :: struct {
Bitfield: ULONG,
}
WIN32_MEMORY_REGION_INFORMATION_u_s_Bitfield :: distinct ULONG
/*bit_field #align align_of(ULONG) {
/*bit_field #align(align_of(ULONG)) {
Private : 1-0,
MappedDataFile : 2-1,
MappedImage : 3-2,
+8 -2
View File
@@ -1709,6 +1709,12 @@ MONITORINFO :: struct {
}
LPMONITORINFO :: ^MONITORINFO
CCHDEVICENAME :: 32
MONITORINFOEXW :: struct {
using _: MONITORINFO,
szDevice: [CCHDEVICENAME]WCHAR,
}
// SetWindowsHook() codes
WH_MIN :: -1
WH_MSGFILTER :: -1
@@ -2469,9 +2475,9 @@ OVERLAPPED :: struct {
}
OVERLAPPED_ENTRY :: struct {
lpCompletionKey: c_ulong,
lpCompletionKey: ULONG_PTR,
lpOverlapped: ^OVERLAPPED,
Internal: c_ulong,
Internal: ULONG_PTR,
dwNumberOfBytesTransferred: DWORD,
}
+3
View File
@@ -228,6 +228,9 @@ foreign user32 {
SetWindowRgn :: proc(hWnd: HWND, hRgn: HRGN, bRedraw: BOOL) -> int ---
CreateRectRgnIndirect :: proc(lprect: ^RECT) -> HRGN ---
GetSystemMetricsForDpi :: proc(nIndex: int, dpi: UINT) -> int ---
GetSystemMenu :: proc(hWnd: HWND, bRevert: BOOL) -> HMENU ---
EnableMenuItem :: proc(hMenu: HMENU, uIDEnableItem: UINT, uEnable: UINT) -> BOOL ---
}
CreateWindowW :: #force_inline proc "stdcall" (
+1 -1
View File
@@ -50,7 +50,7 @@ Example Load:
bytes: u32
guid_accept_ex := WSAID_ACCEPTEX
rc := WSAIoctl(listener, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid_accept_ex, size_of(guid_accept_ex),
fn_acceptex, size_of(fn_acceptex), &bytes, nil, nil,)
fn_acceptex, size_of(fn_acceptex), &bytes, nil, nil)
assert(rc != windows.SOCKET_ERROR)
}
*/
+11 -21
View File
@@ -30,9 +30,12 @@ TS_XML_Options := xml.Options{
parse_qt_linguist_from_bytes :: proc(data: []byte, options := DEFAULT_PARSE_OPTIONS, pluralizer: proc(int) -> int = nil, allocator := context.allocator) -> (translation: ^Translation, err: Error) {
context.allocator = allocator
get_str :: proc(val: xml.Value) -> (str: string, err: Error) {
get_str :: proc(val: xml.Value, intern: ^strings.Intern) -> (str: string, err: Error) {
v, ok := val.(string)
if ok {
if intern != nil {
v, _ = strings.intern_get(intern, v)
}
return v, .None
}
return "", .Bad_Str
@@ -79,8 +82,7 @@ parse_qt_linguist_from_bytes :: proc(data: []byte, options := DEFAULT_PARSE_OPTI
section_name, _ := strings.intern_get(&translation.intern, "")
if !options.merge_sections {
value_text := get_str(ts.elements[section_name_id].value[0]) or_return
section_name, _ = strings.intern_get(&translation.intern, value_text)
section_name = get_str(ts.elements[section_name_id].value[0], &translation.intern) or_return
}
if section_name not_in translation.k_v {
@@ -91,10 +93,7 @@ parse_qt_linguist_from_bytes :: proc(data: []byte, options := DEFAULT_PARSE_OPTI
// Find messages in section.
nth: int
for {
message_id, message_found := xml.find_child_by_ident(ts, child_id, "message", nth)
if !message_found {
break
}
message_id := xml.find_child_by_ident(ts, child_id, "message", nth) or_break
numerus_tag, _ := xml.find_attribute_val_by_key(ts, message_id, "numerus")
has_plurals := numerus_tag == "yes"
@@ -111,13 +110,11 @@ parse_qt_linguist_from_bytes :: proc(data: []byte, options := DEFAULT_PARSE_OPTI
return translation, .TS_File_Expected_Translation
}
source := get_str(ts.elements[source_id].value[0]) or_return
source, _ = strings.intern_get(&translation.intern, source)
source := get_str(ts.elements[source_id].value[0], &translation.intern) or_return
xlat := ""
if !has_plurals {
xlat = get_str(ts.elements[translation_id].value[0]) or_return
xlat, _ = strings.intern_get(&translation.intern, xlat)
xlat = get_str(ts.elements[translation_id].value[0], &translation.intern) or_return
}
if source in section {
@@ -131,10 +128,7 @@ parse_qt_linguist_from_bytes :: proc(data: []byte, options := DEFAULT_PARSE_OPTI
num_plurals: int
for {
numerus_id, numerus_found := xml.find_child_by_ident(ts, translation_id, "numerusform", num_plurals)
if !numerus_found {
break
}
numerus_id := xml.find_child_by_ident(ts, translation_id, "numerusform", num_plurals) or_break
num_plurals += 1
}
@@ -145,12 +139,8 @@ parse_qt_linguist_from_bytes :: proc(data: []byte, options := DEFAULT_PARSE_OPTI
num_plurals = 0
for {
numerus_id, numerus_found := xml.find_child_by_ident(ts, translation_id, "numerusform", num_plurals)
if !numerus_found {
break
}
numerus := get_str(ts.elements[numerus_id].value[0]) or_return
numerus, _ = strings.intern_get(&translation.intern, numerus)
numerus_id := xml.find_child_by_ident(ts, translation_id, "numerusform", num_plurals) or_break
numerus := get_str(ts.elements[numerus_id].value[0], &translation.intern) or_return
section[source][num_plurals] = numerus
num_plurals += 1
+2 -3
View File
@@ -775,10 +775,9 @@ gsub_with :: proc(
haystack := haystack
for {
length, err := find_aux(haystack, pattern, 0, false, &captures)
length := find_aux(haystack, pattern, 0, false, &captures) or_break
// done
if length == 0 || err != .OK {
if length == 0 {
break
}
+2 -2
View File
@@ -200,7 +200,7 @@ peek :: proc(s: ^Scanner, n := 0) -> (ch: rune) {
ch = s.ch
if n > 0 {
prev_s := s^
for in 0..<n {
for _ in 0..<n {
next(s)
}
ch = s.ch
@@ -214,7 +214,7 @@ peek :: proc(s: ^Scanner, n := 0) -> (ch: rune) {
peek_token :: proc(s: ^Scanner, n := 0) -> (tok: rune) {
assert(n >= 0)
prev_s := s^
for in 0..<n {
for _ in 0..<n {
tok = scan(s)
}
tok = scan(s)
+1 -1
View File
@@ -10,7 +10,7 @@ CAS :: intrinsics.atomic_compare_exchange_strong
// NOTE(tetra): Aligned here because of core/unix/pthread_linux.odin/pthread_t.
// Also see core/sys/darwin/mach_darwin.odin/semaphore_t.
Thread_Os_Specific :: struct #align 16 {
Thread_Os_Specific :: struct #align(16) {
unix_thread: unix.pthread_t, // NOTE: very large on Darwin, small on Linux.
cond: sync.Cond,
mutex: sync.Mutex,
+33 -37
View File
@@ -86,44 +86,40 @@ generate_encoding_entity_table :: proc() {
nth := 0
for {
character_entity, entity_ok := xml.find_child_by_ident(char, "entity", nth)
if !entity_ok { break }
nth += 1
if name, name_ok := xml.find_attribute_val_by_key(character_entity, "id"); name_ok {
if len(name) == 0 {
/*
Invalid name. Skip.
*/
continue
}
if name == "\"\"" {
printf("%#v\n", char)
printf("%#v\n", character_entity)
}
if len(name) > max_name_length { longest_name = name }
if len(name) < min_name_length { shortest_name = name }
min_name_length = min(min_name_length, len(name))
max_name_length = max(max_name_length, len(name))
e := Entity{
name = name,
codepoint = rune(codepoint),
description = description,
}
if _, seen := entity_map[name]; seen {
continue
}
entity_map[name] = e
append(&names, name)
count += 1
character_entity := xml.find_child_by_ident(char, "entity", nth) or_break
nth += 1
name := xml.find_attribute_val_by_key(character_entity, "id") or_continue
if len(name) == 0 {
/*
Invalid name. Skip.
*/
continue
}
if name == "\"\"" {
printf("%#v\n", char)
printf("%#v\n", character_entity)
}
if len(name) > max_name_length { longest_name = name }
if len(name) < min_name_length { shortest_name = name }
min_name_length = min(min_name_length, len(name))
max_name_length = max(max_name_length, len(name))
e := Entity{
name = name,
codepoint = rune(codepoint),
description = description,
}
if name in entity_map {
continue
}
entity_map[name] = e
append(&names, name)
count += 1
}
}
}
+176 -83
View File
@@ -459,6 +459,27 @@ named_proc_return_parameters :: proc() {
fmt.println("foo2 =", foo2()) // 567 321
}
variadic_procedures :: proc() {
fmt.println("\n# variadic procedures")
sum :: proc(nums: ..int, init_value:= 0) -> (result: int) {
result = init_value
for n in nums {
result += n
}
return
}
fmt.println("sum(()) =", sum())
fmt.println("sum(1, 2) =", sum(1, 2))
fmt.println("sum(1, 2, 3, 4, 5) =", sum(1, 2, 3, 4, 5))
fmt.println("sum(1, 2, 3, 4, 5, init_value = 5) =", sum(1, 2, 3, 4, 5, init_value = 5))
// pass a slice as varargs
odds := []int{1, 3, 5}
fmt.println("odds =", odds)
fmt.println("sum(..odds) =", sum(..odds))
fmt.println("sum(..odds, init_value = 5) =", sum(..odds, init_value = 5))
}
explicit_procedure_overloading :: proc() {
fmt.println("\n# explicit procedure overloading")
@@ -539,7 +560,7 @@ struct_type :: proc() {
{
// Structs can tagged with different memory layout and alignment requirements:
a :: struct #align 4 {} // align to 4 bytes
a :: struct #align(4) {} // align to 4 bytes
b :: struct #packed {} // remove padding between fields
c :: struct #raw_union {} // all fields share the same offset (0). This is the same as C's union
}
@@ -1134,7 +1155,7 @@ threading_example :: proc() {
threads := make([dynamic]^thread.Thread, 0, len(prefix_table))
defer delete(threads)
for in prefix_table {
for _ in prefix_table {
if t := thread.create(worker_proc); t != nil {
t.init_context = context
t.user_index = len(threads)
@@ -1333,13 +1354,13 @@ partial_switch :: proc() {
{ // union
Foo :: union {int, bool}
f: Foo = 123
switch in f {
switch _ in f {
case int: fmt.println("int")
case bool: fmt.println("bool")
case:
}
#partial switch in f {
#partial switch _ in f {
case bool: fmt.println("bool")
}
}
@@ -1765,19 +1786,7 @@ range_statements_with_multiple_return_values :: proc() {
data[i] = i32(i*i)
}
{
it := make_my_iterator(data)
for val in my_iterator(&it) {
fmt.println(val)
}
}
{
it := make_my_iterator(data)
for val, idx in my_iterator(&it) {
fmt.println(val, idx)
}
}
{
{ // Manual Style
it := make_my_iterator(data)
for {
val, _, cond := my_iterator(&it)
@@ -1787,6 +1796,25 @@ range_statements_with_multiple_return_values :: proc() {
fmt.println(val)
}
}
{ // or_break
it := make_my_iterator(data)
loop: for {
val, _ := my_iterator(&it) or_break loop
fmt.println(val)
}
}
{ // first value
it := make_my_iterator(data)
for val in my_iterator(&it) {
fmt.println(val)
}
}
{ // first and second value
it := make_my_iterator(data)
for val, idx in my_iterator(&it) {
fmt.println(val, idx)
}
}
}
@@ -2024,12 +2052,11 @@ relative_data_types :: proc() {
fmt.println(ptr^)
arr := [3]int{1, 2, 3}
s := arr[:]
rel_slice: #relative(i16) []int
rel_slice = s
fmt.println(rel_slice)
fmt.println(rel_slice[:])
fmt.println(rel_slice[1])
multi_ptr: #relative(i16) [^]int
multi_ptr = &arr[0]
fmt.println(multi_ptr)
fmt.println(multi_ptr[:3])
fmt.println(multi_ptr[1])
}
or_else_operator :: proc() {
@@ -2052,7 +2079,7 @@ or_else_operator :: proc() {
// have optional ok semantics
v: union{int, f64}
i: int
i = v.(int) or_else 123
i = v.(int) or_else 123
i = v.? or_else 123 // Type inference magic
assert(i == 123)
@@ -2158,6 +2185,70 @@ or_return_operator :: proc() {
foo_2()
}
or_break_and_or_continue_operators :: proc() {
fmt.println("\n#'or_break' and 'or_continue'")
// The concept of 'or_break' and 'or_continue' is very similar to that of 'or_return'.
// The difference is that unlike 'or_return', the value does not get returned from
// the current procedure but rather discarded if it is 'false' or not 'nil', and then
// the specified branch (i.e. break or_continue).
// The or branch expression can be labelled if a specific statement needs to be used.
Error :: enum {
None,
Something_Bad,
Something_Worse,
The_Worst,
Your_Mum,
}
caller_1 :: proc() -> Error {
return .Something_Bad
}
caller_2 :: proc() -> (int, Error) {
return 123, .Something_Worse
}
caller_3 :: proc() -> (int, int, Error) {
return 123, 345, .None
}
for { // common approach
err := caller_1()
if err != nil {
break
}
}
for { // or_break approach
caller_1() or_break
}
for { // or_break approach with multiple values
n := caller_2() or_break
_ = n
}
loop: for { // or_break approach with named label
n := caller_2() or_break loop
_ = n
}
for { // or_continue
x, y := caller_3() or_continue
_, _ = x, y
break
}
continue_loop: for { // or_continue with named label
x, y := caller_3() or_continue continue_loop
_, _ = x, y
break
}
}
arbitrary_precision_mathematics :: proc() {
fmt.println("\n# core:math/big")
@@ -2238,98 +2329,98 @@ matrix_type :: proc() {
fmt.println("\n# matrix type")
// A matrix is a mathematical type built into Odin. It is a regular array of numbers,
// arranged in rows and columns
{
// The following represents a matrix that has 2 rows and 3 columns
m: matrix[2, 3]f32
m = matrix[2, 3]f32{
1, 9, -13,
20, 5, -6,
}
// Element types of integers, float, and complex numbers are supported by matrices.
// There is no support for booleans, quaternions, or any compound type.
// Indexing a matrix can be used with the matrix indexing syntax
// This mirrors othe type usages: type on the left, usage on the right
elem := m[1, 2] // row 1, column 2
assert(elem == -6)
// Scalars act as if they are scaled identity matrices
// and can be assigned to matrices as them
b := matrix[2, 2]f32{}
f := f32(3)
b = f
fmt.println("b", b)
fmt.println("b == f", b == f)
}
}
{ // Matrices support multiplication between matrices
a := matrix[2, 3]f32{
2, 3, 1,
4, 5, 0,
}
b := matrix[3, 2]f32{
1, 2,
3, 4,
5, 6,
}
fmt.println("a", a)
fmt.println("b", b)
c := a * b
#assert(type_of(c) == matrix[2, 2]f32)
fmt.tprintln("c = a * b", c)
fmt.tprintln("c = a * b", c)
}
{ // Matrices support multiplication between matrices and arrays
m := matrix[4, 4]f32{
1, 2, 3, 4,
5, 5, 4, 2,
0, 1, 3, 0,
1, 2, 3, 4,
5, 5, 4, 2,
0, 1, 3, 0,
0, 1, 4, 1,
}
v := [4]f32{1, 5, 4, 3}
// treating 'v' as a column vector
fmt.println("m * v", m * v)
// treating 'v' as a row vector
fmt.println("v * m", v * m)
// Support with non-square matrices
s := matrix[2, 4]f32{ // [4][2]f32
2, 4, 3, 1,
7, 8, 6, 5,
2, 4, 3, 1,
7, 8, 6, 5,
}
w := [2]f32{1, 2}
r: [4]f32 = w * s
fmt.println("r", r)
}
{ // Component-wise operations
{ // Component-wise operations
// if the element type supports it
// Not support for '/', '%', or '%%' operations
a := matrix[2, 2]i32{
1, 2,
3, 4,
}
b := matrix[2, 2]i32{
-5, 1,
9, -7,
}
c0 := a + b
c1 := a - b
c2 := a & b
@@ -2339,9 +2430,9 @@ matrix_type :: proc() {
// component-wise multiplication
// since a * b would be a standard matrix multiplication
c6 := hadamard_product(a, b)
c6 := hadamard_product(a, b)
fmt.println("a + b", c0)
fmt.println("a - b", c1)
fmt.println("a & b", c2)
@@ -2350,23 +2441,23 @@ matrix_type :: proc() {
fmt.println("a &~ b", c5)
fmt.println("hadamard_product(a, b)", c6)
}
{ // Submatrix casting square matrices
// Casting a square matrix to another square matrix with same element type
// is supported.
// is supported.
// If the cast is to a smaller matrix type, the top-left submatrix is taken.
// If the cast is to a larger matrix type, the matrix is extended with zeros
// everywhere and ones in the diagonal for the unfilled elements of the
// everywhere and ones in the diagonal for the unfilled elements of the
// extended matrix.
mat2 :: distinct matrix[2, 2]f32
mat4 :: distinct matrix[4, 4]f32
m2 := mat2{
1, 3,
2, 4,
}
m4 := mat4(m2)
assert(m4[2, 2] == 1)
assert(m4[3, 3] == 1)
@@ -2374,7 +2465,7 @@ matrix_type :: proc() {
fmt.println("m4", m4)
fmt.println("mat2(m4)", mat2(m4))
assert(mat2(m4) == m2)
b4 := mat4{
1, 2, 0, 0,
3, 4, 0, 0,
@@ -2383,43 +2474,43 @@ matrix_type :: proc() {
}
fmt.println("b4", matrix_flatten(b4))
}
{ // Casting non-square matrices
// Casting a matrix to another matrix is allowed as long as they share
// Casting a matrix to another matrix is allowed as long as they share
// the same element type and the number of elements (rows*columns).
// Matrices in Odin are stored in column-major order, which means
// the casts will preserve this element order.
mat2x4 :: distinct matrix[2, 4]f32
mat4x2 :: distinct matrix[4, 2]f32
x := mat2x4{
1, 3, 5, 7,
1, 3, 5, 7,
2, 4, 6, 8,
}
y := mat4x2(x)
fmt.println("x", x)
fmt.println("y", y)
}
// TECHNICAL INFORMATION: the internal representation of a matrix in Odin is stored
// in column-major format
// e.g. matrix[2, 3]f32 is internally [3][2]f32 (with different a alignment requirement)
// Column-major is used in order to utilize (SIMD) vector instructions effectively on
// Column-major is used in order to utilize (SIMD) vector instructions effectively on
// modern hardware, if possible.
//
// Unlike normal arrays, matrices try to maximize alignment to allow for the (SIMD) vectorization
// properties whilst keeping zero padding (either between columns or at the end of the type).
//
//
// Zero padding is a compromise for use with third-party libraries, instead of optimizing for performance.
// Padding between columns was not taken even if that would have allowed each column to be loaded
// individually into a SIMD register with the correct alignment properties.
//
// Padding between columns was not taken even if that would have allowed each column to be loaded
// individually into a SIMD register with the correct alignment properties.
//
// Currently, matrices are limited to a maximum of 16 elements (rows*columns), and a minimum of 1 element.
// This is because matrices are stored as values (not a reference type), and thus operations on them will
// be stored on the stack. Restricting the maximum element count minimizing the possibility of stack overflows.
// Built-in Procedures (Compiler Level)
// transpose(m)
// transposes a matrix
@@ -2434,13 +2525,13 @@ matrix_type :: proc() {
// Example:
// m := matrix[2, 2]f32{
// x0, x1,
// y0, y1,
// y0, y1,
// }
// array: [4]f32 = matrix_flatten(m)
// assert(array == {x0, y0, x1, y1})
// conj(x)
// conjugates the elements of a matrix for complex element types only
// Built-in Procedures (Runtime Level) (all square matrix procedures)
// determinant(m)
// adjugate(m)
@@ -2454,8 +2545,8 @@ matrix_type :: proc() {
main :: proc() {
/*
For More Odin Examples - https://github.com/odin-lang/examples
This repository contains examples of how certain things can be accomplished
in idiomatic Odin, allowing you learn its semantics, as well as how to use
This repository contains examples of how certain things can be accomplished
in idiomatic Odin, allowing you learn its semantics, as well as how to use
parts of the core and vendor package collections.
*/
@@ -2463,6 +2554,7 @@ main :: proc() {
the_basics()
control_flow()
named_proc_return_parameters()
variadic_procedures()
explicit_procedure_overloading()
struct_type()
union_type()
@@ -2492,7 +2584,8 @@ main :: proc() {
relative_data_types()
or_else_operator()
or_return_operator()
or_break_and_or_continue_operators()
arbitrary_precision_mathematics()
matrix_type()
}
}
}
+2 -1
View File
@@ -2,9 +2,10 @@
rem call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x86 1> NUL
rem call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x64 1> NUL
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64 1> NUL
rem call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64 1> NUL
rem call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x86 1> NUL
rem call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x64 1> NUL
call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" x64 1> NUL
set _NO_DEBUG_HEAP=1
set ODIN_IGNORE_MSVC_CHECK=1
+19
View File
@@ -168,6 +168,17 @@ gb_internal gb_inline Slice<T> slice(Slice<T> const &array, isize lo, isize hi)
}
return out;
}
template <typename T>
gb_internal gb_inline Slice<T> slice(Array<T> const &array, isize lo, isize hi) {
GB_ASSERT(0 <= lo && lo <= hi && hi <= array.count);
Slice<T> out = {};
isize len = hi-lo;
if (len > 0) {
out.data = array.data+lo;
out.count = len;
}
return out;
}
template <typename T>
@@ -303,6 +314,14 @@ gb_internal void array_add(Array<T> *array, T const &t) {
array->count++;
}
gb_internal void array_add(Array<char const *> *array, char const *t) {
if (array->capacity < array->count+1) {
array__grow(array, 0);
}
array->data[array->count] = t;
array->count++;
}
template <typename T>
gb_internal T *array_add_and_get(Array<T> *array) {
if (array->count < array->capacity) {
+79 -7
View File
@@ -123,6 +123,18 @@ struct TargetMetrics {
TargetABIKind abi;
};
enum Subtarget : u32 {
Subtarget_Default,
Subtarget_iOS,
Subtarget_COUNT,
};
gb_global String subtarget_strings[Subtarget_COUNT] = {
str_lit(""),
str_lit("ios"),
};
enum QueryDataSetKind {
QueryDataSet_Invalid,
@@ -225,9 +237,7 @@ enum VetFlags : u64 {
VetFlag_Style = 1u<<4, // 16
VetFlag_Semicolon = 1u<<5, // 32
VetFlag_Extra = 1u<<16,
VetFlag_All = VetFlag_Unused|VetFlag_Shadowing|VetFlag_UsingStmt, // excluding extra
VetFlag_All = VetFlag_Unused|VetFlag_Shadowing|VetFlag_UsingStmt,
VetFlag_Using = VetFlag_UsingStmt|VetFlag_UsingParam,
};
@@ -245,13 +255,19 @@ u64 get_vet_flag_from_name(String const &name) {
return VetFlag_Style;
} else if (name == "semicolon") {
return VetFlag_Semicolon;
} else if (name == "extra") {
return VetFlag_Extra;
}
return VetFlag_NONE;
}
enum SanitizerFlags : u32 {
SanitizerFlag_NONE = 0,
SanitizerFlag_Address = 1u<<0,
SanitizerFlag_Memory = 1u<<1,
SanitizerFlag_Thread = 1u<<2,
};
// This stores the information for the specify architecture of this build
struct BuildContext {
@@ -293,6 +309,7 @@ struct BuildContext {
String pdb_filepath;
u64 vet_flags;
u32 sanitizer_flags;
bool has_resource;
String link_flags;
@@ -354,6 +371,8 @@ struct BuildContext {
isize max_error_count;
bool tilde_backend;
u32 cmd_doc_flags;
Array<String> extra_packages;
@@ -583,6 +602,8 @@ gb_global NamedTargetMetrics named_targets[] = {
};
gb_global NamedTargetMetrics *selected_target_metrics;
gb_global Subtarget selected_subtarget;
gb_internal TargetOsKind get_target_os_from_string(String str) {
for (isize i = 0; i < TargetOs_COUNT; i++) {
@@ -1145,7 +1166,7 @@ gb_internal char *token_pos_to_string(TokenPos const &pos) {
return s;
}
gb_internal void init_build_context(TargetMetrics *cross_target) {
gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subtarget) {
BuildContext *bc = &build_context;
gb_affinity_init(&bc->affinity);
@@ -1240,6 +1261,21 @@ gb_internal void init_build_context(TargetMetrics *cross_target) {
bc->metrics = *metrics;
switch (subtarget) {
case Subtarget_Default:
break;
case Subtarget_iOS:
GB_ASSERT(metrics->os == TargetOs_darwin);
if (metrics->arch == TargetArch_arm64) {
bc->metrics.target_triplet = str_lit("arm64-apple-ios");
} else if (metrics->arch == TargetArch_amd64) {
bc->metrics.target_triplet = str_lit("x86_64-apple-ios");
} else {
GB_PANIC("Unknown architecture for darwin");
}
break;
}
bc->ODIN_OS = target_os_names[metrics->os];
bc->ODIN_ARCH = target_arch_names[metrics->arch];
bc->endian_kind = target_endians[metrics->arch];
@@ -1350,7 +1386,7 @@ gb_internal void init_build_context(TargetMetrics *cross_target) {
bc->optimization_level = -1; // -o:none
}
bc->optimization_level = gb_clamp(bc->optimization_level, -1, 2);
bc->optimization_level = gb_clamp(bc->optimization_level, -1, 3);
// ENFORCE DYNAMIC MAP CALLS
bc->dynamic_map_calls = true;
@@ -1707,6 +1743,42 @@ gb_internal bool init_build_paths(String init_filename) {
return false;
}
if (build_context.sanitizer_flags & SanitizerFlag_Address) {
switch (build_context.metrics.os) {
case TargetOs_windows:
case TargetOs_linux:
case TargetOs_darwin:
break;
default:
gb_printf_err("-sanitize:address is only supported on windows, linux, and darwin\n");
return false;
}
}
if (build_context.sanitizer_flags & SanitizerFlag_Memory) {
switch (build_context.metrics.os) {
case TargetOs_linux:
break;
default:
gb_printf_err("-sanitize:memory is only supported on linux\n");
return false;
}
if (build_context.metrics.os != TargetOs_linux) {
return false;
}
}
if (build_context.sanitizer_flags & SanitizerFlag_Thread) {
switch (build_context.metrics.os) {
case TargetOs_linux:
case TargetOs_darwin:
break;
default:
gb_printf_err("-sanitize:thread is only supported on linux and darwin\n");
return false;
}
}
if (bc->target_features_string.len != 0) {
enable_target_feature({}, bc->target_features_string);
+9 -6
View File
@@ -471,10 +471,10 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan
// Integer only
case BuiltinProc_simd_add_sat:
case BuiltinProc_simd_sub_sat:
case BuiltinProc_simd_and:
case BuiltinProc_simd_or:
case BuiltinProc_simd_xor:
case BuiltinProc_simd_and_not:
case BuiltinProc_simd_bit_and:
case BuiltinProc_simd_bit_or:
case BuiltinProc_simd_bit_xor:
case BuiltinProc_simd_bit_and_not:
{
Operand x = {};
Operand y = {};
@@ -1748,7 +1748,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
mode = Addressing_Constant;
value = exact_value_i64(at->EnumeratedArray.count);
type = t_untyped_integer;
} else if ((is_type_slice(op_type) || is_type_relative_slice(op_type)) && id == BuiltinProc_len) {
} else if (is_type_slice(op_type) && id == BuiltinProc_len) {
mode = Addressing_Value;
} else if (is_type_dynamic_array(op_type)) {
mode = Addressing_Value;
@@ -2120,7 +2120,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
return false;
}
Type *t = o.type;
if (t == nullptr || t == t_invalid || is_type_asm_proc(o.type) || is_type_polymorphic(operand->type)) {
if (t == nullptr || t == t_invalid || is_type_asm_proc(t) || is_type_polymorphic(t)) {
error(ce->args[0], "Invalid argument for '%.*s'", LIT(builtin_name));
return false;
}
@@ -3692,6 +3692,9 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
case Type_SimdVector:
operand->type = alloc_type_multi_pointer(base_array_type(base));
break;
case Type_Matrix:
operand->type = alloc_type_multi_pointer(base->Matrix.elem);
break;
}
}
break;
+7 -4
View File
@@ -321,7 +321,14 @@ gb_internal void check_type_decl(CheckerContext *ctx, Entity *e, Ast *init_expr,
gb_string_free(str);
is_distinct = false;
}
} else {
if (is_type_typeid(e->type)) {
error(init_expr, "'typeid' cannot be aliased");
} else if (is_type_any(e->type)) {
error(init_expr, "'any' cannot be aliased");
}
}
if (!is_distinct) {
e->type = bt;
named->Named.base = bt;
@@ -1329,10 +1336,6 @@ gb_internal void check_proc_group_decl(CheckerContext *ctx, Entity *pg_entity, D
is_invalid = true;
break;
case ProcOverload_Polymorphic:
#if 0
error(p->token, "Overloaded procedure '%.*s' has a polymorphic counterpart in the procedure group '%.*s' which is not allowed", LIT(name), LIT(proc_group_name));
is_invalid = true;
#endif
break;
case ProcOverload_ParamCount:
case ProcOverload_ParamTypes:
+210 -104
View File
@@ -629,6 +629,9 @@ gb_internal i64 check_distance_between_types(CheckerContext *c, Operand *operand
if (operand->mode == Addressing_Type) {
if (is_type_typeid(type)) {
if (is_type_polymorphic(operand->type)) {
return -1;
}
add_type_info_type(c, operand->type);
return 4;
}
@@ -856,8 +859,8 @@ gb_internal i64 check_distance_between_types(CheckerContext *c, Operand *operand
}
}
if (is_type_relative_slice(dst)) {
i64 score = check_distance_between_types(c, operand, dst->RelativeSlice.slice_type);
if (is_type_relative_multi_pointer(dst)) {
i64 score = check_distance_between_types(c, operand, dst->RelativeMultiPointer.pointer_type);
if (score >= 0) {
return score+2;
}
@@ -1005,8 +1008,8 @@ gb_internal AstPackage *get_package_of_type(Type *type) {
case Type_RelativePointer:
type = type->RelativePointer.pointer_type;
continue;
case Type_RelativeSlice:
type = type->RelativeSlice.slice_type;
case Type_RelativeMultiPointer:
type = type->RelativeMultiPointer.pointer_type;
continue;
}
return nullptr;
@@ -1118,10 +1121,17 @@ gb_internal void check_assignment(CheckerContext *c, Operand *operand, Type *typ
LIT(context_name));
break;
case Addressing_Type:
error(operand->expr,
"Cannot assign '%s' which is a type in %.*s",
op_type_str,
LIT(context_name));
if (is_type_polymorphic(operand->type)) {
error(operand->expr,
"Cannot assign '%s' which is a polymorphic type in %.*s",
op_type_str,
LIT(context_name));
} else {
error(operand->expr,
"Cannot assign '%s' which is a type in %.*s",
op_type_str,
LIT(context_name));
}
break;
default:
// TODO(bill): is this a good enough error message?
@@ -2452,8 +2462,9 @@ gb_internal void add_comparison_procedures_for_fields(CheckerContext *c, Type *t
add_package_dependency(c, "runtime", "quaternion256_ne");
break;
case Basic_cstring:
add_package_dependency(c, "runtime", "cstring_to_string");
/*fallthrough*/
add_package_dependency(c, "runtime", "cstring_eq");
add_package_dependency(c, "runtime", "cstring_ne");
break;
case Basic_string:
add_package_dependency(c, "runtime", "string_eq");
add_package_dependency(c, "runtime", "string_ne");
@@ -2611,7 +2622,16 @@ gb_internal void check_comparison(CheckerContext *c, Ast *node, Operand *x, Oper
if (!is_type_untyped(x->type)) size = gb_max(size, type_size_of(x->type));
if (!is_type_untyped(y->type)) size = gb_max(size, type_size_of(y->type));
if (is_type_string(x->type) || is_type_string(y->type)) {
if (is_type_cstring(x->type) && is_type_cstring(y->type)) {
switch (op) {
case Token_CmpEq: add_package_dependency(c, "runtime", "cstring_eq"); break;
case Token_NotEq: add_package_dependency(c, "runtime", "cstring_ne"); break;
case Token_Lt: add_package_dependency(c, "runtime", "cstring_lt"); break;
case Token_Gt: add_package_dependency(c, "runtime", "cstring_gt"); break;
case Token_LtEq: add_package_dependency(c, "runtime", "cstring_le"); break;
case Token_GtEq: add_package_dependency(c, "runtime", "cstring_gt"); break;
}
} else if (is_type_string(x->type) || is_type_string(y->type)) {
switch (op) {
case Token_CmpEq: add_package_dependency(c, "runtime", "string_eq"); break;
case Token_NotEq: add_package_dependency(c, "runtime", "string_ne"); break;
@@ -3082,14 +3102,6 @@ gb_internal void check_cast(CheckerContext *c, Operand *x, Type *type) {
update_untyped_expr_type(c, x->expr, final_type, true);
}
if (check_vet_flags(x->expr) & VetFlag_Extra) {
if (are_types_identical(x->type, type)) {
gbString str = type_to_string(type);
warning(x->expr, "Unneeded cast to the same type '%s'", str);
gb_string_free(str);
}
}
x->type = type;
}
@@ -3154,14 +3166,6 @@ gb_internal bool check_transmute(CheckerContext *c, Ast *node, Operand *o, Type
return false;
}
if (check_vet_flags(node) & VetFlag_Extra) {
if (are_types_identical(o->type, dst_t)) {
gbString str = type_to_string(dst_t);
warning(o->expr, "Unneeded transmute to the same type '%s'", str);
gb_string_free(str);
}
}
o->expr = node;
o->type = dst_t;
if (o->mode == Addressing_Constant) {
@@ -3663,18 +3667,7 @@ gb_internal void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Typ
ExactValue b = y->value;
if (!is_type_constant_type(x->type)) {
#if 0
gbString xt = type_to_string(x->type);
gbString err_str = expr_to_string(node);
error(op, "Invalid type, '%s', for constant binary expression '%s'", xt, err_str);
gb_string_free(err_str);
gb_string_free(xt);
x->mode = Addressing_Invalid;
#else
// NOTE(bill, 2021-04-21): The above is literally a useless error message.
// Why did I add it in the first place?!
x->mode = Addressing_Value;
#endif
return;
}
@@ -3817,6 +3810,15 @@ gb_internal void update_untyped_expr_type(CheckerContext *c, Ast *e, Type *type,
update_untyped_expr_type(c, ore->expr, type, final);
case_end;
case_ast_node(obe, OrBranchExpr, e);
if (old->value.kind != ExactValue_Invalid) {
// See above note in UnaryExpr case
break;
}
update_untyped_expr_type(c, obe->expr, type, final);
case_end;
case_ast_node(oee, OrElseExpr, e);
if (old->value.kind != ExactValue_Invalid) {
// See above note in UnaryExpr case
@@ -5092,27 +5094,6 @@ gb_internal bool check_identifier_exists(Scope *s, Ast *node, bool nested = fals
return false;
}
gb_internal isize add_dependencies_from_unpacking(CheckerContext *c, Entity **lhs, isize lhs_count, isize tuple_index, isize tuple_count) {
if (lhs != nullptr && c->decl != nullptr) {
for (isize j = 0; (tuple_index + j) < lhs_count && j < tuple_count; j++) {
Entity *e = lhs[tuple_index + j];
if (e != nullptr) {
DeclInfo *decl = decl_info_of_entity(e);
if (decl != nullptr) {
rw_mutex_shared_lock(&decl->deps_mutex);
rw_mutex_lock(&c->decl->deps_mutex);
for (Entity *dep : decl->deps) {
ptr_set_add(&c->decl->deps, dep);
}
rw_mutex_unlock(&c->decl->deps_mutex);
rw_mutex_shared_unlock(&decl->deps_mutex);
}
}
}
}
return tuple_count;
}
gb_internal bool check_no_copy_assignment(Operand const &o, String const &context) {
if (o.type && is_type_no_copy(o.type)) {
Ast *expr = unparen_expr(o.expr);
@@ -5220,6 +5201,31 @@ enum UnpackFlag : u32 {
gb_internal bool check_unpack_arguments(CheckerContext *ctx, Entity **lhs, isize lhs_count, Array<Operand> *operands, Slice<Ast *> const &rhs_arguments, UnpackFlags flags) {
auto const &add_dependencies_from_unpacking = [](CheckerContext *c, Entity **lhs, isize lhs_count, isize tuple_index, isize tuple_count) -> isize {
if (lhs == nullptr || c->decl == nullptr) {
return tuple_count;
}
for (isize j = 0; (tuple_index + j) < lhs_count && j < tuple_count; j++) {
Entity *e = lhs[tuple_index + j];
if (e == nullptr) {
continue;
}
DeclInfo *decl = decl_info_of_entity(e);
if (decl == nullptr) {
continue;
}
rw_mutex_shared_lock(&decl->deps_mutex);
rw_mutex_lock(&c->decl->deps_mutex);
for (Entity *dep : decl->deps) {
ptr_set_add(&c->decl->deps, dep);
}
rw_mutex_unlock(&c->decl->deps_mutex);
rw_mutex_shared_unlock(&decl->deps_mutex);
}
return tuple_count;
};
bool allow_ok = (flags & UnpackFlag_AllowOk) != 0;
bool is_variadic = (flags & UnpackFlag_IsVariadic) != 0;
bool allow_undef = (flags & UnpackFlag_AllowUndef) != 0;
@@ -5474,6 +5480,8 @@ gb_internal CallArgumentError check_call_arguments_internal(CheckerContext *c, A
auto variadic_operands = slice(slice_from_array(positional_operands), positional_operand_count, positional_operands.count);
bool named_variadic_param = false;
if (named_operands.count != 0) {
GB_ASSERT(ce->split_args->named.count == named_operands.count);
for_array(i, ce->split_args->named) {
@@ -5499,6 +5507,9 @@ gb_internal CallArgumentError check_call_arguments_internal(CheckerContext *c, A
err = CallArgumentError_ParameterNotFound;
continue;
}
if (pt->variadic && param_index == pt->variadic_index) {
named_variadic_param = true;
}
if (visited[param_index]) {
if (show_error) {
error(arg, "Duplicate parameter '%.*s' in procedure call", LIT(name));
@@ -5546,11 +5557,7 @@ gb_internal CallArgumentError check_call_arguments_internal(CheckerContext *c, A
o.expr->Ident.token.pos = ast_token(variadic_operands[0].expr).pos;
Entity *vt = pt->params->Tuple.variables[pt->variadic_index];
if (is_type_polymorphic(vt->type)) {
o.type = alloc_type_slice(default_type(variadic_operands[0].type));
} else {
o.type = vt->type;
}
o.type = vt->type;
} else {
dummy_argument_count += 1;
o.type = t_untyped_nil;
@@ -5704,7 +5711,6 @@ gb_internal CallArgumentError check_call_arguments_internal(CheckerContext *c, A
if (param_is_variadic) {
continue;
}
score += eval_param_and_score(c, o, e->type, err, param_is_variadic, e, show_error);
}
}
@@ -7154,6 +7160,7 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c
c->decl->defer_used += 1;
}
}
add_entity_use(c, operand->expr, initial_entity);
}
if (operand->mode != Addressing_ProcGroup) {
@@ -7361,11 +7368,11 @@ gb_internal bool check_set_index_data(Operand *o, Type *t, bool indirection, i64
}
return true;
case Type_RelativeSlice:
case Type_RelativeMultiPointer:
{
Type *slice_type = base_type(t->RelativeSlice.slice_type);
GB_ASSERT(slice_type->kind == Type_Slice);
o->type = slice_type->Slice.elem;
Type *pointer_type = base_type(t->RelativeMultiPointer.pointer_type);
GB_ASSERT(pointer_type->kind == Type_MultiPointer);
o->type = pointer_type->MultiPointer.elem;
if (o->mode != Addressing_Constant) {
o->mode = Addressing_Variable;
}
@@ -7753,7 +7760,10 @@ gb_internal void add_constant_switch_case(CheckerContext *ctx, SeenMap *seen, Op
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)) {
Operand to = {};
to.mode = Addressing_Value;
to.type = tap.type;
if (!check_is_assignable_to_with_score(ctx, &to, operand.type, nullptr)) {
continue;
}
@@ -7796,20 +7806,8 @@ gb_internal void add_to_seen_map(CheckerContext *ctx, SeenMap *seen, TokenKind u
break;
}
bool found = false;
for (Entity *f : bt->Enum.fields) {
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);
}
v.value = exact_value_i64(vi);
add_constant_switch_case(ctx, seen, v);
}
} else {
add_constant_switch_case(ctx, seen, lhs);
@@ -7931,7 +7929,7 @@ gb_internal ExprKind check_ternary_if_expr(CheckerContext *c, Operand *o, Ast *n
// NOTE(bill, 2023-01-30): Allow for expression like this:
// x: union{f32} = f32(123) if cond else nil
if (type_hint && !is_type_any(type_hint) && !ternary_compare_types(x.type, y.type)) {
if (type_hint && !is_type_any(type_hint)) {
if (check_is_assignable_to(c, &x, type_hint) && check_is_assignable_to(c, &y, type_hint)) {
check_cast(c, &x, type_hint);
check_cast(c, &y, type_hint);
@@ -8188,6 +8186,104 @@ gb_internal ExprKind check_or_return_expr(CheckerContext *c, Operand *o, Ast *no
return Expr_Expr;
}
gb_internal ExprKind check_or_branch_expr(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) {
ast_node(be, OrBranchExpr, node);
String name = be->token.string;
Operand x = {};
check_multi_expr_with_type_hint(c, &x, be->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, be->expr, x.mode, x.type, x.value);
if (right_type == nullptr) {
check_or_else_expr_no_value_error(c, name, x, type_hint);
} else {
if (is_type_boolean(right_type) || type_has_nil(right_type)) {
// okay
} else {
gbString s = type_to_string(right_type);
error(node, "'%.*s' requires a boolean or nil-able type, got %s", s);
gb_string_free(s);
}
}
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));
}
Ast *label = be->label;
switch (be->token.kind) {
case Token_or_break:
if ((c->stmt_flags & Stmt_BreakAllowed) == 0 && label == nullptr) {
error(be->token, "'%.*s' only allowed in non-inline loops or 'switch' statements", LIT(name));
}
break;
case Token_or_continue:
if ((c->stmt_flags & Stmt_ContinueAllowed) == 0 && label == nullptr) {
error(be->token, "'%.*s' only allowed in non-inline loops", LIT(name));
}
break;
}
if (label != nullptr) {
if (label->kind != Ast_Ident) {
error(label, "A branch statement's label name must be an identifier");
return Expr_Expr;
}
Ast *ident = label;
String name = ident->Ident.token.string;
Operand o = {};
Entity *e = check_ident(c, &o, ident, nullptr, nullptr, false);
if (e == nullptr) {
error(ident, "Undeclared label name: %.*s", LIT(name));
return Expr_Expr;
}
add_entity_use(c, ident, e);
if (e->kind != Entity_Label) {
error(ident, "'%.*s' is not a label", LIT(name));
return Expr_Expr;
}
Ast *parent = e->Label.parent;
GB_ASSERT(parent != nullptr);
switch (parent->kind) {
case Ast_BlockStmt:
case Ast_IfStmt:
case Ast_SwitchStmt:
if (be->token.kind != Token_or_break) {
error(label, "Label '%.*s' can only be used with 'or_break'", LIT(e->token.string));
}
break;
case Ast_RangeStmt:
case Ast_ForStmt:
if ((be->token.kind != Token_or_break) && (be->token.kind != Token_or_continue)) {
error(label, "Label '%.*s' can only be used with 'or_break' and 'or_continue'", LIT(e->token.string));
}
break;
}
}
return Expr_Expr;
}
gb_internal void check_compound_literal_field_values(CheckerContext *c, Slice<Ast *> const &elems, Operand *o, Type *type, bool &is_constant) {
Type *bt = base_type(type);
@@ -9497,14 +9593,14 @@ gb_internal ExprKind check_index_expr(CheckerContext *c, Operand *o, Ast *node,
if (is_const) {
if (is_type_array(t)) {
// OKay
// 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)) {
} else if (is_type_relative_multi_pointer(t)) {
// Okay
} else if (is_type_matrix(t)) {
// Okay
@@ -9642,17 +9738,9 @@ gb_internal ExprKind check_slice_expr(CheckerContext *c, Operand *o, Ast *node,
}
break;
case Type_RelativeSlice:
case Type_RelativeMultiPointer:
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', as value is not addressable", str);
gb_string_free(str);
o->mode = Addressing_Invalid;
o->expr = node;
return kind;
}
o->type = type_deref(o->type);
break;
case Type_EnumeratedArray:
@@ -9731,8 +9819,19 @@ gb_internal ExprKind check_slice_expr(CheckerContext *c, Operand *o, Ast *node,
x[i:n] -> []T
*/
o->type = alloc_type_slice(t->MultiPointer.elem);
} else if (t->kind == Type_RelativeMultiPointer && se->high != nullptr) {
/*
x[:] -> [^]T
x[i:] -> [^]T
x[:n] -> []T
x[i:n] -> []T
*/
Type *pointer_type = base_type(t->RelativeMultiPointer.pointer_type);
GB_ASSERT(pointer_type->kind == Type_MultiPointer);
o->type = alloc_type_slice(pointer_type->MultiPointer.elem);
}
o->mode = Addressing_Value;
if (is_type_string(t) && max_count >= 0) {
@@ -9939,6 +10038,10 @@ gb_internal ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast
return check_or_return_expr(c, o, node, type_hint);
case_end;
case_ast_node(re, OrBranchExpr, node);
return check_or_branch_expr(c, o, node, type_hint);
case_end;
case_ast_node(cl, CompoundLit, node);
kind = check_compound_literal(c, o, node, type_hint);
case_end;
@@ -10005,14 +10108,7 @@ gb_internal ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast
return kind;
}
if (type_hint) {
Type *type = type_of_expr(ac->expr);
check_cast(c, o, type_hint);
if (is_type_typed(type) && are_types_identical(type, type_hint)) {
if (check_vet_flags(node) & VetFlag_Extra) {
error(node, "Redundant 'auto_cast' applied to expression");
}
}
}
o->expr = node;
return Expr_Expr;
@@ -10505,6 +10601,16 @@ gb_internal gbString write_expr_to_string(gbString str, Ast *node, bool shorthan
str = gb_string_appendc(str, " or_return");
case_end;
case_ast_node(oe, OrBranchExpr, node);
str = write_expr_to_string(str, oe->expr, shorthand);
str = gb_string_append_rune(str, ' ');
str = string_append_token(str, oe->token);
if (oe->label) {
str = gb_string_append_rune(str, ' ');
str = write_expr_to_string(str, oe->label, shorthand);
}
case_end;
case_ast_node(pe, ParenExpr, node);
str = gb_string_append_rune(str, '(');
str = write_expr_to_string(str, pe->expr, shorthand);
+7 -2
View File
@@ -102,8 +102,13 @@ gb_internal void check_stmt_list(CheckerContext *ctx, Slice<Ast *> const &stmts,
new_flags |= Stmt_FallthroughAllowed;
}
u32 prev_stmt_flags = ctx->stmt_flags;
ctx->stmt_flags = new_flags;
check_stmt(ctx, n, new_flags);
ctx->stmt_flags = prev_stmt_flags;
if (i+1 < max_non_constant_declaration) {
switch (n->kind) {
case Ast_ReturnStmt:
@@ -1893,7 +1898,7 @@ gb_internal void check_value_decl_stmt(CheckerContext *ctx, Ast *node, u32 mod_f
}
if (is_arch_wasm() && e->Variable.thread_local_model.len != 0) {
error(e->token, "@(thread_local) is not supported for this target platform");
// error(e->token, "@(thread_local) is not supported for this target platform");
}
@@ -1983,7 +1988,7 @@ gb_internal void check_value_decl_stmt(CheckerContext *ctx, Ast *node, u32 mod_f
for (auto const &entry : scope->elements) {
Entity *f = entry.value;
if (f->kind == Entity_Variable) {
Entity *uvar = alloc_entity_using_variable(e, f->token, f->type, nullptr);
Entity *uvar = alloc_entity_using_variable(e, f->token, f->type, e->identifier);
uvar->flags |= (e->flags & EntityFlag_Value);
Entity *prev = scope_insert(ctx->scope, uvar);
if (prev != nullptr) {

Some files were not shown because too many files have changed in this diff Show More