Compare commits

..

2582 Commits

Author SHA1 Message Date
gingerBill aa846d0ea5 Fix union #maybe comparison against nil -llvm-api 2021-04-26 11:46:26 +01:00
gingerBill 8d0428a8b3 Merge pull request #915 from wilsonk/issue-820
Fix for issue 720 (import name is not an identifier)
2021-04-26 10:50:06 +01:00
Kelly Wilson 86c1aed20d Fix for issue 820 (import name is not an identifier) 2021-04-25 23:26:12 -06:00
gingerBill ff620422fa Fix #857 2021-04-25 19:40:02 +01:00
gingerBill 5685a8d885 Fix #911 for -llvm-api backend 2021-04-25 19:19:44 +01:00
gingerBill b8327ad00d Merge pull request #912 from odin-lang/llvm-api-ci-changes
Update Makefile to compile with LLVM C API
2021-04-25 19:02:24 +01:00
gingerBill 1bdce19c18 Update nightly.yml to support -llvm-api 2021-04-25 18:44:05 +01:00
gingerBill 041ff13672 Update CI for Linux 2021-04-25 18:06:29 +01:00
gingerBill 60a2eaf666 Revert changes to macOS Makefile 2021-04-25 18:04:07 +01:00
gingerBill ec2db568c1 Update Makefile for macOS to be more "correct" with Linux 2021-04-25 15:57:35 +01:00
gingerBill 1387fd9047 Make -llvm-api run first before old backend on Linux 2021-04-25 15:52:24 +01:00
gingerBill fb6288a54e Try specifying the specific libs on Linux 2021-04-25 15:48:54 +01:00
gingerBill 4d00058858 Try clang-11 2021-04-24 22:11:38 +01:00
gingerBill 5c26cf9d73 Try llvm-config-11 in the Makefil 2021-04-24 21:58:44 +01:00
gingerBill 6048d25d36 Try llvm-config-11 2021-04-24 21:26:14 +01:00
gingerBill 748f094e15 Add llvm-dev-11 to Linux CI (just testing) 2021-04-24 21:20:18 +01:00
gingerBill 184c686c7e Add clang-11 for Linux; blank out threading_example on darwin 2021-04-24 21:13:40 +01:00
gingerBill 240a568eb9 Update CI to run both old and new backends 2021-04-24 21:09:35 +01:00
gingerBill ad953c4670 Add cast on S_ISDIR 2021-04-24 21:08:15 +01:00
gingerBill 0f9b0c2052 Remove libllvm-11 2021-04-24 21:04:38 +01:00
gingerBill cde334ada3 Modify flags in Makefile 2021-04-24 21:03:22 +01:00
gingerBill 2b4010998d Up ci.yml 2021-04-24 20:55:50 +01:00
gingerBill 4272fe5e85 Update Makefile to compile with LLVM C API 2021-04-24 20:46:47 +01:00
gingerBill c29b643a58 Move out some intrinsics into separate procedures in llvm_backend.cpp; Rename InlineRangeStmt to UnrollRangeStmt (eventually merge the two AST nodes) 2021-04-24 15:00:01 +01:00
gingerBill c9b82a21e9 Move check_builtin_procedure to check_builtin.cpp 2021-04-23 10:01:52 +01:00
gingerBill bd31a99bf7 Remove redundant auto_cast 2021-04-23 09:50:26 +01:00
gingerBill 17bbb48d8a Warn on redundant auto_cast, and make an error on -vet 2021-04-22 17:36:28 +01:00
gingerBill ac53577e9b Improve auto_cast logic 2021-04-22 17:29:48 +01:00
gingerBill 896057b5a7 Reuse unused 'context' variables to minimize stack usage (-llvm-api) 2021-04-22 16:56:02 +01:00
gingerBill 01db195b47 Make main calling convention "odin" rather than "contextless" to simplify code generation 2021-04-22 16:26:28 +01:00
gingerBill d33350e3a5 Add truncate_to_byte and truncate_to_rune for packages strings and bytes 2021-04-22 15:49:10 +01:00
gingerBill 8a86c4c7cc Remove old code 2021-04-22 14:24:30 +01:00
gingerBill 1c9f48031d Change function pass manager passes 2021-04-22 13:54:26 +01:00
gingerBill 7fcd5ecbd5 Change how lb_populate_function_pass_manager works by using the default LLVM passes when not using minimal optimizations 2021-04-22 12:35:01 +01:00
gingerBill b68b090f13 Add intrinsics: overflow_add, overflow_sub, overflow_mul; Change byte swap behaviour in -llvm-api to be the same as the intrinsic 2021-04-22 11:33:46 +01:00
gingerBill 542098dc6f Add intrinsics: byte_swap (integers and floats); count_ones; trailing_zeros; reverse_bits 2021-04-22 11:06:16 +01:00
gingerBill 0a66f8c9a3 Remove intrinsics.x86_mmx type 2021-04-22 10:39:20 +01:00
gingerBill 158e4c0b6c Add @(cold) tag 2021-04-22 10:35:37 +01:00
gingerBill 47c7dc6a9b Add new intrinsics: debug_trap, trap, read_cycle_counter, expect 2021-04-22 10:35:17 +01:00
gingerBill 65551ba8fb Add optimization_mode attribute for procedures
Allowed modes: "none", "minimal", "size", "speed"
Currently: none == minimal and size == speed
2021-04-22 00:04:47 +01:00
gingerBill c7d92562c2 Fix typo 2021-04-21 23:40:19 +01:00
gingerBill 5b3802b8ca Add new -o:<string> flag as an alternative to -opt:<integer> 2021-04-21 23:39:48 +01:00
gingerBill 2fb0383e82 Add -build-mode:llvm-ir for -llvm-api backend 2021-04-21 23:25:08 +01:00
gingerBill 8077d5f565 Merge branch 'master' of https://github.com/odin-lang/Odin 2021-04-21 10:52:34 +01:00
gingerBill 6b45856e81 Remove useless error message for constant binary expressions with non-constant operations 2021-04-21 10:52:26 +01:00
gingerBill 28e5df6e7f Merge pull request #907 from awwdev/fix-variable-name-in-path_unix
fix variable name in path_unix
2021-04-20 21:14:25 +01:00
André 22867ec6f0 fix variable name in path_unix
replace the immutable variable "path" (that is a parameter) with a new variable "path_str"
2021-04-20 22:09:10 +02:00
gingerBill d0a50ff0a3 Merge pull request #905 from jasmcaus/patch-1
Fix potential Typo
2021-04-20 10:44:54 +01:00
gingerBill e9b1d4f633 Fix #906 2021-04-20 10:34:41 +01:00
gingerBill ba9f0dd553 Hack ABI for windows passing pointers to structures 2021-04-19 23:03:22 +01:00
gingerBill c3b3194a00 Update builtin procedures to support the new allocator features (without breaking other code) 2021-04-19 22:44:20 +01:00
gingerBill 201cad51a9 Fix typo 2021-04-19 22:41:52 +01:00
gingerBill d21e522208 Add code that was accidentally removed 2021-04-19 22:35:59 +01:00
gingerBill f1bdd2e60f Improve #optional_ok logic for procedures; Add #optional_second for package runtime usage 2021-04-19 22:31:14 +01:00
gingerBill 0eb75886d1 Allow assignment of procedure calls with #optional_ok to single values 2021-04-19 16:02:36 +01:00
gingerBill 3612569624 Allow casting of #optional_ok call expressions 2021-04-19 15:46:12 +01:00
gingerBill c83d13d0cb Fix update_expr_type behaviour, along with fixing procedure groups updating the proc expr type 2021-04-19 15:12:10 +01:00
gingerBill f98c4d6837 Improve the Allocator interface to support returning Allocator_Error to allow for safer calls
Virtually all code (except for user-written custom allocators) should work as normal. Extra features will need to be added to make the current procedures support the `Allocator_Error` return value (akin to #optional_ok)
2021-04-19 12:31:31 +01:00
gingerBill a4d0092b16 Remove temporary reference types 2021-04-19 11:02:09 +01:00
gingerBill eb49b5f84a Fix override_entity_in_scope behaviour to correctly to report the changes upstream better 2021-04-19 11:01:00 +01:00
Jason Dsouza 9d949ef82e Fix potential Typo : S32 ==> I32 2021-04-19 11:41:02 +05:30
gingerBill ae04af4e4e Add package flags 2021-04-18 20:19:03 +01:00
gingerBill 3baddd4116 Improve init_string determination for constants 2021-04-18 20:13:20 +01:00
gingerBill 6ae468828c Improve odin-doc type information for Named types by storing the base type 2021-04-18 19:59:24 +01:00
gingerBill b59e110fec Add calling_convention to Type 2021-04-18 19:26:36 +01:00
gingerBill 4282688e60 Add calling_convention to odin-doc Type format 2021-04-18 19:26:21 +01:00
gingerBill 9b3fb25a41 Fix enumerated arrays for .odin-doc 2021-04-18 19:15:14 +01:00
gingerBill 2ce9873464 Remove dead comment 2021-04-18 18:53:19 +01:00
gingerBill 986844a0f0 Change elem_counts to i64le from u64 2021-04-18 18:48:56 +01:00
gingerBill 7c1f538c02 Change u32 to u32le 2021-04-18 18:46:29 +01:00
gingerBill 2f1c896290 Add -doc-format command for the new .odin-doc file format (to be used to generate documentation tools) 2021-04-18 18:33:15 +01:00
gingerBill 8827818b1d Clean-up fallback io.read_at and io.write_at behaviour 2021-04-14 21:25:46 +01:00
gingerBill e19958152a Fix floattidf 2021-04-14 20:45:05 +01:00
gingerBill 05a181d719 Fix style issues; Use new attribute @(cold) where appropriate in the new sync package 2021-04-14 20:19:02 +01:00
gingerBill d24784074c Add extra error to io.Error 2021-04-14 20:17:54 +01:00
gingerBill cd2476e084 Add buffer_read_at buffer_write_at 2021-04-14 20:13:26 +01:00
gingerBill ebbc33fdb5 Mockup of the new package os interface (incomplete and non-functioning) 2021-04-14 19:39:12 +01:00
gingerBill 3a4373641b Correct call site attributes 2021-04-14 17:16:10 +01:00
gingerBill 9adec628c1 Add @(cold) attribute to procedure declarations 2021-04-14 17:15:28 +01:00
gingerBill 3e54cddf64 Merge pull request #902 from Kelimion/run_as_user
Add support to core:windows to add/delete users.
2021-04-14 12:15:30 +01:00
gingerBill d602709133 Fix typo 2021-04-14 12:14:44 +01:00
gingerBill 8e1120bc09 Fix typo 2021-04-13 19:23:12 +01:00
gingerBill ebed29fc09 Revert *nix thread stuff to old sync
(I was just testing)
2021-04-13 19:09:04 +01:00
gingerBill bee8beb2c9 Default to pthreads in sync2 for *nix 2021-04-13 19:04:44 +01:00
gingerBill 12296a0dcc Allow intrinsics entities to be exported from other packages if wanted 2021-04-13 18:57:47 +01:00
Jeroen van Rijn 2942e45ff5 Placate -vet for unrelated core:thread update. 2021-04-13 02:23:14 +02:00
Jeroen van Rijn aca5c7c1c6 Placate -vet. 2021-04-13 02:18:47 +02:00
Jeroen van Rijn a1d871360c Add support to core:windows to add/delete users.
main :: proc() {

	using fmt;
	using windows;

	username := "testuser";
	password := "testpass";

	ok := add_user("", username, password);
	fmt.printf("add_user: %v\n", ok);
	pi := windows.PROCESS_INFORMATION{};

	ok2, path := windows.add_user_profile(username);
	fmt.printf("add_user_profile: %v, %v\n", ok2, path);

	ok3 := windows.delete_user_profile(username);
	fmt.printf("delete_user_profile: %v\n", ok3);

	ok4 := windows.delete_user("", username);
	fmt.printf("delete_user: %v\n", ok4);

	// Has optional bool to not wait on the process before returning.
	b := run_as_user(username, password, "C:\\Repro\\repro.exe", "Hellope!", &pi);
	fmt.printf("run_as_user: %v %v\n", b, pi);
}
2021-04-13 02:09:44 +02:00
gingerBill 2b36069924 Fix typo 2021-04-12 17:13:05 +01:00
gingerBill 4fb4ada2c7 Update sync2 to just use atomic intrinsics rather than the parapoly wrappers 2021-04-12 15:22:40 +01:00
gingerBill e3ee005404 Clean up path_unix.odin to make it not depend on package os 2021-04-11 19:05:01 +01:00
gingerBill e8bf1f2064 Minor fixes to platform checking code 2021-04-11 18:59:54 +01:00
gingerBill 1156bd9dd0 Remove thread stuff from sync2; Cleanup package thread 2021-04-11 18:25:56 +01:00
gingerBill 52c193316b Add Thread stuff to new sync package 2021-04-11 15:36:55 +01:00
gingerBill 2db1fe7429 New redesign of core:sync (stored under core:sync/sync2 for the time being) 2021-04-11 15:18:28 +01:00
gingerBill 5bc9e4e4f7 Merge pull request #901 from atkurtul/swarning
fix Syntax Warning
2021-04-09 11:28:06 +01:00
gingerBill 2d99a348b8 Fix proc literal bug not finding the associated DeclInfo 2021-04-09 11:27:44 +01:00
Gitea 011c8d5cda fix Syntax Warning 2021-04-09 13:03:01 +03:00
vassvik 8169cb4853 Fix missing newlines in core:math/linalg/specific.odin 2021-04-09 09:21:20 +02:00
gingerBill 18ab7fb68b Add break; for sanity 2021-04-08 15:32:59 +01:00
gingerBill 3eaf3327d4 Add "Dwarf Version" metadata for darwin on -llvm-api 2021-04-08 15:06:23 +01:00
gingerBill d721ffa6fa Add assertion check on parameter types for lb_emit_call_internal 2021-04-06 11:26:57 +01:00
gingerBill 535048e2b3 Fix LLVMConstIntOfArbitraryPrecision usage for a pointer 2021-04-06 11:07:05 +01:00
gingerBill 050d6f670e Merge pull request #896 from Platin21/Master-Origin
Add's Handling for Return Values for Linker-Stage
2021-04-05 19:06:04 +01:00
Platin21 ae7d7d33d4 Merge remote-tracking branch 'origin/master' into Master-Origin 2021-04-05 19:57:58 +02:00
gingerBill 19470683e7 Add runtime.extendhfsf2 to dependency list 2021-04-05 18:57:09 +01:00
gingerBill 394e4fcbad Add __extendhfsf2 for macOS 2021-04-05 18:44:08 +01:00
Platin21 f722cceef0 Removed debug code 2021-04-05 19:35:03 +02:00
Platin21 66fb2a94ee Adds return values to linker stages 2021-04-05 19:28:19 +02:00
gingerBill f78b2a6090 Undo fix 2021-04-03 18:04:39 +01:00
gingerBill 46bf39cae1 Fix lb_emit_array_ep 2021-04-03 18:03:36 +01:00
gingerBill 46c5c7d1ec Experiment with different opt passes 2021-04-01 23:41:01 +01:00
gingerBill bcda9ddee7 Add core:math/fixed 2021-04-01 17:09:34 +01:00
gingerBill 4a66cbb1f4 Fix signed fixed arithmetic intrinsics 2021-04-01 17:08:34 +01:00
gingerBill f0392d0c75 Cleanup again 2021-04-01 15:46:07 +01:00
gingerBill 3bd39886a0 Cleanup code for fixed-point intrinsics 2021-04-01 15:43:50 +01:00
gingerBill cef698afd6 Implement fixed-point arithmetic intrinsics for -llvm-api backend 2021-04-01 14:36:06 +01:00
gingerBill 0fc04a939e Add f16 support to core:math/linalg 2021-04-01 11:12:40 +01:00
gingerBill 3e1b4c17ac Fix alignment for complex32 and quaternion64 2021-04-01 11:10:17 +01:00
gingerBill b3e788b9d9 Fix missing complex32/quaternion64 checks 2021-04-01 10:56:57 +01:00
gingerBill 63bb26c0e0 Add f16 specific procedures to core:math 2021-04-01 10:52:46 +01:00
gingerBill b3dce34bc6 Add min(f16) and max(f16) support 2021-04-01 10:35:07 +01:00
gingerBill 491b282615 Add extra optimization level pass -opt:2 in lb_populate_module_pass_manager 2021-04-01 10:31:46 +01:00
gingerBill 54e6c50769 Implement f16 functionality 2021-04-01 10:06:00 +01:00
gingerBill a00d7cc705 Merge pull request #884 from corruptmemory/corruptmemory/better-define-errors
Helpful error message for invalid `-define:` cases
2021-03-30 21:59:03 +01:00
Jim Powers 9757af5e4a Helpful error message for invalid -define: cases 2021-03-30 16:49:18 -04:00
gingerBill 3359d0323a Change >> behaviour in LLVM to prevent stupid UB 2021-03-30 20:38:04 +01:00
gingerBill fbd01660ee Experiment with new grammatical parsing rule for expression level (-strict-style) idea 2021-03-30 11:48:32 +01:00
gingerBill bc5e80d7d6 Merge pull request #885 from DanielGavin/parser
Parser fixes
2021-03-30 11:47:45 +01:00
DanielGavin c429c85ade Merge remote-tracking branch 'upstream/master' into parser 2021-03-30 12:42:11 +02:00
DanielGavin 02bbac0903 changed error 2021-03-30 12:40:40 +02:00
DanielGavin b8658547e0 Give error if raw literal hits EOF, and stop removing .Using if it exists in flags and allowed_flags. 2021-03-30 12:38:58 +02:00
gingerBill 2c14accfd0 Merge pull request #879 from Kelimion/partial_hash_updates
Allow seeding CRC32, CRC64 & Adler32 with previous partial hash.
2021-03-30 11:20:19 +01:00
gingerBill 439e2c9242 Fix shifting limits and LLVM code gen bug relating to shifts 2021-03-29 23:15:31 +01:00
gingerBill 6fb0868517 Remove dead code and comments 2021-03-29 22:45:36 +01:00
gingerBill e1588c9322 Remove LLVMPassManagerBuilder usage in lb_populate_module_pass_manager; simplify lb_populate_function_pass_manager 2021-03-29 22:04:54 +01:00
gingerBill 8fcc6ca464 Add LLVM_USE_NO_EXTRA_PASSES build flag 2021-03-29 16:51:06 +01:00
gingerBill faa0240900 Change how lb_populate_module_pass_manager handles the LLVMPassManagerBuilder calls 2021-03-29 16:40:39 +01:00
gingerBill 66941aed0a Clamp maximum optimization level to 2 for -llvm-api 2021-03-29 15:51:15 +01:00
gingerBill fc8c94324e Fix typo 2021-03-29 15:43:33 +01:00
gingerBill 8c20ac1bf0 Add optional LLVM_USE_BASIC_PASSES build flag. If evaluates to a truthy value, it will be do only basic passes for -llvm-api 2021-03-29 14:55:37 +01:00
gingerBill 371094b067 Remove LLVMAddScalarReplAggregatesPass from passes 2021-03-29 14:50:09 +01:00
gingerBill c1e125a009 Change alignment of alloca to a larger one if OdinLLVMBuildTransmute requires it 2021-03-29 14:31:26 +01:00
gingerBill 48767301a4 Another minor change to OdinLLVMBuildTransmute regarding minimum source alignment 2021-03-29 14:11:02 +01:00
gingerBill 253a3edd30 Change OdinLLVMBuildTransmute when to deal with loads 2021-03-29 14:07:25 +01:00
gingerBill 8239cd34eb Issue #823 - Change semantics of disabled attribute to not evaluate any of the parameters at run time 2021-03-27 17:59:01 +00:00
gingerBill 818942b72e Minor code style change 2021-03-27 17:26:38 +00:00
gingerBill 9bac9af022 Clean up code for record type checking 2021-03-27 17:25:56 +00:00
gingerBill 342761e83a Refactor record polymorphic params code for unification 2021-03-27 17:21:12 +00:00
gingerBill 87bc9275fe Correct poly type determination of a where clause for an enumerated array 2021-03-27 16:49:56 +00:00
gingerBill 5ade037b7d Refactor polymorphic parameter for records; Improve error message for parametric polymorphic enumerated array index types 2021-03-27 16:42:42 +00:00
gingerBill 1e587d6635 Fix #883 - polymorphic specialization with target types of enumerated arrays 2021-03-27 15:22:05 +00:00
gingerBill e21d716720 Fix endian conversion to and from floats and ints 2021-03-27 14:33:33 +00:00
gingerBill d62ff39e60 Remove extra passes 2021-03-27 13:30:15 +00:00
gingerBill 0ccf103160 Fix byte swapping for endian specific types in -llvm-api 2021-03-27 12:48:29 +00:00
gingerBill 01c2662de4 Simplify ir_print.cpp escape byte code 2021-03-27 12:17:12 +00:00
gingerBill bd607b131e Fix #882 2021-03-27 12:13:17 +00:00
gingerBill 43ac6ca8f4 Add linalg.matrix_cast 2021-03-26 16:24:56 +00:00
gingerBill 62d2656f69 Add linalg.matrix_cast 2021-03-26 14:33:46 +00:00
gingerBill a611cf545d Add basic error correction in parser to check for unattached else 2021-03-26 11:39:46 +00:00
gingerBill 7463ad23d8 Move variable declarations to aid other compilers 2021-03-25 22:59:15 +00:00
gingerBill 6271d10af7 Fix to OdinLLVMBuildTransmute to goto general_end on different sized data 2021-03-25 22:54:49 +00:00
gingerBill c5c82e0551 Fix pseudo-constant local slice initialization 2021-03-25 22:47:23 +00:00
gingerBill 29ed1d5459 Minor zero enforcement 2021-03-25 22:34:35 +00:00
gingerBill 50b439daa8 Fix pseudo-constant local embedded slice generation 2021-03-25 22:27:52 +00:00
gingerBill 23c68b4f7a Change to assert to test both LLVMIsConstant and LLVMIsGlobalConstant 2021-03-25 22:14:38 +00:00
gingerBill 615104afd1 Revert change :D 2021-03-25 20:59:24 +00:00
gingerBill d3665331c7 Another minor fix to OdinLLVMBuildTransmute 2021-03-25 20:47:10 +00:00
gingerBill 04be6d190e Minor fix to OdinLLVMBuildTransmute 2021-03-25 20:45:22 +00:00
gingerBill 6668fd44cf Merge branch 'master' of https://github.com/odin-lang/Odin 2021-03-25 20:23:49 +00:00
gingerBill 0007ac63ed Correct #c_vararg behaviour on -llvm-api 2021-03-25 20:23:43 +00:00
gingerBill f656968aea Merge pull request #880 from breeo7/master
Add `container.Priority_Queue`
2021-03-25 16:02:22 +00:00
breeo 24e7b5ea78 Add container.Priority_Queue 2021-03-25 15:50:33 +01:00
Jeroen van Rijn f4d0f74dbb Allow seeding CRC32, CRC64 & Adler32 with previous partial hash.
Foo  := []u8{'F', 'o','o', '3', 'F', 'o', 'o', '4'};
crc     := hash.crc32(Foo[0:4]);
crc      = hash.crc32(Foo[4:], crc);
crc_all := hash.crc32(Foo);

fmt.printf("%8x %8x\n", crc, crc_all);
d6285ff7 d6285ff7

a32     := hash.adler32(Foo[0:4]);
a32      = hash.adler32(Foo[4:], a32);
a32_all := hash.adler32(Foo);

fmt.printf("%8x %8x\n", a32, a32_all);
0c5102b0 0c5102b0
2021-03-25 13:48:34 +01:00
gingerBill 7c951cbf0a Add SOA struct len/cap/allocator fields for the debug symbols 2021-03-24 23:12:54 +00:00
gingerBill 2d0e2625ac Ensure pointers are of the same type in LLVM ICmp 2021-03-24 23:01:48 +00:00
gingerBill 1aecd7f5ff Add support for soa slice reference iteration 2021-03-24 22:39:29 +00:00
gingerBill 5faf859a56 Support using on intermediate soa field value from a for-in statement 2021-03-24 22:34:55 +00:00
gingerBill 7028797d53 Implement soa_unzip 2021-03-24 19:29:25 +00:00
gingerBill 6c9d3715d8 Add type hinting to soa_zip 2021-03-24 18:08:34 +00:00
gingerBill 989a03dc77 soa_zip (-llvm-api only): creates an #soa[]struct from passed slices
x := []i32{1, 3, 9};
y := []f32{2, 4, 16};
z := []b32{true, false, true};

s_anonymous := soa_zip(x, y, z);
assert(s_anonymous[0]._1 == 2);

s_named := soa_zip(a=x, b=y, c=z);
assert(s_anonymous[0].b == 2);
2021-03-24 17:33:05 +00:00
gingerBill 7a045bd957 Merge pull request #877 from Kelimion/datetime
Add core:datetime_to_time
2021-03-24 16:59:19 +00:00
gingerBill a5329ae48c Add better package declaration specific error message (#878) 2021-03-24 14:34:30 +00:00
gingerBill 2ec3326653 Support #soa array iteration in a for in loop for -llvm-api backend only 2021-03-24 14:31:44 +00:00
gingerBill bec42e8dd3 Improve core:odin/ast ast.Range_Stmt to use generic number of vals rather than the fixed two to aid with parsing errors 2021-03-24 12:34:06 +00:00
gingerBill d969d0b264 Make for in logic a bit more generic 2021-03-24 12:31:05 +00:00
gingerBill 0e3ecc350a Make the parser support as many identifiers on the LHS in for in loops to improve error messages 2021-03-24 12:11:00 +00:00
gingerBill 295c1550a8 Support using variables in debug information 2021-03-24 10:57:00 +00:00
gingerBill fc1a352285 For bit_set, allow + and - to be aliases for | and &~, respectively 2021-03-23 23:34:01 +00:00
gingerBill 082381284c Remove dead code 2021-03-23 23:23:40 +00:00
gingerBill ccd078620b Improve error message in parser 2021-03-23 23:05:00 +00:00
gingerBill 08f7d3edbe Allow $ in polymorphic record parameter fields (but disallow mixing) 2021-03-23 22:59:10 +00:00
gingerBill c62980eaea Minor improvement to error message about assigning a type to a variable with no inference 2021-03-23 22:33:32 +00:00
gingerBill d88d6a1fdd bit_set support in debug symbols by treating them like a bit field of 1 bit booleans 2021-03-23 22:09:16 +00:00
gingerBill f1e13bdddb Prefix named types with package name in debug types 2021-03-23 20:45:39 +00:00
gingerBill 331167e91f Improve debug type names for composite types (arrays, map, struct, union) 2021-03-23 20:41:49 +00:00
gingerBill e229882fde Clean up some debug type code 2021-03-23 19:33:22 +00:00
gingerBill 300f988905 Add global variables to -llvm-api debug information 2021-03-23 18:34:20 +00:00
gingerBill 7f6a43f0af Move LLVM optimization procedures to a separate file to aid with organization 2021-03-23 18:24:49 +00:00
Jeroen van Rijn 06c5a7fb3e Correct overflowed months. 2021-03-23 18:49:50 +01:00
Jeroen van Rijn 781f784375 Add core:datetime_to_time
datetime_to_time takes separate parameters for date and time values and returns a time.Time and an `ok` bool.

If the values are out of range, they're considered modulo and ok will be set to false.
2021-03-23 18:41:40 +01:00
gingerBill ccd91aee5c Fix debug information for typeid on -llvm-api 2021-03-22 16:14:58 +00:00
gingerBill bf46a3f1d3 Correct debug info for basic composite types (e.g. string, any) 2021-03-22 15:36:18 +00:00
gingerBill 8ab1b32fe1 Add local debug variable support for -llvm-api 2021-03-22 14:51:19 +00:00
gingerBill 0355908af8 Start work on very basic LLVM debug type information 2021-03-22 13:09:23 +00:00
gingerBill fd7d70954e Begin integrating work from branch llvm-debug-symbols 2021-03-20 13:10:53 +00:00
gingerBill cb0bd80f50 Fix LLVMConstArray usage 2021-03-19 16:59:46 +00:00
gingerBill 5a67e6ecbd Fix LLVM asserts 2021-03-19 16:53:22 +00:00
gingerBill c8a823a387 Add ExternC.h 2021-03-19 15:49:07 +00:00
gingerBill 178e891c78 Fix some LLVM asserts by using LLVMConstNamedStruct everywhere 2021-03-19 15:47:10 +00:00
gingerBill bda9eb7348 Update llvm-c headers for Version 11.0.1 2021-03-19 15:46:33 +00:00
gingerBill 2b806f7463 Merge pull request #875 from atkurtul/master
Run an early memcpy pass regardless of the opt flag and return large structs by pointer on linux
2021-03-19 11:07:12 +00:00
atkurtul 6de0b68928 Merge pull request #2 from atkurtul/main
early memcpyopt
2021-03-19 10:26:10 +03:00
atkurtul bb6e6fb4ef Merge pull request #1 from atkurtul/llvm
return by pointer on linux
2021-03-19 07:30:18 +03:00
atil 5f5dfdc00e return by pointer on linux 2021-03-19 07:28:27 +03:00
Atil Kurtulmus 88b8052532 fix windows 2021-03-19 07:23:17 +03:00
atil 2c0ddfb5db fixtypo 2021-03-19 09:57:38 +03:00
atil 2f4902c9b9 fixtypo 2021-03-19 09:54:28 +03:00
atil d28f6144a4 early memcpyopt 2021-03-19 09:52:53 +03:00
gingerBill 3337412228 split*_iterator procedures for package bytes and strings 2021-03-18 13:26:33 +00:00
gingerBill e3f9d99a3b Merge branch 'master' of https://github.com/odin-lang/Odin 2021-03-18 13:25:47 +00:00
gingerBill 359ae29d98 Minor fixes 2021-03-18 13:25:41 +00:00
gingerBill 453b756edc Merge pull request #872 from Kelimion/fix-cubic
Fix typo in cubic().
2021-03-16 15:36:34 +00:00
Jeroen van Rijn d80670fe0c Fix typo in cubic(). 2021-03-16 16:34:59 +01:00
gingerBill 04e0cacd30 Update package core:math/linalg to support matrix3 euler angle operations 2021-03-16 12:14:54 +00:00
gingerBill b94ab4dc05 Make check_single_global_entity use create_checker_context 2021-03-15 14:05:38 +00:00
gingerBill 85fd8aaf37 Merge pull request #868 from nakst/patch-1
Make size of allocation multiple of the alignment
2021-03-15 11:47:48 +00:00
gingerBill 6412a18ae1 Merge pull request #869 from nakst/patch-2
Similar to the update to gb.h
2021-03-14 20:53:30 +00:00
Nakst acefb2edbc Similar to the update to gb.h 2021-03-14 20:37:32 +00:00
Nakst 0d1addf0d4 Make size of allocation multiple of the alignment
To silence an error from GCC's address sanitizer.
2021-03-14 20:36:35 +00:00
gingerBill f5142aaec4 Change from test_* prefix to @(test) attribute for odin test 2021-03-14 18:43:21 +00:00
gingerBill db0ac2ba98 Add "NO TESTS RAN" message to testing.runner if no tests were ran 2021-03-14 18:17:00 +00:00
gingerBill 468ad4837b Add pkg field to testing.Internal_Test 2021-03-14 18:15:08 +00:00
gingerBill 2aa588209e odin test to work with the new core:testing package 2021-03-14 18:01:31 +00:00
gingerBill 10f91a0d3f Make base32 and base64 adhere to -strict-style 2021-03-14 12:54:28 +00:00
gingerBill 8cc4cba06c Add support for backslash \ to consume a newline 2021-03-14 12:53:57 +00:00
gingerBill 8f6439fa6b Simplify expect_semicolon_newline_error rule 2021-03-13 23:17:56 +00:00
gingerBill 81efd2dc64 Remove && false from test code 2021-03-13 21:39:33 +00:00
gingerBill b5c0c68615 Add -strict-style flag: Enforces code style stricter whilst parsing, requiring such things as trailing commas 2021-03-13 21:20:46 +00:00
gingerBill a60d22fefd Make trailing comma usage consistent 2021-03-13 21:18:07 +00:00
gingerBill 8123ff83a3 Fix is_diverging_stmt for invalid statements 2021-03-13 15:01:23 +00:00
gingerBill 4e2a2ac80a Fix formatting of code 2021-03-10 10:53:30 +00:00
gingerBill d23c10d80e Merge pull request #865 from matias-eduardo/patch_llvm_bool_return_types
Add LLVM boolean compatibility to result types
2021-03-10 09:48:57 +00:00
Matias Fernandez ba62bcf116 Add LLVM boolean compatibility to result types 2021-03-09 23:17:34 -04:00
gingerBill 84bb349900 Merge branch 'master' of https://github.com/odin-lang/Odin 2021-03-09 11:40:42 +00:00
gingerBill 3ff7bded64 Add intrinsics.volatile_store and intrinsics.volatile_load 2021-03-09 11:40:36 +00:00
gingerBill 8784b79482 Merge pull request #862 from Kelimion/kelimion/master
Remove double removal of extension when using the -out option.
2021-03-06 23:15:09 +00:00
gingerBill d0f923ba74 Merge pull request #863 from jlreymendez/dll_build_fix
Fix nullref access violation when building with no entry point
2021-03-06 23:14:55 +00:00
Jose Luis Rey Mendez 4e8ec4ce38 Fix nullref access violation when building with no entry point 2021-03-06 20:02:16 -03:00
Jose Luis Rey Mendez 4f1fb73f32 Added vs code to git ignore 2021-03-06 20:01:11 -03:00
Jeroen van Rijn cefde23232 Remove double removal of extension when using the -out option.
When specifying the out parameter, the extension was stripped twice.
If your path contains a ".", this caused issues.

e.g.
cd "C:\Repro\Path With a . In The Name\"
odin run repro.odin -keep-temp-files -out repro.exe

This would cause the files to end up as:
"C:\Repro\Path With a.exe", "C:\Repro\Path With a.ll", "C:\Repro\Path With a.bc" and "C:\Repro\Path With a.obj"

With this patch it works as expected, with or without a . in the file path.
2021-03-06 23:09:15 +01:00
gingerBill 083cec6c88 Remove dead code 2021-03-06 16:11:54 +00:00
gingerBill 45cd5c0b1c Remove test code 2021-03-06 16:11:39 +00:00
gingerBill 572b9d1b3f Fix context bug with deferred_* attributes which caused a new context to be created every time 2021-03-06 16:11:01 +00:00
gingerBill 0ae1b96182 Fix ir_print.cpp i32 line/column values 2021-03-05 15:42:59 +00:00
gingerBill 1988856eed Minimize the size of runtime.Source_Code_Location to use i32 instead of int 2021-03-05 12:56:36 +00:00
gingerBill 15dbc99cb9 Minimize TokenPos size by using i32 for line/column/offset and file_id instead of String
To make `i32` safe, the parser limits the file size of odin files to a maximum of 2GiB (which will be good enough for the vast vast majority of cases)
2021-03-04 16:45:30 +00:00
gingerBill 17eb0ce525 Minor update to math/linalg 2021-03-03 22:18:18 +00:00
gingerBill 619a977856 Improve math/linalg to support both f32 and f64 basic procedures for the specific*.odin files 2021-03-03 16:44:41 +00:00
gingerBill b727b6438b Minimize unneeded casts 2021-03-03 14:31:17 +00:00
gingerBill 75f127af7c Add -vet-extra (checks for unneeded casts and transmutes) 2021-03-03 14:17:48 +00:00
gingerBill c2794b62a9 Clean up logic for << and >> behaviour 2021-03-02 16:48:39 +00:00
gingerBill 4e63ab5edc Re-enable "LLVM Function Pass" 2021-03-02 13:36:57 +00:00
gingerBill 2a1bec9fbb Clean up lb_end_procedure_body logic 2021-03-02 00:43:25 +00:00
gingerBill 6faf024ab4 Remove unneeded return value from incl and excl 2021-03-02 00:40:40 +00:00
gingerBill 35edf45514 Add make_soa and delete_soa; Reorganize soa procedures into a separate file 2021-03-01 18:07:09 +00:00
gingerBill 667aa3671e Fix Addressing for SOA on store; Add intrinsics.type_struct_field_count(T) 2021-03-01 17:54:49 +00:00
gingerBill b428e9ee14 Improve lb_end_procedure_body logic 2021-03-01 15:14:21 +00:00
gingerBill 868117cddd Remove hack in lb_addr_store 2021-03-01 12:59:17 +00:00
gingerBill 9e0210f7f6 Merge branch 'master' of https://github.com/odin-lang/Odin 2021-03-01 12:15:38 +00:00
gingerBill 302742689b Patch win64 ABI problem caused by a bug in LLVM for 128 bit integers 2021-03-01 12:15:28 +00:00
gingerBill 6ffb4d2683 Minor changes to function pass manager in llvm_backend.cpp 2021-02-27 17:47:57 +00:00
gingerBill 4f298a5314 Fix LLVM -opt:2 bug for initializing global variables 2021-02-27 15:54:22 +00:00
gingerBill f49278b5f4 Merge pull request #855 from nakst/master
Update Essence API header
2021-02-27 11:34:38 +00:00
gingerBill a2557142cc Update package os for package path/filepath support on macOS 2021-02-27 11:30:43 +00:00
gingerBill fa09640e7e Fix slice.concatenate 2021-02-27 10:58:10 +00:00
gingerBill 1f9a2df42b Fix crash when a forced dependency doesn't exist 2021-02-27 10:57:44 +00:00
gingerBill ee04dde7c2 HACK check_unchecked_bodies further! 2021-02-26 15:34:12 +00:00
gingerBill 88599eeac1 Update build-m1.sh to remove unneeded macro define 2021-02-26 15:29:41 +00:00
gingerBill 54194af71c Fix patch (yeah... I know) 2021-02-26 15:29:10 +00:00
gingerBill 575c7ff031 Patch issue with minimum dependency system and how it interacts with para poly procedures 2021-02-26 15:09:32 +00:00
nakst 7b4ddd9b18 update essence API header 2021-02-26 14:46:38 +00:00
gingerBill ac155d9036 Merge branch 'master' of https://github.com/odin-lang/Odin 2021-02-26 10:56:40 +00:00
gingerBill d772710ae7 Add message to assert in ir_build_expr_internal 2021-02-26 10:56:32 +00:00
gingerBill 172fc9a46c Merge pull request #853 from ttvd/master
Fixing a typo in llvm backend.
2021-02-25 19:13:49 +00:00
Mykola Konyk 8182d9e828 Fixing a typo in llvm backend. 2021-02-25 13:13:25 -05:00
gingerBill d0ac9f605d Merge branch 'master' of https://github.com/odin-lang/Odin 2021-02-25 13:17:07 +00:00
gingerBill 3eae69effc Make USE_NEW_LLVM_ABI_SYSTEM the actual behaviour and remove the previous approach 2021-02-25 13:17:00 +00:00
gingerBill 53e4c536a1 Merge pull request #852 from Tetralux/fix-dll-mac
Fix -build-mode:shared on Darwin
2021-02-25 12:17:29 +00:00
gingerBill 84deee75cc Make lb_create_enum_attribute ignore certain attributes (they are not properly supported by the actual LLVM C API) 2021-02-25 11:39:46 +00:00
gingerBill 82275082ff Add #force_inline parsing directly to expression statements 2021-02-25 10:01:12 +00:00
gingerBill fc48e9638a Merge branch 'master' of https://github.com/odin-lang/Odin 2021-02-25 09:55:56 +00:00
gingerBill 4a69bfada1 Remove #force_inline for and only have #unroll for 2021-02-25 09:55:48 +00:00
gingerBill 4d13a43590 Enforce -llvm-api on Mac M1 2021-02-25 00:39:44 +00:00
gingerBill b2fdb53e26 fix timings.cpp for M1 2021-02-25 00:39:26 +00:00
gingerBill 58422711d1 Remove sret attribute in llvm_abi.cpp 2021-02-25 00:22:47 +00:00
gingerBill ba817d153c Get compiling on Mac Mini M1 2021-02-24 23:21:34 +00:00
gingerBill 2d88c6c6a5 Begin work on aarch64 ABI for -llvm-api 2021-02-24 16:49:19 +00:00
gingerBill a6fdb5eb5e Add -DUSE_NEW_LLVM_ABI_SYSTEM by default to Windows build for -llvm-api 2021-02-24 16:00:05 +00:00
gingerBill 425bb0579e Default to -microarch:generic 2021-02-24 15:59:31 +00:00
Tetralux a9af8b093d Fix -build-mode:shared on Darwin
Apparently, the '__$startup_runtime' symbol to initialize RTTI stuff has
three underscores (not two) on Darwin!
2021-02-24 02:18:47 +00:00
gingerBill 8f9111e552 Build tag to make all declarations within a file private to the package //+private 2021-02-23 20:40:48 +00:00
gingerBill 731e6ca3a6 Merge branch 'master' of https://github.com/odin-lang/Odin 2021-02-23 20:40:09 +00:00
gingerBill 79eb46bce3 Replace inline uses in the rest of core with #force_inline 2021-02-23 20:39:59 +00:00
gingerBill d39d238754 Merge pull request #851 from WalterPlinge/master
Fixed linalg distance function return type
2021-02-23 20:17:47 +00:00
WalterPlinge 0e9dee62bf Update extended.odin 2021-02-23 20:10:43 +00:00
gingerBill 533dde4648 Add deprecation message for inline and no_inline to use #force_inline and #force_no_inline instead 2021-02-23 16:22:28 +00:00
gingerBill 6988b12012 Replace inline with #force_inline in sys/es/api.odin 2021-02-23 16:15:37 +00:00
gingerBill aa93305015 Replace usage of inline proc with #force_inline proc in the core library 2021-02-23 16:14:47 +00:00
gingerBill 41b854f192 Remove #opaque types 2021-02-23 15:45:06 +00:00
gingerBill 28f279329d Remove bit_field keyword and parsing logic 2021-02-23 15:29:54 +00:00
gingerBill fe33a64b2e Remove #opaque usage in core library 2021-02-23 15:21:05 +00:00
gingerBill f95185a16e Fix new flags 2021-02-23 15:05:03 +00:00
gingerBill 01313eec7f Add flags -ignore-warnings and -warnings-as-errors 2021-02-23 14:59:28 +00:00
gingerBill a1693c0184 Deprecate inline for in favour of #unroll for 2021-02-23 14:45:15 +00:00
gingerBill 657c0ac4f5 Update odin/parser 2021-02-23 14:38:46 +00:00
gingerBill 908a403d78 Add #force_inline, #force_no_inline and #unroll for the transition to deprecate and then remove the keywords inline and no_inline
`inline for` will be replaced with `#unroll for`
2021-02-23 14:37:05 +00:00
gingerBill 28ed310f31 Remove "pure" and "pure_none" calling conventions 2021-02-23 13:10:23 +00:00
gingerBill a652c24ac3 Remove opaque keyboard 2021-02-23 13:02:18 +00:00
gingerBill 595885d3db Remove bit_field in type info, runtime, and general core library 2021-02-19 11:36:23 +00:00
gingerBill efdee0dafb Remove bit_field type from Odin (keyword and dead runtime code still exists) 2021-02-19 11:31:14 +00:00
gingerBill f332cf498d Merge branch 'master' of https://github.com/odin-lang/Odin 2021-02-19 00:05:02 +00:00
gingerBill 6ae619c0a6 Add to package math/bits bitfield_extract and bitfield_insert 2021-02-19 00:04:48 +00:00
gingerBill 7ea86f9c91 Merge pull request #844 from DanielGavin/master
Incorrect setting of allocators in stat_linux and read_dir includes itself and parent
2021-02-12 22:44:22 +00:00
DanielGavin 0f11c47579 set the correct allocators and ignore the previous and parent directory in readdir. 2021-02-12 23:22:53 +01:00
gingerBill 5cced38a6e Add kernel32 memory api 2021-02-11 15:31:51 +00:00
gingerBill d5dfa14f18 Clear up fmt.wprint* length logic 2021-02-11 10:44:38 +00:00
gingerBill fa02dc9736 Fix #840 2021-02-11 10:15:58 +00:00
gingerBill 92431c83ec Change default_temp_allocator_proc behaviour to use the default_allocator when the backing data has not been set. 2021-02-09 14:00:59 +00:00
gingerBill f5418837f0 Minor style clean up 2021-02-04 15:02:07 +00:00
gingerBill 825c5a963f Improve fmt's %#v behaviour for nested records 2021-02-04 14:52:23 +00:00
gingerBill f50ea36c70 Fix miscorrect type usage 2021-02-04 14:24:42 +00:00
gingerBill de9b6e3f6e Correct sys/win32 to match sys/windows 2021-02-04 13:50:48 +00:00
gingerBill 415379e1cf Fix delete_map 2021-02-02 16:30:34 +00:00
gingerBill d168c7936e Fix slices of slices in procedures for -llvm-api 2021-01-27 15:56:32 +00:00
gingerBill aed63a6e8b Update package reflect 2021-01-27 15:27:59 +00:00
gingerBill 98521618e6 Merge branch 'master' of https://github.com/odin-lang/Odin 2021-01-27 15:27:45 +00:00
gingerBill e64eb74eef Fix #831 2021-01-27 15:27:38 +00:00
gingerBill 31528f5ea2 Merge pull request #836 from laleksic/master
Mirror Windows interface for Linux in os module
2021-01-26 12:29:33 +00:00
Luka Aleksić ac184957db Fix CI 2021-01-21 20:55:58 +01:00
Luka Aleksić 92e23ec397 * Add some procedures to path_unix to mirror the path_windows API
* Add files stat_linux and dir_linux to mirror the stat/dir_windows API
* Add helper functions to os_linux that are used by the above
2021-01-21 20:20:38 +01:00
gingerBill c71c86f563 Merge pull request #821 from corruptmemory/corruptmemory/fix-for-c_vararg
Fix for `c_vararg` issue
2021-01-21 16:09:50 +00:00
gingerBill 773be83cad Merge pull request #835 from laleksic/master
Tracking allocator now tracks bad free calls
2021-01-21 16:09:20 +00:00
gingerBill e789e1eac1 Merge pull request #834 from DanielGavin/master
Invalid expression causes segmentation fault in parse_binary_expr in core/odin package
2021-01-21 16:08:30 +00:00
Luka Aleksić 00ebc877a1 Tracking allocator now tracks bad free calls 2021-01-21 00:19:56 +01:00
DanielGavin 3224869c29 handle expr is null in parse_binary_expr 2021-01-20 16:10:16 +01:00
DanielGavin 38c6182280 Merge branch 'master' of https://github.com/DanielGavin/Odin 2021-01-20 16:05:15 +01:00
Jim Powers 24db60eb4b Fix for c_vararg issue
Fixes #817
2021-01-18 20:05:33 -05:00
gingerBill 53d8ec4d15 Add extra error checks 2021-01-18 11:34:09 +00:00
gingerBill 2990b3efd5 Fix #825 2021-01-17 11:59:51 +00:00
gingerBill c653e400db Add extra error checking in parser.cpp 2021-01-15 16:15:03 +00:00
gingerBill e884f8c165 Fix typo 2021-01-15 15:46:15 +00:00
gingerBill 3bcccf88d5 vet all core packages 2021-01-09 23:43:34 +00:00
gingerBill 9e8c46b8de Add time.Tick for performance related timings 2021-01-09 01:08:16 +00:00
gingerBill fba4bfb2d5 Minor cleanup of slice/slice.odin code 2021-01-09 00:40:30 +00:00
gingerBill 79432be784 Add the mini ginger* hashes to package hash 2021-01-09 00:33:34 +00:00
gingerBill 56980e51da Update package io 2021-01-09 00:30:10 +00:00
gingerBill 37253f2621 Add encoding/csv Writer 2021-01-09 00:21:47 +00:00
gingerBill da380d6fc4 Add encoding/csv Reader 2021-01-08 23:24:35 +00:00
gingerBill bf183b2c2c Update c/frontend/preprocessor 2021-01-06 11:22:15 +00:00
gingerBill a07d199a48 Add slice.map_keys, slice.map_values, slice.map_entries, slice.map_entry_infos 2021-01-06 11:21:22 +00:00
gingerBill fa0e4c1294 Add -no-entry-point to help 2021-01-04 08:56:42 +00:00
gingerBill 60fe3c9ec6 Remove unused import from doc.odin 2021-01-02 16:50:24 +00:00
gingerBill a6ce417a35 Clean up doc.odin 2021-01-02 16:44:32 +00:00
gingerBill 6523aefdcc Merge branch 'master' of https://github.com/odin-lang/Odin 2021-01-02 16:36:51 +00:00
gingerBill 31c4a9d770 Add packages "core:c/frontend/tokenizer" and "core:c/frontend/preprocessor" 2021-01-02 16:36:43 +00:00
gingerBill 9fa6427a18 Merge pull request #816 from kennethmaples/file-time-fix
Fix layout of Stat for linux and make usage consistent
2020-12-29 11:38:17 +00:00
kennethmaples 6d5bd8bead Fix layout of Stat for linux and make usage consistent across unix variants 2020-12-29 17:45:19 +08:00
gingerBill 98ad912509 Fix typo 2020-12-27 16:16:04 +00:00
DanielGavin bd6ead32f8 Merge pull request #1 from odin-lang/master
update from master
2020-12-18 14:19:03 +01:00
gingerBill 3558848da8 Fix ir_print.cpp for typeid constants 2020-12-17 17:36:59 +00:00
gingerBill 720f2c7c61 Allow check_expr_with_type_hint to allow assignment of types to typeid without requiring typeid_of 2020-12-17 14:23:45 +00:00
gingerBill e6dfc22b8a Add bytes.buffer_write_to and bytes.buffer_read_from 2020-12-17 00:47:05 +00:00
gingerBill 1470cab842 Make bytes.odin consistent with strings.odin in functionality 2020-12-17 00:36:25 +00:00
gingerBill a31b992d2b Rename bytes/strings.odin to bytes/bytes.odin 2020-12-17 00:25:05 +00:00
gingerBill 5faa560f82 Make container.Map have similar semantics to the built-in map type 2020-12-15 23:23:07 +00:00
gingerBill 6c2b93d519 Improve text/scanner whitespace parameter to use a bit_set instead; Improve error message for for x in y where y is not iterable but allows in as an operator 2020-12-15 22:28:40 +00:00
gingerBill 2957da538d Add strings.Intern 2020-12-15 22:07:53 +00:00
gingerBill 089eccb245 Fix minor constant value declaration bug 2020-12-14 22:47:21 +00:00
gingerBill cbd4aa5392 Remove unused constant 2020-12-14 17:40:57 +00:00
gingerBill 1d333fedaa Support %i as an alternative to %d 2020-12-14 17:00:29 +00:00
gingerBill 82d63306c4 Fix enumerated array index printing bug #808 2020-12-14 16:55:19 +00:00
gingerBill 416051f17b Fix #811 2020-12-14 16:39:31 +00:00
gingerBill f6e2d74d10 Keep -vet happy 2020-12-14 14:36:45 +00:00
gingerBill aa2562fe7c Replace procedure call 2020-12-14 14:33:32 +00:00
gingerBill c17d17a9b4 Remove unused procedure 2020-12-14 14:32:34 +00:00
gingerBill 404c9e40ee Update io/util.odin 2020-12-14 14:31:18 +00:00
gingerBill 34788bfced Merge branch 'master' of https://github.com/odin-lang/Odin 2020-12-13 17:09:47 +00:00
gingerBill cffbd2d276 Add odin/parser/parse_files.odin 2020-12-13 17:09:41 +00:00
gingerBill 9250e4d3df Merge pull request #810 from oskarnp/fix-math-factorial
Fix math.factorial()
2020-12-13 11:17:59 +00:00
Oskar Nordquist 60b9ef1f5d Fix math.factorial() 2020-12-13 02:36:29 +01:00
gingerBill f64584b92a Improve -insert-semicolon rules 2020-12-09 23:40:45 +00:00
gingerBill 9eb12889f4 Merge branch 'master' of https://github.com/odin-lang/Odin 2020-12-09 23:35:14 +00:00
gingerBill 6f6a3f2ccf Fix typos for -insert-semicolon 2020-12-09 23:35:08 +00:00
gingerBill a574ebe5ec Merge pull request #805 from DanielGavin/master
small fixes to the parser
2020-12-09 23:22:11 +00:00
gingerBill 9be0272c13 Merge pull request #806 from arqv/nix
Add Nix derivation
2020-12-09 23:21:21 +00:00
Lyla Bravo 5923470e35 Add Nix derivation 2020-12-09 18:51:37 -03:00
DanielGavin 934809397f small fixes to the parser 2020-12-09 21:33:10 +01:00
gingerBill b6aa549eb8 Fix typo 2020-12-08 17:01:28 +00:00
gingerBill 168532ae8d Add runtime.print_strings 2020-12-08 17:01:06 +00:00
gingerBill d7a5767aa3 If ir_type_requires_mem_zero is stored with zero, don't store again with the zeroinitializer 2020-12-08 15:43:57 +00:00
gingerBill 15bf57e4e1 Fix typo 2020-12-08 15:03:46 +00:00
gingerBill 83cd2473f2 Improve rules for zeroing types with the ir.cpp backend with ir_type_requires_mem_zero 2020-12-08 15:00:07 +00:00
gingerBill 510d1f2518 Add docs to text/scanner 2020-12-07 12:43:28 +00:00
gingerBill 7b55068b04 Unify peek_n with peek and renamescan_peek_n to peek_token 2020-12-07 12:13:41 +00:00
gingerBill b9aa94ee0d Add scan_peek_n to package text/scanner #800 2020-12-07 11:30:54 +00:00
gingerBill 96d8971d87 Add peek_n to package text/scanner 2020-12-07 10:55:27 +00:00
gingerBill 98c8fde098 Remove unused tokens 2020-12-06 13:17:48 +00:00
gingerBill 1ac84b09a1 Add comments to ast.walk related entities 2020-12-06 13:04:11 +00:00
gingerBill 21d8562923 Add ast.walk and ast.inspect 2020-12-06 12:59:26 +00:00
gingerBill c8360f4fff Update ast.clone 2020-12-06 12:08:44 +00:00
gingerBill fe7e4e88c6 Merge pull request #797 from Tetralux/improve-string-parsing
Improve number parsing procedures
2020-12-06 11:43:04 +00:00
Tetralux c06528d702 Improve number parsing procedures
- No longer returns true for partial string parsing.
  All characters in the string must be part of the number.
  i.e: parse_int("2.345") no longer returns (2, true) - it now returns (2, false)

- Return (0, false) on empty strings.
2020-12-06 11:39:03 +00:00
gingerBill ea60db9f53 Add inline asm expression to odin/parser 2020-12-06 01:14:55 +00:00
gingerBill dff4c6b666 Clean up logic 2020-12-06 00:59:23 +00:00
gingerBill 0e9b357a5d Fix typo 2020-12-06 00:55:31 +00:00
gingerBill 1eb1bffd89 Merge pull request #799 from odin-lang/parser-experiments
Add experimental `-insert-semicolon` functionality to tokenizer and parser
2020-12-06 00:53:52 +00:00
gingerBill e8653ac47e Update main.cpp 2020-12-06 00:51:32 +00:00
gingerBill f0683c9102 Merge branch 'master' into parser-experiments 2020-12-06 00:49:48 +00:00
gingerBill ca4657fd31 Add custom semicolon insertion to odin/tokenizer and odin/parser 2020-12-06 00:47:58 +00:00
gingerBill d94414b0f4 Correct ternary if/when parsing 2020-12-06 00:15:35 +00:00
gingerBill 80fead1de5 Add ast.Selector_Expr_Call 2020-12-06 00:03:45 +00:00
gingerBill 069c6cac3f Add package name and source code location to Type_Info_Named 2020-12-05 20:47:50 +00:00
gingerBill 1a8ea6113a Remove hash field in runtime.Source_Code_Location 2020-12-05 19:52:08 +00:00
gingerBill 76e6624dbb Remove type name generation for procedures in ir.cpp 2020-12-05 19:21:00 +00:00
gingerBill 09a52b7ee6 Fix typos 2020-12-05 16:56:09 +00:00
gingerBill 7b36174c17 Fix formatting 2020-12-05 16:38:26 +00:00
gingerBill a82c902f99 Minor correction to bytes.Buffer's vtable 2020-12-05 15:36:02 +00:00
gingerBill 14ae2e0a8d Add bufio.Writer and bufio.Read_Writer 2020-12-05 15:14:21 +00:00
gingerBill 2ab6cdb98e Add package bufio; add bufio.Reader 2020-12-05 12:03:57 +00:00
gingerBill 21c1abe15a Add fmt formatting for runtime.Source_Code_Location 2020-12-05 12:03:38 +00:00
gingerBill 4c41045133 Fix typo in package io 2020-12-05 12:03:07 +00:00
gingerBill 0ed1300bd6 Make bytes.Reader and strings.Reader have the same interface 2020-12-04 21:25:13 +00:00
gingerBill dd63665b58 Update bytes.Reader 2020-12-04 20:33:14 +00:00
gingerBill 9b22583397 Add bytes.Buffer 2020-12-04 20:18:41 +00:00
gingerBill 63f2480951 Begin work on package bytes ([]byte equivalent of package strings) 2020-12-04 19:16:40 +00:00
gingerBill edbb3e3b32 Fix typos 2020-12-04 18:53:17 +00:00
gingerBill ecf324e213 Remove buffered type 2020-12-04 18:50:30 +00:00
gingerBill 7268c80d64 Add strings.fields and strings.fields_proc 2020-12-04 18:50:05 +00:00
gingerBill fd453be831 Deprecate opaque in favour of #opaque in the core library 2020-12-04 18:49:39 +00:00
gingerBill 2a232f2397 Remove the (reserved) keyword macro 2020-12-04 16:14:11 +00:00
gingerBill c4cb7170ee Deprecate keyword opaque in favour of #opaque 2020-12-04 16:13:05 +00:00
gingerBill b6bbe29c8f Remove const as a (reserved) keyword 2020-12-04 16:04:58 +00:00
gingerBill 5d0db4c63a Clean up fmt usage with io.Writer and strings.Builder 2020-12-04 15:04:54 +00:00
gingerBill 05a3bdad58 Allow nested procedures to access @(static) and @(thread_local) variables 2020-12-04 11:28:14 +00:00
gingerBill 0ef02e6737 Improve packages io and strings; add io.Section_Reader 2020-12-03 15:57:46 +00:00
gingerBill 047586afc6 Change ExactValue layout for complex/quaternion types to minimize its size 2020-12-03 14:21:33 +00:00
gingerBill 5acdcfb57c Keep -vet happy 2020-12-03 13:26:33 +00:00
gingerBill 6e04b1c429 Remove using stream on custom stream types in package io 2020-12-03 13:23:36 +00:00
gingerBill 828fe2ce56 Fix #795 2020-12-03 12:25:45 +00:00
gingerBill 18da0b3418 Integrate package io into core library 2020-12-03 10:45:26 +00:00
gingerBill 334a8c46e8 Fix io typos 2020-12-03 00:27:21 +00:00
gingerBill e0fb081cbd Keep -vet happy 2020-12-02 23:46:41 +00:00
gingerBill bca28e94ec Keep fmt happy 2020-12-02 23:43:28 +00:00
gingerBill 875415daa9 Make os._file_stream_vtable private 2020-12-02 23:40:23 +00:00
gingerBill 0cf3ae93c0 Add os.stream_from_handle; fix io.close 2020-12-02 23:39:33 +00:00
gingerBill c4172e3914 Rename stream field names 2020-12-02 23:17:21 +00:00
gingerBill 8e08ae47fb Add strings.Reader 2020-12-02 23:12:43 +00:00
gingerBill d9343ae997 Add package io 2020-12-02 23:12:14 +00:00
gingerBill 4d30b88927 Fix typos 2020-12-02 23:11:46 +00:00
gingerBill 7389ffba6d Fix -llvm-api const initialization of &T{} 2020-12-02 21:07:15 +00:00
gingerBill a6301ab58a Add type_assertion_check2 2020-12-02 11:50:57 +00:00
gingerBill 996c854071 Disable lb_const_hash for the time being 2020-12-02 11:48:50 +00:00
gingerBill a9c1811027 Fix typo 2020-12-02 10:41:18 +00:00
gingerBill 32b1537aa3 Fix xor for constant booleans 2020-12-02 10:39:59 +00:00
gingerBill 2d0c0a7a83 Fix typo 2020-12-01 15:38:15 +00:00
gingerBill 400816ebf7 Fix Pointer store in LLVM backend 2020-12-01 00:40:54 +00:00
gingerBill ef417017f0 Fix typo 2020-11-30 19:46:41 +00:00
gingerBill 7c1c9d22b4 Fix thread.run_with_poly_data* 2020-11-30 19:44:43 +00:00
gingerBill 5803fcc158 Revert function passes 2020-11-29 20:41:01 +00:00
gingerBill f4f2b8f5ad Add _internal field to context 2020-11-29 18:42:13 +00:00
gingerBill dd4f8e9747 Improve default pass manager for -llvm-api 2020-11-29 18:32:49 +00:00
gingerBill f06f33872c Make 16 simple hasher cases for small types 2020-11-29 18:17:21 +00:00
gingerBill 9e13416312 Simplify simple compare hasher code 2020-11-29 17:58:54 +00:00
gingerBill 5ab7ec5b16 Support any comparable type for map keys 2020-11-29 16:37:19 +00:00
gingerBill b922398a96 Sanity check for map key 2020-11-29 16:13:16 +00:00
gingerBill 57f5976ac1 Support map keys for simple compare types 2020-11-29 16:12:21 +00:00
gingerBill 7fbc081119 Improve const hash 2020-11-29 16:03:21 +00:00
gingerBill 1dfe0cdd1d Simplify hashing approach map 2020-11-29 15:50:29 +00:00
gingerBill 97c66c9c73 Add intrinsics.type_hasher_proc; Make map work with generic hasher procedure 2020-11-29 15:27:53 +00:00
gingerBill 085972bb2c Minor clean up 2020-11-29 14:31:42 +00:00
gingerBill 39bed567b3 Add intrinsics.type_equal_proc; Make map use an internal equal procedure to compare keys 2020-11-29 14:22:42 +00:00
gingerBill 2e0fd34e59 Keep -vet happy 2020-11-29 12:52:30 +00:00
gingerBill 9959a069fc Simplify internals of map[K]V 2020-11-29 12:48:33 +00:00
gingerBill c77098a91c Fix for in enum type 2020-11-26 10:19:45 +00:00
gingerBill 89cceb910a Keep -vet happy 2020-11-26 00:09:38 +00:00
gingerBill f36c5de746 Fix typo 2020-11-26 00:05:15 +00:00
gingerBill ca10248740 Add __dynamic_map_fix_keys 2020-11-25 23:50:25 +00:00
gingerBill aa859c2187 Clean up and fix __dynamic_map_erase 2020-11-25 22:36:34 +00:00
gingerBill 8591655334 Clean up __dynamic_map_rehash behaviour 2020-11-25 21:03:20 +00:00
gingerBill 70f5d7a1c9 Enforce zeroing through memset to ensure padding is zeroed with llvm api 2020-11-25 19:50:48 +00:00
gingerBill 1acd5acd70 Remove unused variable 2020-11-25 16:28:13 +00:00
gingerBill dbaf4d24f6 Update package json for new map layout; Correct llvm-api includes for *nix 2020-11-25 16:19:56 +00:00
gingerBill 9c1c9693f2 Patch up gb.h 2020-11-24 15:18:20 +00:00
gingerBill 776c3f4e90 Prepare for M1 Mac 2020-11-24 12:20:48 +00:00
gingerBill a55568b0c4 Make hash internal key be uintptr rather than u64 to reduce entry size 2020-11-23 19:14:36 +00:00
gingerBill b08ec005b2 Keep -vet happy 2020-11-23 18:33:49 +00:00
gingerBill 91758656f6 Change internal layout of map[K]V 2020-11-23 18:25:01 +00:00
gingerBill 4762d2f2d1 map type internal reorganization 2020-11-23 16:56:31 +00:00
gingerBill 67bc35e882 Fix logic for comparisons of struct #raw_union types 2020-11-23 16:19:26 +00:00
gingerBill 4e370e6ed8 Add equal procedure field to runtime.Type_Info_Struct 2020-11-23 15:53:49 +00:00
gingerBill 0b30c3dc5a Add flags: Type_Info_Flags, to runtime.Type_Info 2020-11-23 14:35:31 +00:00
gingerBill 9e42cb1595 Add comparisons to structs where all fields are comparable == and != 2020-11-23 12:20:04 +00:00
gingerBill 4379917c7d Re-enable zeroext for i1 2020-11-22 21:52:39 +00:00
gingerBill dc8e895d72 Merge branch 'master' of https://github.com/odin-lang/Odin 2020-11-22 21:38:52 +00:00
gingerBill a2461bdf6b Modify llvm_abi.cpp to work correctly for win64 abi of i128 types. (it's a pain) 2020-11-22 21:38:45 +00:00
Mikkel Hjortshøj 5cc9ddd40b Update nightly.yml 2020-11-22 02:49:19 +01:00
gingerBill acef96bde7 Merge pull request #787 from dbechrd/dbechrd-mixed-value-error-typo-fix
Update check_expr.cpp
2020-11-22 01:22:48 +00:00
gingerBill e0c028329b Merge pull request #786 from dbechrd/dbechrd-kernel32-typo
Update kernel32.odin
2020-11-22 01:22:18 +00:00
gingerBill 740411f207 Minor change to unicode/letter.odin 2020-11-21 23:14:07 +00:00
gingerBill fa50c8d7d3 Add ODIN_TEST constant for checking if odin test is being run 2020-11-21 11:40:15 +00:00
Dan Bechard 2d878de84d Update check_expr.cpp
Fixed typo in error message `procedure all` -> `procedure call`
2020-11-20 15:43:51 -08:00
Dan Bechard 58f768cb4f Update kernel32.odin
Fix typo in CreateProcessA/W mappings (https://github.com/odin-lang/Odin/issues/785)
2020-11-20 15:39:08 -08:00
gingerBill 260e28c0af Fix casting of untyped strings 2020-11-20 16:30:34 +00:00
gingerBill a14ea5b2b5 Add support for %s and %q for [dynamic]byte 2020-11-20 16:25:11 +00:00
gingerBill 63e4a2341f Support string literals for fixed arrays of runes; Add %q support for arrays/slices of bytes 2020-11-20 16:24:23 +00:00
gingerBill 6416a6f39c Allow string literals for [N]byte 2020-11-20 16:01:59 +00:00
gingerBill 87956676f5 Add %s support for arrays and slices of bytes 2020-11-20 16:01:16 +00:00
gingerBill 913eac13b1 Reorganize runtime code into separate files 2020-11-19 00:08:23 +00:00
gingerBill 3b7fd4711f Fix text/scanner.scan_string 2020-11-18 23:48:01 +00:00
gingerBill fef5172278 Add %q for runes in fmt 2020-11-18 23:40:54 +00:00
gingerBill a39921aa6a Add package text/scanner 2020-11-18 23:33:16 +00:00
gingerBill 9408eb9580 Update odin doc to support multiple package outputs by passing multiple paths; Replace -all with -short
Example:
odin doc core/path core/path/filepath
2020-11-18 23:22:27 +00:00
gingerBill ef2f204c58 Improve system_exec_command_line_app functionality; Restrict test_* procedures to *_test.odin files 2020-11-17 20:33:15 +00:00
gingerBill 30765475c6 Fix up system_exec_command_line_app exit code code 2020-11-17 18:59:48 +00:00
gingerBill 2bd0fd932a Begin rudimentary work on implementing odin test tooling with *_test.odin files 2020-11-17 18:50:30 +00:00
gingerBill 11577db6a8 Minor fixes 2020-11-17 16:36:33 +00:00
gingerBill ede25a88f8 Ignore +build flags in packages comments with odin doc 2020-11-17 16:01:33 +00:00
gingerBill aa5cb7f6a9 Fix proc type printing 2020-11-17 15:54:22 +00:00
gingerBill d730c5b334 Improve file doc logic 2020-11-17 15:48:18 +00:00
gingerBill 34ca4e92eb Fix parser logic for first comment group line in a file 2020-11-17 15:45:55 +00:00
gingerBill 7442f4bab6 Fix typo 2020-11-17 15:17:36 +00:00
gingerBill 4f303603e7 Add more documentation for odin doc flags 2020-11-17 15:15:26 +00:00
gingerBill a0fbc56317 Improve flags for odin doc 2020-11-17 15:13:38 +00:00
gingerBill d90fc18bef Basic odin doc support 2020-11-17 15:05:16 +00:00
gingerBill 00192bb349 Improve flag handling to check for invalid uses 2020-11-17 13:55:08 +00:00
gingerBill edd9d5e50b Add -show-unused-with-location 2020-11-17 13:02:10 +00:00
gingerBill fea8c63ab3 Fix string_compare 2020-11-17 12:19:28 +00:00
gingerBill 6f71d1f2a9 Add -show-unused (Shows unused package declarations of all imported packages)
Crude output at the moment but better than nothing
2020-11-17 12:10:25 +00:00
gingerBill ca4b0527e8 Minimize memory usage for AST nodes by using Slice<T> rather than Array<T> when the parameter doesn't need to grow 2020-11-16 15:18:25 +00:00
gingerBill adf6c85fd3 Minimize Ast flags usage 2020-11-16 01:42:30 +00:00
gingerBill 939878df50 Improve logic for x->y() shorthand 2020-11-15 23:54:18 +00:00
gingerBill 5fafb17d81 Improve generate_entity_dependency_graph: Calculate edges for graph M - Part 2 2020-11-15 22:46:07 +00:00
gingerBill 3a229397e4 Add next_pow2_isize for PtrSet 2020-11-15 21:22:26 +00:00
gingerBill db0bcbc4f4 Fix calling convention for new LLVM ABI, and changePtrSet index to be u32 rather than isize 2020-11-15 21:19:08 +00:00
gingerBill 0d6f5cec37 Implement custom temporary allocator using ring buffer 2020-11-15 19:36:37 +00:00
gingerBill 17ec3e72a6 Add SCOPED_TEMPORARY_BLOCK for temporary allocations within a block 2020-11-15 18:45:40 +00:00
gingerBill 30d922b059 Make set_procedure_abi_types use the permanent_allocator 2020-11-15 18:11:49 +00:00
gingerBill 3c1c10a178 Begin clarifying allocation patterns by changing from heap_allocator to specific arenas 2020-11-15 18:08:52 +00:00
gingerBill 9f93042163 Improve lb_abi_to_odin_type 2020-11-14 17:09:42 +00:00
gingerBill a64ea342df Improve USE_NEW_LLVM_ABI_SYSTEM's System V ABI 2020-11-12 23:40:13 +00:00
gingerBill fa284f9a5a Fix import paths 2020-11-12 14:20:33 +00:00
gingerBill 78b6948ff2 Reorganize package strings 2020-11-12 14:17:41 +00:00
gingerBill a6c5c203ab Begin work on Sys V for new ABI system 2020-11-12 01:21:09 +00:00
gingerBill 70b8b3c7dd Update LLVM backend to begin work on a generic ABI system 2020-11-12 00:43:49 +00:00
gingerBill 6ee4f51670 Add new math procedure: inf_f32 inf_f64 nan_f32 nan_f64 2020-11-11 11:42:21 +00:00
gingerBill e8da2ef65e Update package unicode 2020-11-10 19:00:38 +00:00
gingerBill 6c0fa24e5d Force dependency for @(export) entities 2020-11-10 19:00:16 +00:00
gingerBill 27d0660546 Merge pull request #779 from F0x1fy/master
Add flag -no-entry-point
2020-11-10 17:47:02 +00:00
F0x1fy 0eba4b46b5 Made sure the entry point is not generated when -no-entry-point is specified. 2020-11-10 10:16:22 -07:00
F0x1fy 6b6f1a5283 For the sake of consistency, fixed the placement of the -no-entry-point flag check. 2020-11-10 09:56:16 -07:00
F0x1fy 3bed5fad77 Removed unnecessary newline from previous commit. 2020-11-10 09:55:00 -07:00
F0x1fy 301e1d2ff3 Added -no-entry-point flag and relevant check. 2020-11-10 09:50:53 -07:00
gingerBill 49e140f4db Add utf8.full_rune 2020-11-10 16:47:56 +00:00
gingerBill 95b94a0f56 Fix sync.Channel code; add thread.run_with_poly_data and run_with_poly_data(2|3|4) procedures 2020-11-10 15:00:40 +00:00
gingerBill ee3b3fe6a3 Fix typeid_of bug 2020-11-10 14:48:57 +00:00
gingerBill eea3a1ecd3 Improve sync.Channel to encode the direction into the type 2020-11-09 13:05:02 +00:00
gingerBill 31f4590f4b Fix default parameters on record types 2020-11-09 13:04:36 +00:00
gingerBill 7909a9f5a5 Remove debug code causing bug 2020-11-09 10:36:09 +00:00
gingerBill c26cb470a2 Fix LLVM-API type cycle for procedures of named procedures 2020-11-09 10:27:27 +00:00
gingerBill 3d5e180dec Merge branch 'master' of https://github.com/odin-lang/Odin 2020-11-08 23:55:53 +00:00
gingerBill 44baf56d62 Fix cyclic check in is_type_polymorphic 2020-11-08 23:54:09 +00:00
Mikkel Hjortshøj 11a4dc8ee3 [CI] Done testing webhook 2020-11-08 01:47:09 +01:00
Mikkel Hjortshøj 19e2f7b7bf [CI] testing webhook 2020-11-08 01:46:28 +01:00
Mikkel Hjortshøj 817db70bde [CI] Remove -march for makefile nightly 2020-11-08 01:23:19 +01:00
Mikkel Hjortshøj ef27528ace [CI] Non-sudo install of b2? 2020-11-08 00:31:25 +01:00
Mikkel Hjortshøj a239fcfa3a Update nightly.yml 2020-11-08 00:21:28 +01:00
Mikkel Hjortshøj a77976533c [CI] Add manual trigger to nightly 2020-11-08 00:08:11 +01:00
Mikkel Hjortshøj 06b2a9a3e7 [CI] Try setting python 3.x in nightly upload step 2020-11-08 00:01:31 +01:00
gingerBill 7a7fddd1df Merge pull request #775 from Tetralux/fix-type-table-unix
Fix -build-mode:shared type table on Unix
2020-11-06 20:51:06 +00:00
Tetralux 140bb3ebfc Fix -build-mode:shared type table on Unix
Fixes #527.

Previously on Linux, '__$startup_runtime', the procedure that
initializes the type table for runtime typeids, was NOT called when
a shared library was loaded by the dynamic loader.

This caused the library to not have its type table populated, which
caused an assert to fail if you tried to use runtime typeids - like
core:fmt, for example.

This commit fixes this by calling ld instead of clang, when building a
shared library, so that we can pass "-init '__$startup_runtime'" to it,
when building a shared library.

Try as I might, I could not get clang to correctly pass through
the linker flags that I wanted.
2020-11-06 20:44:11 +00:00
gingerBill 6fab181c0d Merge pull request #774 from F0x1fy/master
Moved internal_windows to internal_any
2020-11-06 19:21:54 +00:00
gingerBill 17271f74c7 Merge pull request #776 from hectormonacci/patch-3
Fix small typo
2020-11-06 19:21:08 +00:00
Héctor M. Monacci 39044b5bb5 Fix small typo
Fix small typo
2020-11-06 15:46:32 -03:00
F0x1fy 94277fe41c As per GingerBill's request, copied the files over to a linux-specific file instead of renaming to . 2020-11-06 11:11:26 -07:00
F0x1fy b5a619e975 Moved internal_windows to internal_any to allow for manual linking related to issue odin-lang/Odin#527. 2020-11-05 22:14:56 -07:00
gingerBill 7c5247f5fb Add package sys/cpu - implements processor feature detection 2020-11-06 00:39:09 +00:00
gingerBill 9ac6d45bd6 Add more procedures to package slice 2020-11-06 00:38:03 +00:00
gingerBill 4cc84002db Merge pull request #773 from Tetralux/fix-slice-last
Fix slice.last()
2020-11-05 15:18:52 +00:00
Tetralux c1d3c3f926 Fix slice.last()
There was a typo that prevented it from being used.
2020-11-05 00:52:32 +00:00
gingerBill 85b2da2e2a Merge pull request #770 from hectormonacci/patch-2
Fix some typos
2020-11-03 13:53:35 +00:00
Héctor M. Monacci 968aa2f688 Fix some typos
Fix some typos
2020-11-03 10:51:56 -03:00
gingerBill 0784b0ac7f Merge pull request #769 from hectormonacci/patch-1
Fix typo
2020-11-03 10:41:39 +00:00
Héctor M. Monacci 44cfa3484f Fix typo
Fix typo (proprosal -> proposal)
2020-11-03 07:40:17 -03:00
gingerBill 54fbdabc38 Add experimental -insert-semicolon functionality to tokenizer and parser 2020-11-01 15:10:06 +00:00
Mikkel Hjortshøj 81398d21ed Merge pull request #768 from Platin21/fix_macos_linking
Fix macOS linking for user/local/libs and object files
2020-10-31 23:18:35 +01:00
Platin21 8c46582667 Fixes text layout now via GitHub 2020-10-31 22:37:11 +01:00
Platin21 f29f7351e9 Revert "Changed tab width was on 2 now 4"
This reverts commit fc7c0ca3b0.
2020-10-31 22:30:03 +01:00
Platin21 fc7c0ca3b0 Changed tab width was on 2 now 4 2020-10-31 22:29:02 +01:00
Platin21 8158239d76 Sets llvm api back to use the generic sdk link 2020-10-31 22:15:16 +01:00
Platin21 f3108493fb Combines all link-able types to a single if and adds .o for linking 2020-10-31 22:12:50 +01:00
Platin21 7694a89d38 Fix for local/lib linking from brew for macOS 2020-10-31 22:05:40 +01:00
gingerBill 75e8e5e06f Merge pull request #767 from SrMordred/patch-1
Update thread_windows.odin
2020-10-31 10:07:33 +00:00
Patric Dexheimer 59b8748c2c Update thread_windows.odin 2020-10-31 02:40:52 -03:00
Patric Dexheimer 2231f02f61 Update thread_windows.odin
`n` was left over being always zero. But you want `win32.WaitForMultipleObjects` to be the number of threads to wait for which u already have with `j`.
2020-10-31 02:37:26 -03:00
Mikkel Hjortshøj f9eadc3e98 Merge pull request #766 from odin-lang/fix-macos-ci
[CI] Fix macOS CI builds
2020-10-29 20:16:19 +01:00
Mikkel Hjortshøj d6057a7ec6 [CI] Fix macOS CPATH for nightly builds 2020-10-29 20:10:26 +01:00
Mikkel Hjortshøj 532d307a75 [CI] Remove test stage for macOS and go back to macos-latest 2020-10-29 20:06:50 +01:00
Mikkel Hjortshøj 6ae8f5a62d [CI] Try and fix CPATH setting for macOS 2020-10-29 20:03:38 +01:00
Mikkel Hjortshøj a5c6487bc1 [CI] Try not installing our own llvm with brew 2020-10-29 19:28:50 +01:00
Mikkel Hjortshøj 6a808235fe [CI] Change deprecated workflow commands for macOS 2020-10-29 19:25:22 +01:00
Mikkel Hjortshøj 61d7cdfe92 [CI] Fix macOS tag 2020-10-29 13:35:53 +01:00
Mikkel Hjortshøj 45815fd26e [CI] Change macos version to 11 from 10.5 2020-10-29 13:33:12 +01:00
Mikkel Hjortshøj c7a2d6970b [CI] Switch xcode version back to 11.7 2020-10-29 13:23:45 +01:00
gingerBill 6912ef1bc1 Merge branch 'master' of https://github.com/odin-lang/Odin 2020-10-29 09:58:15 +00:00
gingerBill 08fae7360a Fix ir printing for nested procedure literals indirectly through identifiers 2020-10-29 09:58:08 +00:00
gingerBill 6772cb0f3b Merge pull request #758 from zhibog/master
Fixed getting windows version. The former function is no longer worki…
2020-10-26 11:36:09 +00:00
gingerBill ce35de47e4 Merge pull request #761 from Tetralux/patch-7
Reuse container.Queue capacity when calling pop_front()
2020-10-26 11:35:25 +00:00
Tetralux 213864a50c Reuse container.Queue capacity when calling pop_front()
Currently, the Queue will never reuse it's full capacity if you call `pop_front`, even if you empty it before pushing more items.

With this change, if you empty the Queue with `pop_front`, then the offset will be set back to the start of the underlying array when you pop the last item.
Future pushes will then reuse the already-allocated--but now empty--space.
2020-10-26 00:12:31 +00:00
gingerBill 4629754f7c Inline asm expression (-llvm-api)
See https://llvm.org/docs/LangRef.html#inline-assembler-expressions
Example:
```
x := asm(i32) -> i32 {
    "bswap $0",
    "=r,r",
}(123);
```
Allowed directives `#side_effect`, `#align_stack`, `#att`, `#intel` e.g. `asm() #side_effect #intel {...}`
2020-10-24 16:32:37 +01:00
gingerBill 0061e63db0 Merge branch 'master' of https://github.com/odin-lang/Odin 2020-10-24 15:08:46 +01:00
gingerBill 5fa488f163 Add intrinsics.cpu_relax for llvm-api 2020-10-24 15:08:35 +01:00
gingerBill 71ef27fef9 Merge pull request #753 from Tetralux/fix-dirnoexist-error
Fix error message when importing package that does not exist
2020-10-24 09:41:26 +01:00
gingerBill 6ea000b648 Merge pull request #752 from powerc9000/patch-4
Fix a few bugs in path based code.
2020-10-24 01:28:15 +01:00
zhibog 05b58bdbb1 Fixed package name 2020-10-24 00:17:36 +02:00
zhibog 4c4112fbc7 Fixed getting windows version. The former function is no longer working on Windows 10. Also fixed the struct to use correct win32 names 2020-10-24 00:14:01 +02:00
gingerBill feeb342c00 Improve multiple return value copy-elision 2020-10-20 17:08:55 +01:00
gingerBill c4dbc88a12 Improve array programming code generation 2020-10-20 15:38:41 +01:00
gingerBill f4b4cd0433 Specific set the code gen level for -llvm-api 2020-10-20 12:43:15 +01:00
gingerBill 4e5b8f2c61 Add -build-mode:assembly for -llvm-api 2020-10-20 12:35:12 +01:00
gingerBill 0be6ddc7e2 Add -microarch:<string> (e.g. -microarch:native) 2020-10-20 12:25:11 +01:00
gingerBill b1bdd95f19 Begin work on making packages import assembly sort files (.S) 2020-10-16 15:32:09 +01:00
gingerBill 063c0548b0 Add new package strings procedures: trim_prefix, trim_suffix, to_valid_utf8 2020-10-16 15:30:14 +01:00
gingerBill 41f6a684e1 Rename slice.sort_proc to slice.sort_by; add slice.sort_by_key 2020-10-16 14:55:36 +01:00
gingerBill 289908e0b8 Add +build ignore tag 2020-10-15 16:25:57 +01:00
gingerBill 5a28a7e0f5 Add intrinsics.type_field_index_of 2020-10-15 16:12:47 +01:00
gingerBill f8e697dbbb Fix indirect selector bug with using on offset_of 2020-10-15 14:58:57 +01:00
gingerBill 7fc3030c63 Update path/filepath to use new slice.sort; Add sort.reverse_interface 2020-10-14 20:47:13 +01:00
gingerBill edd802e1ff Add package slice; New sort.Interface with default sort.sort 2020-10-14 19:52:05 +01:00
gingerBill de13584be2 Add #no_bounds_check to crc procedures 2020-10-14 16:00:08 +01:00
gingerBill 8806283cf7 Improve location information for log.panic* 2020-10-14 15:59:45 +01:00
gingerBill ec5934705c Enforce do bodies to be on the same line as the control statement's condition or token 2020-10-14 15:59:19 +01:00
gingerBill fa33476438 Improve default temp allocator; Fix filepath.abs behaviour on Windows 2020-10-13 14:40:13 +01:00
Tetralux dfac45942c Fix error message when importing package that does not exist
Previously on Linux, if a file in your program tried to import a
package that did not actually exist, read_directory() assumed that
the errno after calling opendir() was ENOTDIR.

This was incorrect.

Instead, we now switch on errno and check for ENOENT, which it is
if the directory does not exist.
2020-10-09 05:56:12 +01:00
gingerBill 1b4bccbc94 Add append_nothing 2020-10-08 12:23:44 +01:00
Clay Murray 062ae56f25 Fix a few bugs in path based code.
Trying to use path.dir and path.rel I found these two issues with the implementation.
2020-10-07 16:32:00 -06:00
gingerBill 6eeb12a986 Improve default temp_allocator; make nil loggers do nothing; improve mem.Scratch_Allocator behaviour 2020-10-02 16:06:55 +01:00
gingerBill a65553293f Add mem.Small_Allocator 2020-10-02 11:09:36 +01:00
gingerBill 8f28312705 Fix pop behaviour, and improve assert messages by using #caller_location 2020-10-02 11:04:17 +01:00
gingerBill 3a4f0d85a6 Fix container.Array and container.Ring 2020-10-01 17:04:56 +01:00
gingerBill c604e359c7 Move flush to within the sbprint* procedures 2020-10-01 12:09:38 +01:00
gingerBill 66c648e5e0 Remove unused variable 2020-10-01 12:05:42 +01:00
gingerBill e83af93394 Allow flushing with strings.Builder; Make fmt.fprint* procedures use a custom flush procedure 2020-10-01 12:03:20 +01:00
gingerBill dd4c02a1b9 Fix multiple declared foreign procedures 2020-10-01 12:02:07 +01:00
gingerBill bc2151f529 Add new os_specific_*.odin files 2020-10-01 10:59:47 +01:00
gingerBill 252a864308 Reimplement the Windows OS dependencies in package runtime 2020-10-01 10:57:02 +01:00
gingerBill 9513cf1ac6 Fix os.stat code; make fmt.panicf diverging 2020-09-30 22:04:39 +01:00
gingerBill c35d533ce5 Replace the *_remove_range with procedures with remove_range 2020-09-30 12:38:40 +01:00
gingerBill 464e733b88 Merge branch 'master' of https://github.com/odin-lang/Odin 2020-09-29 11:11:42 +01:00
gingerBill 519dcc2b76 Add os.read_at and for Windows; fix mem.clone_slice; fix current directory locking code 2020-09-29 11:11:28 +01:00
gingerBill 1818ceb4f2 Merge pull request #747 from Platin21/master
Fixes for MacOS 11 / Big Sur
2020-09-28 12:48:50 +01:00
gingerBill e95addb1f4 Revert user_data addition 2020-09-28 12:40:48 +01:00
gingerBill d343e47a86 Add user_data parameter to filepath.walk and filepath.Walk_Proc 2020-09-28 12:39:34 +01:00
gingerBill 1d21740afb Add filepath.walk 2020-09-28 12:29:14 +01:00
gingerBill 9ae3879956 Add os.stat, os.lstat, os.fstat, filepath.walk 2020-09-28 12:28:02 +01:00
Platin21 6b83159b06 Switched to else instead of not equal 2020-09-27 22:17:35 +03:00
Platin21 d72a01a714 Merge branch 'master' of https://github.com/odin-lang/Odin 2020-09-27 22:13:12 +03:00
Platin21 2ed6785b4a Adds -syslibroot to linker command needed for System.framework 2020-09-27 22:11:23 +03:00
Platin21 f7e40b8572 Adds when statement for framework include 2020-09-27 22:08:33 +03:00
Platin21 a71cbd4087 Changed foreign imports to now use the System Framework 2020-09-27 21:57:27 +03:00
gingerBill 2ebb94fa72 Allow os.read_dir to use a different allocator 2020-09-27 00:31:29 +01:00
gingerBill 96a0125599 Fix typo in reflect.set_union_variant_type_info 2020-09-27 00:30:54 +01:00
gingerBill 626d0736f4 Add more to package reflect (as_string, as_pointer, as_raw_data, relative_pointer_to_absolute) 2020-09-27 00:15:16 +01:00
gingerBill e26f63b448 Update package reflect 2020-09-26 23:51:42 +01:00
gingerBill b9076b0d5b Add package unicode/utf8/utf8string for efficient utf8 codepoint indexing to strings 2020-09-26 23:16:18 +01:00
gingerBill c43b8ef387 Merge branch 'master' of https://github.com/odin-lang/Odin 2020-09-26 23:12:20 +01:00
gingerBill b9f511954a Make runtime.slice_handle_error explicitly diverging 2020-09-26 23:12:04 +01:00
gingerBill 4936713a5e Merge pull request #740 from bttelle/issue-697
Fix issue #697
2020-09-26 21:09:40 +01:00
gingerBill 0bd38ba1f6 Add some comments to explain what the differences between packages path and path/filepath 2020-09-26 20:17:54 +01:00
gingerBill 49eaeccd84 Remove OS specific stuff from package path 2020-09-26 20:02:24 +01:00
gingerBill 840af6825a Update packages os, path, and filepath 2020-09-26 16:02:03 +01:00
gingerBill 3ccaf47566 Remove unused imports 2020-09-25 20:23:29 +01:00
gingerBill 8cc5cd1494 Add package path/filepath; Add os.stat for windows (TODO: unix) 2020-09-25 20:20:53 +01:00
gingerBill 6b634d5e46 Fix fmt with -vet 2020-09-25 15:54:23 +01:00
gingerBill 903ba1c5d8 Add built-in custom formatters for time.Time and time.Duration 2020-09-25 15:47:39 +01:00
gingerBill b42c7f9161 Update package path and fix bugs; add path.match which uses shell pattern matching 2020-09-25 11:43:51 +01:00
gingerBill 654b24e514 Add -disallow-do 2020-09-23 17:17:32 +01:00
gingerBill fc4fdd588e Remove usage of do in core library 2020-09-23 17:17:14 +01:00
gingerBill 4844dd4d96 Add check to block statements to see if they only contain one statement, a value declaration, and err. 2020-09-23 11:16:33 +01:00
gingerBill 609af3a651 Fix and clean up default procedure parameter code for non-constant types 2020-09-22 12:06:05 +01:00
gingerBill 20e4548999 Make llvm-c header use local includes 2020-09-18 13:18:28 +01:00
Joseph Battelle 7490ac2cfd Fix issue #697
Add `is_type_typeid` check to `does_field_type_allow_using`
2020-09-16 21:18:25 -07:00
gingerBill 10afc58d7d Minor style change in parser.odin 2020-09-16 22:28:32 +01:00
gingerBill f5b18482f6 Merge pull request #739 from bttelle/issue-486
Fix issue #486
2020-09-16 22:23:41 +01:00
gingerBill 97d7d8301a Fix ast.Branch_Node parsing in package odin/parser 2020-09-16 22:19:57 +01:00
Joseph Battelle 3a3d415295 Fix issue #486
Use `check_is_assignable_to_using_subtype` in
`is_polymorphic_type_assignable`.

The polymorphic procedure in #486 can now also be written without the
cast:
```odin
print_entity :: proc(e : ^$E, p : proc(^$T) = print_base) { p(e); }
```
2020-09-16 12:32:57 -07:00
gingerBill 33003d1bc1 Update README.md 2020-09-16 20:15:28 +01:00
gingerBill 59d9821bd9 Add intrinsics.type_has_field 2020-09-16 20:08:45 +01:00
gingerBill f530c80216 Fix -debug bug with internal startup procedures 2020-09-16 15:16:29 +01:00
gingerBill 94b27aa64e Merge pull request #737 from nakst/master
update essence platform
2020-09-15 22:28:15 +01:00
nakst c92860e142 update essence platform 2020-09-15 23:22:19 +01:00
gingerBill 4cf240ca05 Fix odin/parser issues 2020-09-15 22:14:23 +01:00
gingerBill ebad8e8990 Change how ir.cpp calls the startup type info procedure 2020-09-15 19:40:37 +01:00
gingerBill 2475c69f00 Remove runtime.os_stdout, since it is not required by the runtime 2020-09-15 14:16:44 +01:00
gingerBill c9dcb7242f Merge branch 'master' of https://github.com/odin-lang/Odin 2020-09-15 12:46:12 +01:00
gingerBill 9d976b04bc Fix +build tag logic 2020-09-15 12:45:44 +01:00
gingerBill 6f1e774a42 Move runtime os specific freestanding stuff to a separate file 2020-09-15 12:36:37 +01:00
gingerBill b94dde2817 Force used of imports in reflect/map.odin 2020-09-15 12:31:21 +01:00
gingerBill 92cd50d3f0 Add TargetOS_freestanding for future use 2020-09-15 12:29:32 +01:00
gingerBill 1ef1407f02 Update ODIN_VERSION 2020-09-15 12:28:15 +01:00
gingerBill edbad0709e Add -default-to-nil-allocator flag (sets ODIN_DEFAULT_TO_NIL_ALLOCATOR) 2020-09-15 12:27:53 +01:00
gingerBill bfc7d74967 Add relfect.map_entry_info_slice 2020-09-15 12:23:49 +01:00
gingerBill 9d91c46cb4 Move all os specific stuff for the runtime to one file 2020-09-15 12:19:56 +01:00
gingerBill 17b3c2ed4c Merge pull request #736 from jockus/json-parse-number-option
Added option to parse number as integer, disabled by default
2020-09-15 12:15:57 +01:00
jockus 8d637f5139 Added parse_integers optional to validation 2020-09-15 12:03:40 +01:00
gingerBill f48a873954 Reorganize package runtime
Separates out the OS specific stuff into different files
2020-09-15 11:52:19 +01:00
gingerBill 4930a9c1a4 Add mem.clone_slice 2020-09-15 11:51:38 +01:00
jockus 195dbd658d Added option to parse number as integer, disabled by default 2020-09-15 11:39:34 +01:00
gingerBill 0cd681e6b7 Expose runtime._startup_runtime to allow for freestanding targets in the future 2020-09-15 10:51:51 +01:00
gingerBill 3211e60018 Merge pull request #734 from krixano/FreeBSD
FreeBSD Support
2020-09-15 10:12:42 +01:00
gingerBill 775bd66382 Merge pull request #735 from bttelle/issue-723
Fix issue #723
2020-09-15 10:05:05 +01:00
Christian Seibold a13eed9894 Cleanup, check sched_param and SCHED_* constants in pthread_freebsd.odin 2020-09-15 01:34:01 -05:00
Joseph Battelle e9c598a426 Fix issue #723
Typo in `check_stmt_internal` for case Ast_UsingStmt; first element
was used for all elements of the enumerated list.
2020-09-14 16:41:53 -07:00
Christian Seibold 65787381c1 Change sizes of pthread types for freebsd 2020-09-14 16:48:55 -05:00
Christian Seibold dd7b29e681 Finish add all errors 2020-09-14 16:18:36 -05:00
Christian Seibold 577be4a8ae Get Odin compiling and produced exe's running on FreeBSD 2020-09-14 15:22:35 -05:00
Christian Seibold ac126a8cd7 Add FreeBSD targets, get gb.h working with FreeBSD, fix odin_root_directory function for FreeBSD and a few other operating systems not yet added 2020-09-14 11:28:41 -05:00
gingerBill d53725fe14 Merge pull request #733 from bttelle/issue-515
Fix issue #515
2020-09-14 14:07:02 +01:00
gingerBill b8bebf4511 Fix typo in Small_Array procedure 2020-09-14 10:10:35 +01:00
Joseph Battelle 2f32b8fb3d Fix issue #515
Modify `check_type_specialization_to` to require exact values
to be equal when called with constant basic types. This also
now allows procedure group members to differ only by constant
value specializations.  See the further example in the issue.
2020-09-13 22:58:05 -07:00
gingerBill 1fd1203d8b Improve error message for multi-valued global declarations not be allowed 2020-09-12 16:04:02 +01:00
gingerBill ccb7c3513b Fix check_arity_match bug 2020-09-12 15:50:42 +01:00
gingerBill bf215377de Add edge case check for "" string 2020-09-11 16:20:46 +01:00
gingerBill d317d3d8b3 Simplify "" string code 2020-09-11 16:18:24 +01:00
gingerBill 77829af9de Fix delete("") on -llvm-api; Fix linalg stuff 2020-09-11 13:46:52 +01:00
gingerBill 97846d8390 Clean up quaternion_from_matrix(3|4) code 2020-09-10 21:19:59 +01:00
gingerBill 079b887313 Make procedure names consistent 2020-09-10 17:32:18 +01:00
gingerBill 6aa708a455 Fix Odin bug with "none" procedure calling conventions in the runtime 2020-09-10 16:36:33 +01:00
gingerBill 8f38b06c60 Add sanity conversion for rand.norm_float64 2020-09-10 15:42:07 +01:00
gingerBill 993fc577b2 Clarify euler angle procedures better 2020-09-10 15:33:50 +01:00
gingerBill 824491f410 Clean up Euler Angle code for math/linalg 2020-09-10 15:23:08 +01:00
gingerBill c1149dbdee Update math and math/linalg; add "pure_none" calling convention 2020-09-10 15:00:19 +01:00
gingerBill 7e625f6ee7 Add extra check for checking uniqueness of package names 2020-09-10 11:13:09 +01:00
gingerBill 2dfa3a5df7 Fix typo 2020-09-07 14:40:36 +01:00
gingerBill 1064622ff7 Improve math/rand functionality 2020-09-07 14:38:01 +01:00
gingerBill f5b8609160 Remove debug print 2020-09-07 12:15:54 +01:00
gingerBill 7f48cf8405 [REFLECTION BREAKING] Modify the internals of the map type to increase performance 2020-09-07 11:41:42 +01:00
gingerBill 7e08bccc9a Merge branch 'master' of https://github.com/odin-lang/Odin 2020-09-04 11:18:58 +01:00
gingerBill 9fd9130891 Add new core procedures: ordered_remove_range; unordered_remove_range; insert_at 2020-09-04 11:18:46 +01:00
gingerBill 9f1f194d18 Merge pull request #727 from JoshuaManton/master-fork
Add allocator parameter to os.read_entire_file()
2020-09-03 08:37:22 +01:00
Joshua Mark Manton 0fe47a2f1b Add allocator parameter to os.read_entire_file() 2020-09-02 18:42:12 -07:00
Mikkel Hjortshøj 31989c93ac Merge pull request #725 from Skytrias/master
fix t0 not being t
2020-08-29 22:48:49 +02:00
Michael Kutowski 7b0ba76915 Update specific.odin 2020-08-29 22:33:24 +02:00
Michael Kutowski bd8ca64a30 Merge pull request #1 from odin-lang/master
Merge pull request #724 from Skytrias/master
2020-08-29 22:32:26 +02:00
Mikkel Hjortshøj 32fda798f3 Merge pull request #724 from Skytrias/master
fix hsl math.mod to usual hsl conversion
2020-08-29 21:58:16 +02:00
Michael Kutowski 12895de9ac fix hsl math.mod to usual hsl conversion 2020-08-29 21:49:49 +02:00
gingerBill 0216ade2f9 Merge pull request #721 from Tetralux/fix-getcwd-allocator
Fix os.get_current_directory() allocator
2020-08-27 11:38:24 +01:00
gingerBill 14e6cdb1a0 Merge pull request #722 from jockus/fix-core-path-name-extension
Fix path.name failing to remove extension
2020-08-27 11:38:04 +01:00
gingerBill 4daf098a3a Fix defer on explicit return of a procedure with no return values for llvm-api 2020-08-27 11:06:44 +01:00
jockus 914c99a15e Merge branch 'master' into fix-core-path-name-extension 2020-08-27 08:24:59 +01:00
gingerBill d31c63c0ae Fix #714 2020-08-27 00:11:02 +01:00
gingerBill c783840eab Fix #642 2020-08-26 23:20:25 +01:00
gingerBill d3eca21e40 Fix style in parse.odin 2020-08-26 22:48:32 +01:00
gingerBill df3690c32a Revert accidental removal of #const for procedure variable parameters #718 2020-08-26 22:46:54 +01:00
gingerBill 999d1a022d Merge branch 'master' of https://github.com/odin-lang/Odin 2020-08-26 22:41:06 +01:00
gingerBill 1f2f3cb315 Fix #712 2020-08-26 22:40:03 +01:00
jockus 8de70ce73d Fix path.name failing to remove extension 2020-08-26 17:32:47 +01:00
Tetralux 3820f27c7c Fix os.get_current_directory() allocator
This procedure accidentally used the temporary allocator for the
returned string.
Use context.allocator, and the allocator parameter idiom instead.
2020-08-26 11:37:44 +00:00
gingerBill 7309cfdbb2 Merge pull request #715 from Platin21/patch-1
Update ring.odin
2020-08-23 17:13:29 +01:00
Mikkel Hjortshoej ea19f3e77f Merge branch 'master' of github.com:odin-lang/Odin 2020-08-23 15:25:45 +02:00
Mikkel Hjortshoej ae2fc5830e Add git sha to odin version command 2020-08-23 15:25:19 +02:00
Platin21 3946f357e8 Update ring.odin
Someone missed the T type here ;)
2020-08-22 13:12:18 +02:00
gingerBill b9b2b90f0c Merge branch 'master' of https://github.com/odin-lang/Odin 2020-08-18 21:12:02 +01:00
gingerBill a6a7395be7 Update unicode/letter.odin 2020-08-18 21:11:51 +01:00
Mikkel Hjortshoej 16b50a2f57 Fix #711 2020-08-18 21:57:47 +02:00
gingerBill e7f54d25d6 Add mem.Allocator_Query_Info and mem.query_info 2020-08-16 23:05:33 +01:00
gingerBill 033b46def8 Add mem.Allocator_Mode.Query_Features, mem.Allocator_Mode_Set, mem.query_features` 2020-08-16 22:07:40 +01:00
gingerBill 1f571f48e5 Add mem.Tracking_Allocator 2020-08-16 21:29:14 +01:00
gingerBill ec178825ec Add more sort.compare_* procedures 2020-08-16 12:40:28 +01:00
gingerBill 6158a49618 Make sync.atomic_* operations use when statements instead of switch; Make #panic diverging 2020-08-16 12:34:12 +01:00
gingerBill 674aeffee4 Fix typo 2020-08-12 19:15:47 +01:00
gingerBill 546759bdef Fix multi_logger_proc to check for lowest_level 2020-08-12 19:01:25 +01:00
gingerBill fa903fb4df Fix #674 2020-08-06 00:09:36 +01:00
gingerBill 5164d1d866 Fix named results but in ir.cpp 2020-08-05 23:43:23 +01:00
gingerBill b6e33a1e64 Ensure add_type_info_type and add_min_dep_type_info are consistent 2020-08-05 23:36:31 +01:00
gingerBill f5248a8d9d Fix #705 2020-08-05 23:33:35 +01:00
gingerBill 74ed779616 Fix #702 2020-08-05 23:14:11 +01:00
gingerBill 9f24188ec8 Fix #708 2020-08-05 22:51:24 +01:00
gingerBill 5551404be4 Fix gb_alloc_str_len 2020-08-05 22:32:27 +01:00
gingerBill 9fd35776fd Fix typos in math.odin 2020-08-04 14:40:11 +01:00
gingerBill 3385fcecb0 Fix typo 2020-08-04 14:31:14 +01:00
gingerBill 804b96a985 Remove unused entities 2020-08-02 15:11:21 +01:00
gingerBill 9cc20954a3 Add sys/windows/synchronization.odin 2020-08-02 15:07:52 +01:00
gingerBill 91ff3e5bca Add sync/channel_*.odin files 2020-08-02 15:05:04 +01:00
gingerBill 6d032e6f1a Update package sync 2020-08-02 15:01:17 +01:00
gingerBill 16abfd56e8 Merge branch 'master' of https://github.com/odin-lang/Odin 2020-08-02 14:59:51 +01:00
gingerBill d1d5f61230 Add intrinsics.alloca 2020-08-02 14:59:39 +01:00
gingerBill 5b7e1cd6f6 Update LICENSE 2020-08-01 11:35:56 +01:00
gingerBill cbfe3571ab Merge pull request #693 from powerc9000/patch-2
Fix pthread_t on Macos.
2020-07-22 22:28:38 +01:00
gingerBill b04bc21ec6 Merge pull request #704 from oskarnp/log_thread_id
Add .Thread_Id option to log package
2020-07-22 22:27:53 +01:00
gingerBill 2945feecde Merge pull request #703 from oskarnp/darwin_thread_id
Implement os.current_thread_id() for Darwin (assumes OSX 10.6 / iOS 3…
2020-07-22 22:27:02 +01:00
Oskar Nordquist 36cac87387 Add .Thread_Id option to log package 2020-07-22 17:42:01 +02:00
Oskar Nordquist a7e38dc063 Implement os.current_thread_id() for Darwin (assumes OSX 10.6 / iOS 3.2 and later) 2020-07-22 17:38:13 +02:00
gingerBill 0aaab84938 Allow multiple -define flags 2020-07-16 20:59:03 +01:00
gingerBill 3a1492fc99 Add sync.Wait_Group 2020-07-15 00:25:37 +01:00
gingerBill ca818fb857 Remove comments containing unicode characters from tokenizer 2020-07-14 23:51:46 +01:00
gingerBill 13e5cb8cc4 Fix #691 and Fix #692 2020-07-14 23:50:09 +01:00
gingerBill 7ae54ae3b4 Add -no-dynamic-literals to disallow dynamic array and map literals 2020-07-14 23:01:34 +01:00
gingerBill b2beb9512f Add thread.join_multiple 2020-07-14 21:08:04 +01:00
gingerBill 96ad6d2084 Improve sync.Channel behaviour 2020-07-14 18:43:50 +01:00
gingerBill 86f1574f78 Fix #696 2020-07-14 16:43:23 +01:00
gingerBill 6565a49e34 Remove fmt from sync/channel.odin 2020-07-14 16:39:47 +01:00
gingerBill ce85b73eca Add sync.Once 2020-07-14 16:38:54 +01:00
gingerBill fc65aee307 Update sync.Channel 2020-07-14 16:37:29 +01:00
gingerBill ede135a08f Merge branch 'master' of https://github.com/odin-lang/Odin 2020-07-14 16:36:47 +01:00
gingerBill c18fc2da9f Remove some dead code 2020-07-14 16:36:33 +01:00
gingerBill c8a3937ea0 Merge pull request #695 from jharler/master
Added "sep" parameter to logging procs
2020-07-13 13:28:30 +01:00
jharler f9a6777e3a Added "sep" parameter to logging procs 2020-07-13 08:22:41 -04:00
Clay Murray 83eabe2140 Fix pthread_t on Macos.
From some testing with directly using C code, pthread_t on macos is 8 bytes.
This is my test code:

```
#include <assert.h>
#include <stdio.h>

#include <pthread.h>



void* PosixThreadMainRoutine(void* data)

{

	// Do some work here.
	for (int i = 0; i < 2000000000; i++) {

	}



	return NULL;

}



pthread_t LaunchThread()

{

	// Create the thread using POSIX routines.

	pthread_attr_t  attr;

	pthread_t       posixThreadID;

	int             returnVal;



	returnVal = pthread_attr_init(&attr);

	assert(!returnVal);

	returnVal = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

	assert(!returnVal);



	int     threadError = pthread_create(&posixThreadID, &attr, &PosixThreadMainRoutine, NULL);



	returnVal = pthread_attr_destroy(&attr);

	assert(!returnVal);

	if (threadError != 0)

	{

		// Report an error.

	}

	return posixThreadID;

}

int main() {
	pthread_t t = LaunchThread();

	void ** ret;


	printf("%d, %d\n", sizeof(t), sizeof(pthread_t));

	int val = pthread_join(t, ret);


	printf("%d", val);
	return 0;
}
```
running this on macos reports `8, 8`. 
Then I made the proposed changes and errors I was having with threads completely went away.
2020-07-11 18:22:56 -06:00
gingerBill c4067372dd Fix double declaration 2020-07-10 22:28:48 +01:00
gingerBill b4e976364a Add path_unix.odin 2020-07-10 08:42:59 +01:00
gingerBill 642afa4f88 Fix new package path 2020-07-10 08:42:22 +01:00
gingerBill f65fa0e4a6 Merge pull request #339 from dotbmp/master
"core:path" Path library and "core:strings" `split` Utilities
2020-07-10 08:25:24 +01:00
gingerBill 65b9dbe13f Clean-up OS constants; Clean-up procs_wasm32.odin 2020-07-09 17:21:40 +01:00
gingerBill cb52f6986a Fix Addressing_OptionalOk selector expression rules for struct field variables 2020-07-08 23:39:49 +01:00
gingerBill 94ba182691 Add sync.Benaphore 2020-07-08 23:16:54 +01:00
gingerBill 5b7c83d871 Add strings.pop_byte strings.pop_rune 2020-07-08 23:15:48 +01:00
gingerBill 4059542afb Merge pull request #673 from kevinw/patch-2
add `#config` to odin parser
2020-07-08 23:08:31 +01:00
gingerBill 9da1347c21 Fix Source_Code_Location error for *_insert_dynamic_map_key_and_value procedures 2020-07-08 22:57:39 +01:00
gingerBill a8c10c58b4 Fix negation of complex and quaternion numbers for ir.cpp backend 2020-07-08 22:35:47 +01:00
Mikkel Hjortshøj 6d9b2ec5b4 Merge pull request #685 from ThisDrunkDane/master
Fix misplaced line number in log (was wrongly formatted and before procedure)
2020-07-05 19:53:22 +02:00
Mikkel Hjortshoej d749f5c704 Fix typo 2020-07-02 16:13:49 +02:00
Mikkel Hjortshoej 83f553cd89 Revert to old format and fix : when no file opt specified 2020-07-02 16:11:41 +02:00
Mikkel Hjortshoej 730f9ee0b3 Fix misplaced line number (was wrongly formatted and before procedure) 2020-07-02 15:31:40 +02:00
gingerBill 51e50d3e31 Add intrinsics.type_proc_parameter_type; Add intrinsics.type_proc_return_type 2020-07-01 22:35:38 +01:00
gingerBill 1b2cc739a9 Handle llvm package name edge case for IR mangling 2020-06-30 19:12:53 +01:00
gingerBill 7bdd8094d6 Fix signature_parameter_similar_enough logic 2020-06-30 19:10:24 +01:00
gingerBill 323fc7a6a9 Fix system calls for compiler 2020-06-30 19:04:14 +01:00
gingerBill 92363da58e Add -show-system-calls; Update runtime for windows_386; Fix some minor bugs 2020-06-30 10:09:58 +01:00
gingerBill 0ea64182f1 Begin work on windows 386 2020-06-29 17:35:33 +01:00
gingerBill 8478b887a5 Add mem.check_zero and mem.check_zero_ptr 2020-06-29 16:17:40 +01:00
gingerBill 86448ee044 Add raw_data to replace cases in which &x[0] was used 2020-06-29 15:58:24 +01:00
gingerBill 56a52a1d06 Add sync.condition_wait_for_timeout for unix 2020-06-27 12:21:31 +01:00
gingerBill 858c5f8fd8 Update thread_unix logic 2020-06-27 11:36:48 +01:00
gingerBill f92b4c7849 Update sys/unix; Rename thread.create_and_start 2020-06-27 11:26:38 +01:00
gingerBill 9fdebebd28 Add sync.Barrier; Add sync.Blocking_Mutex for unix 2020-06-27 11:23:37 +01:00
gingerBill 2b18f43b65 Update sys/windows; Add sync.Blocking_Mutex (windows only at the moment) 2020-06-27 00:59:40 +01:00
gingerBill 53e1512978 Add more exception handling stuff to sys/windows 2020-06-26 20:42:17 +01:00
gingerBill b5f9c95ce7 Remove foreign import for -vet 2020-06-26 20:33:47 +01:00
gingerBill 231f91304a Keep previous behaviour for sync but move to sys/windows 2020-06-26 20:30:33 +01:00
gingerBill d7b3f3a0e7 Revert sync_windows.odin 2020-06-26 20:22:48 +01:00
gingerBill bb81d4869f Update sys/windows 2020-06-26 20:09:31 +01:00
gingerBill b633a42bc2 Revert channel.odin 2020-06-26 19:16:17 +01:00
gingerBill 6bd05ef5d7 Begin migration from sys/win32 to sys/windows 2020-06-26 19:11:34 +01:00
gingerBill 251a3a690e Add optional sep parameter to fmt.*print and fmt.*println procedures 2020-06-25 15:00:50 +01:00
gingerBill f22b014db0 Revert build.bat 2020-06-23 09:20:13 +01:00
gingerBill a6edcf4f18 Fix ABI typo bug; Add pop_safe and pop_front_safe 2020-06-22 21:03:57 +01:00
gingerBill 2a598aa061 Update sync.Channel 2020-06-22 17:45:01 +01:00
gingerBill 910ab7b3d4 Fix typo 2020-06-22 17:00:35 +01:00
gingerBill 2b27300387 Fix LLVM code gen bug 2020-06-22 16:57:21 +01:00
gingerBill 0db1ebb4e5 -vet sync/channel.odin 2020-06-22 16:01:26 +01:00
gingerBill 0013033f9a Revert build.bat 2020-06-22 15:58:48 +01:00
gingerBill f00123742c Add experimental sync.Channel 2020-06-22 15:54:35 +01:00
gingerBill 509e8b512f Add time.read_cycle_counter 2020-06-22 15:54:19 +01:00
gingerBill 2562df5387 Remove unused imports in thread.odin 2020-06-22 13:35:44 +01:00
gingerBill 0ab356aa4e Fix sync and thread on *nix 2020-06-22 13:32:58 +01:00
gingerBill b3c51a8b44 Add thread.run* shorthand procedures; Thread.init_context use new Maybe concept 2020-06-22 13:28:37 +01:00
gingerBill fb3aeccd36 Add built-in Maybe 2020-06-22 13:25:19 +01:00
gingerBill 9495e3d10c Update sync.Condition to require a ^sync.Mutex on init 2020-06-22 13:24:51 +01:00
gingerBill 0f711b8719 Remove old llvm-demo 2020-06-21 20:04:29 +01:00
gingerBill 2a6130b7e1 Reorder log.do_location_header order 2020-06-19 15:24:42 +01:00
gingerBill 34384cc2f1 Clean up some of the log code 2020-06-19 15:18:23 +01:00
gingerBill aeafed0218 Add fmt.DEFAULT_BUFFER_SIZE to be configurable with #config(FMT_DEFAULT_BUFFER_SIZE, 1<<12) 2020-06-19 15:08:54 +01:00
gingerBill 3a4bbfcfae Change fmt.*print behaviour to match fmt.*println behaviour 2020-06-19 15:01:39 +01:00
gingerBill 01c84b32a6 Add log.panic and log.panicf 2020-06-19 12:23:06 +01:00
gingerBill 240fc65d4d Add multi_logger.odin; Fix os_windows.odin 2020-06-19 11:49:08 +01:00
gingerBill c9d3b95b0d Fix time.now 2020-06-19 11:35:43 +01:00
gingerBill 9f596d6f34 Clean up package log code 2020-06-19 11:18:23 +01:00
gingerBill 2a684830f9 Fix using pointers bug with addressing struct fields 2020-06-18 17:50:54 +01:00
gingerBill c4ba3f1c83 Merge branch 'master' of https://github.com/odin-lang/Odin 2020-06-17 23:28:46 +01:00
gingerBill 724c776dbe Fix enumerated array type information creation bug 2020-06-17 23:28:39 +01:00
Mikkel Hjortshoej ad8048b615 [CI] Use powershell to download LLVM on windows, split macOS and linux. 2020-06-16 18:12:43 +02:00
gingerBill 781395ada1 Add deferred_in_out attribute 2020-06-16 16:21:44 +01:00
gingerBill 9635ea8706 Revert demo.odin 2020-06-16 16:08:51 +01:00
gingerBill 413188bab2 Merge branch 'master' of https://github.com/odin-lang/Odin 2020-06-16 16:07:53 +01:00
gingerBill 5fa54fd2cc Commit fix 2020-06-16 16:07:44 +01:00
gingerBill b79e1b6b5c Cleanup package encoding/json 2020-06-16 16:05:15 +01:00
gingerBill 8dff0f7ef5 -vet code 2020-06-16 12:57:06 +01:00
gingerBill f85f3dce12 Revert demo.odin 2020-06-16 12:55:09 +01:00
gingerBill 5edb1e8a28 Add hash.djb2 hash.jenkins; Add container.Bloom_Filter; Add container.Ring 2020-06-16 12:53:57 +01:00
gingerBill f70939ab4f Use windows specific exception traps 2020-06-15 12:39:29 +01:00
gingerBill 08e271720a Merge branch 'master' of https://github.com/odin-lang/Odin 2020-06-15 11:54:28 +01:00
gingerBill c3ebc49ad2 Fix @static slice for LLVM C API backend 2020-06-15 11:54:18 +01:00
vassvik 9cccb20f49 Add some tests to test utf16_to_utf8 and wstring_to_utf8 2020-06-13 18:04:19 +02:00
vassvik 6985d72fda Make os.get_current_directory no longer strip the zero at the end of the resulting string, as it no longer should occur. 2020-06-13 15:20:39 +02:00
vassvik 0056cdffa7 Reworked win32.utf16_to_utf8 and win32.wstring_to_utf8 to scan for zeros from the start of the string instead of from the end.
This is useful to correctly convert strings from a buffer possibly containing multiple multiple substrings.

The resulting utf8 string is not null terminated, even if the backing memory might be null terminated.
2020-06-13 15:19:41 +02:00
gingerBill a229f9825b Fix -vet warning for fmt.printf("%10s") 2020-06-12 23:13:26 +01:00
gingerBill a6ff48a5de Merge pull request #681 from ralph-the-mighty/stringwidth
Control %s width in fmt.print* functions
2020-06-12 23:10:28 +01:00
Josh 6648dc9ed1 use width in when printing formatted string to control padding added after the string 2020-06-12 18:05:40 -04:00
vassvik bbbf7168f1 Add wstring_to_utf8 to sys/win32 2020-06-12 21:06:21 +02:00
vassvik c15ed44f82 Fix off by one bug introduced in the previous commit. 2020-06-12 18:19:46 +02:00
gingerBill 58466a6f3b Add extra NUL termination check for string length in win32 general string convertors 2020-06-12 15:01:43 +01:00
gingerBill be76c860a5 mem.simple_equal 2020-06-12 14:52:31 +01:00
gingerBill 4533c02cc7 Improve intrinsics.type_is_simple_compare 2020-06-12 14:37:27 +01:00
gingerBill 01d12770fa Fix compound literals for constant procedure fields 2020-06-11 16:11:54 +01:00
gingerBill 82b559c32b Remove debug code 2020-06-10 19:29:24 +01:00
gingerBill 474d79dcf1 Add mem.simple_compare_values 2020-06-10 16:37:22 +01:00
gingerBill 61db6c1234 Add force usage when importing intrinsics or builtin 2020-06-10 16:36:59 +01:00
gingerBill e641d714a0 Fix #677 2020-06-10 16:32:53 +01:00
gingerBill f305726015 Fix #c_vararg for LLVM C API 2020-06-10 16:15:56 +01:00
gingerBill 57b09b2ffb Fix #439 2020-06-10 15:37:50 +01:00
gingerBill e86fde3cb1 Fix #648 2020-06-10 15:09:04 +01:00
gingerBill 99944f3b02 Improve behaviour of return with named results to aid with defer statements 2020-06-10 14:53:35 +01:00
gingerBill a9295d33ab Fix #674 2020-06-10 14:39:50 +01:00
gingerBill 4acae2af44 Add support for using on relative pointers #670 2020-06-10 14:25:11 +01:00
gingerBill 036429bf2f Fix reflect.as_i64 and reflect.as_u64 2020-06-10 14:13:50 +01:00
gingerBill d0920804c3 Stop statement generation after terminating instruction in current block (LLVM C API) 2020-06-10 13:57:25 +01:00
gingerBill 97d3d4ff6f Minor changes for \*nix backend 2020-06-10 13:38:17 +01:00
gingerBill 6ea0910213 Fix typo 2020-06-10 13:02:42 +01:00
gingerBill b8d33165c9 Add -target:<string> fuzzy checking with "Did you mean" message 2020-06-10 12:59:54 +01:00
gingerBill 6b3ee447f0 Basic cross compilation support 2020-06-10 12:26:31 +01:00
gingerBill 9b1cc6e94f Update logic for slice literals, backing array to be on the stack if possible (LLVM C API) 2020-06-08 12:41:42 +01:00
gingerBill 0ffb718a91 Add fmt.User_Formatter 2020-06-08 12:40:50 +01:00
gingerBill a7dd686859 Add #caller_location to strings.clone; remove deprecated procedures in package strings 2020-06-08 11:42:38 +01:00
gingerBill 87a6d695d6 Fix typo in error message 2020-06-06 22:39:36 +01:00
gingerBill a89633e3ed Remove return after unreachable 2020-06-06 15:22:22 +01:00
gingerBill 59a0bbb385 Improve termination rules checking for missing return; Make diverging procedure -> ! be terminators 2020-06-06 15:16:24 +01:00
gingerBill a3fa647bfd Add package sys/llvm to expose some of the LLVM intrinsics 2020-06-06 14:52:22 +01:00
gingerBill 1a4e2196bd Fix runtime.bswap_16 2020-06-05 14:12:30 +01:00
gingerBill d8f9daac95 Fix different endian integers for LLVM C API backend 2020-06-05 13:12:57 +01:00
gingerBill f992e36f9a Rename reflect.to_* to reflect.as_* 2020-06-05 10:38:38 +01:00
gingerBill 11dd971e13 Add reflect.{to_int, to_uint, to_i64, to_u64, to_f64} 2020-06-05 10:27:32 +01:00
gingerBill 5ed4bac16f Merge pull request #676 from Tetralux/fix-temp-alloc-resize
Fix temporary allocator resizing
2020-06-04 23:13:41 +01:00
Tetralux 04ceb5d20c Fix temporary allocator resizing 2020-06-04 21:49:07 +00:00
Kevin Watters 0b67de47d6 add #config to odin parser
Update the `core:odin` parser for the new `#config` idiom.
2020-06-04 10:48:13 -04:00
gingerBill 15c4077806 Fix WASM foreign import names 2020-06-04 00:30:44 +01:00
gingerBill 37a3abdaaa Fix calling convention stuff with LLVM C API 2020-06-03 21:23:30 +01:00
gingerBill ac709b8afb Merge branch 'master' of https://github.com/odin-lang/Odin 2020-06-03 21:10:18 +01:00
gingerBill d80049bfd2 Change runtime.Type_Info_Enum_Value to be i64 internally rather than a union 2020-06-03 21:10:07 +01:00
gingerBill 239f3c0418 Merge pull request #672 from foxnne/fixwrap
Fix wrap in core:math.
2020-06-03 14:57:43 +01:00
gingerBill 5b11a842a8 Merge pull request #668 from kevinw/patch-1
Remove `intrinsics` import
2020-06-03 14:56:36 +01:00
gingerBill 626b4740b1 Add wasm-ld support for wasm code generation 2020-06-03 13:12:38 +01:00
foxnne 437d5e28cd fix wrap in core:math 2020-06-02 00:37:06 -05:00
Kevin Watters 6c7fc4212a Remove intrinsics import
When using `linalg` with the `-vet` compiler switch, you get the warning/error:

`odin/core/math/linalg/specific.odin(4:8) 'intrinsics' declared but not used`
2020-06-01 18:44:47 -04:00
gingerBill 8589af1458 Improve bits.rotate_left* 2020-05-31 16:19:08 +01:00
gingerBill bf5ce04b24 Improve rules for shifting behaviour
Example:
x: u64 = 123;
assert(x >> 64 == 0); // In C this would be 123 because (64 & 0b111111) == 0

a: u64 123;
assert(a << 64 == 0); // In C this would be 123 because (64 & 0b111111) == 0
2020-05-31 13:50:17 +01:00
gingerBill 8057af9e09 Fix #659 Compiler error when indexing constant slices 2020-05-31 12:20:47 +01:00
gingerBill d8bc2030e6 Fix big_int_to_f64 2020-05-30 16:45:49 +01:00
gingerBill 5eaef091e2 Update math/bits 2020-05-30 12:24:00 +01:00
gingerBill 84fd40de77 Fix rules for recursive initialization with procedure entities; Fix executable name if not given 2020-05-30 12:23:41 +01:00
gingerBill 1d7f99cbdf Remove mem_zero from make; Implement custom memset for windows amd64 2020-05-27 20:17:58 +01:00
gingerBill 3d4a3730b0 Add notin deprecation 2020-05-27 18:47:45 +01:00
gingerBill 1f31d573e4 Fix tokenization 2020-05-27 18:43:02 +01:00
gingerBill 237962182b Fix tokenizing for %% 2020-05-27 18:41:10 +01:00
gingerBill e84406a895 Move zero_size 2020-05-27 18:26:20 +01:00
gingerBill 1a0614b0d7 Improve performance of tokenization and parsing 2020-05-27 18:23:37 +01:00
gingerBill 876820789e Add rune_is_letter_or_digit for tokenizer 2020-05-27 12:54:11 +01:00
gingerBill 4e21a4d46a Optimize rune_is_* procedures for tokenizer 2020-05-27 12:43:49 +01:00
gingerBill 6ac0fb80a6 Minor tokenizer performance improvements 2020-05-27 12:32:11 +01:00
gingerBill 098699103d Begin work on supporting wasm32 architecture 2020-05-25 12:46:23 +01:00
gingerBill d6bcc25b69 Fix tokenizer for 0i #658 2020-05-24 21:43:36 +01:00
gingerBill a2c50d3666 Fix -vet for strings 2020-05-24 17:57:55 +01:00
gingerBill f06efffe22 Update strings case convertors to be unicode compliant 2020-05-24 17:50:27 +01:00
gingerBill e42f7008fc Change spaces to tabs 2020-05-24 16:40:48 +01:00
gingerBill 26c9d17040 Merge branch 'master' of https://github.com/odin-lang/Odin 2020-05-24 12:52:19 +01:00
gingerBill 2be87169ef Fix #656 2020-05-24 12:52:08 +01:00
Mikkel Hjortshøj 732c745bb3 Merge pull request #655 from ThisDrunkDane/master
Add case conversions by @dotbmp
2020-05-24 12:52:38 +02:00
Mikkel Hjortshoej c035fc337f Add case conversions by @dotbmp 2020-05-24 12:47:43 +02:00
gingerBill cbfbff7240 Add intrinsics.type_is_comparable; Add sort.linear_search 2020-05-23 14:02:21 +01:00
gingerBill 99e6eba20f Revert demo.odin 2020-05-23 13:57:45 +01:00
gingerBill 7d11ee605c Add sort.binary_search (uses interpolation sort for ordered numeric types) 2020-05-23 13:57:24 +01:00
gingerBill 4671207c61 Make the using import deprecation warning an error 2020-05-23 13:39:18 +01:00
gingerBill aa029fe8d9 Add "pure" procedure types 2020-05-23 13:38:06 +01:00
gingerBill ef539696b9 Strip carriage return \r from raw string literals 2020-05-23 11:39:29 +01:00
gingerBill 26fe9b0212 Fix SelectorCallExpr with no return values 2020-05-22 23:41:17 +01:00
gingerBill fd6e2ed5de Revert demo.odin 2020-05-22 14:56:32 +01:00
gingerBill 7bd1039a49 Selector Call Expressions: x->y(123) == x.y(x, 123) 2020-05-22 14:54:30 +01:00
gingerBill 76a230372f Merge branch 'master' of https://github.com/odin-lang/Odin 2020-05-22 12:32:36 +01:00
gingerBill 86b613fb15 Remove the need for type_of, size_of, align_of, offset_of to be keywords 2020-05-22 12:32:29 +01:00
gingerBill aacf524a47 Merge pull request #653 from lkppo/master
Fix the shebang portability of the build.sh script
2020-05-22 10:35:49 +01:00
Stéphane Aulery 8ad3a1f41f Fix the shebang portability of the build.sh script 2020-05-22 11:28:17 +02:00
gingerBill d09ac8943a Minor fixes to improve hash map/set performance 2020-05-21 16:27:40 +01:00
gingerBill 8e63c94393 Add string.h 2020-05-21 11:10:03 +01:00
gingerBill 0b16ed7c85 Use memcmp for str_eq 2020-05-21 11:05:38 +01:00
gingerBill 89d824216a Add extra information to -show-more-timings 2020-05-21 09:30:15 +01:00
gingerBill 3f23a0b3b0 Fix edge cases of relative pointers 2020-05-17 15:23:27 +01:00
gingerBill 7819fec0a1 Merge pull request #645 from Tetralux/llvm-noabc-obey-directive
LLVM C backend: Obey directives on blocks, procedures, and expressions
2020-05-16 18:15:25 +01:00
Tetralux 96ed948590 LLVM C backend: Obey directives on blocks, procedures, and expressions
e.g: #no_bounds_check / #bounds_check
2020-05-16 17:04:16 +00:00
gingerBill 3bd01d3a02 Merge pull request #644 from Tetralux/llvm-bounds-checks
Add bounds checks to LLVM C backend
2020-05-16 15:32:15 +01:00
Tetralux c4b492fb64 Add bounds checks to LLVM C backend 2020-05-16 14:25:36 +00:00
gingerBill e1bdaa981a Relative pointer and relative slices 2020-05-15 18:45:24 +01:00
gingerBill 95e8668b77 Relative pointers in old backend 2020-05-15 17:52:09 +01:00
gingerBill 90adf214d7 Merge branch 'master' of https://github.com/odin-lang/Odin 2020-05-15 17:37:14 +01:00
gingerBill ff92eb9112 Relative pointers 2020-05-15 17:37:00 +01:00
gingerBill 5f08c77d8b Merge pull request #641 from Tetralux/fix-container-arraypushelems
Fix container.Array.array_push_back_elems
2020-05-15 08:49:26 +01:00
Tetralux dc236d6830 Fix container.Array.array_push_back_elems
We were previously using array_slice to get the storage
that we were copying the new elements into, using the current
length as the offset: `copy(data[len:], ..elems)`

However, array_slice returns a slice over `data[0:len]` -- we
were using it as if it was `data[0:cap]`.

Add array_cap_slice that does this instead. :^)
2020-05-15 03:54:32 +00:00
gingerBill 8b066b2456 Fix runtime.memset issue 2020-05-14 17:56:24 +01:00
gingerBill 218c1599b1 Add explicit context to thread_unix.odin 2020-05-14 13:48:03 +01:00
gingerBill 9b2eecb3df Merge branch 'master' of https://github.com/odin-lang/Odin 2020-05-14 13:44:34 +01:00
gingerBill e0a242e9a1 Enforce explicit context definition for procedure calls 2020-05-14 13:44:28 +01:00
Mikkel Hjortshoej 48946fe46f Alright, things work. Reverting broken stuff 2020-05-14 14:20:04 +02:00
Mikkel Hjortshoej 0b0e661b62 Another test sorry 2020-05-14 14:18:20 +02:00
Mikkel Hjortshoej 10c3acf37f Remove test for webhook 2020-05-14 14:09:22 +02:00
Mikkel Hjortshoej e377f5a329 Briefly break master to test webhook 2020-05-14 14:07:33 +02:00
gingerBill cd4403be0c Fix Assertion failure in ir_print_exact_value #620 2020-05-14 00:34:27 +01:00
gingerBill f661d34049 Implement Explicit context creation #639 2020-05-14 00:13:26 +01:00
gingerBill af1d4d6e72 Implement Allow .? operator to unwrap any union #549 2020-05-14 00:00:10 +01:00
gingerBill f6c7a0c9b8 Fix -llvm-api memset "bug" 2020-05-13 23:51:51 +01:00
gingerBill c2bfb221f5 Fix #561 where statements that eval to false do not show incorrect usage location 2020-05-13 23:45:55 +01:00
gingerBill d59fced21b #591 Improve type switch statement error for fallthrough 2020-05-13 23:33:03 +01:00
gingerBill 7c42d4ba75 (#594) Add #config to replace #defined; Restrict #defined within procedure bodies to remove race condition 2020-05-13 23:29:06 +01:00
gingerBill 14ce6d8ed8 Fix #632 behaviour 2020-05-13 23:09:38 +01:00
gingerBill 2630e9ced1 Fix #622 on both backends 2020-05-13 23:00:34 +01:00
gingerBill 482c687462 Fix procedure references in global compound literals in old backend 2020-05-13 22:42:15 +01:00
gingerBill de8c1165c2 Fix procedure literal declarations at file scope with -llvm-api 2020-05-13 22:30:38 +01:00
gingerBill d51b98a8d2 Add extra 128 bit integer procedures 2020-05-13 13:46:32 +01:00
gingerBill 6861ff47bc Replace entity_of_ident with entity_of_node 2020-05-12 16:28:22 +01:00
gingerBill 0ba3b5c0bd Fix bug for array-like compounds for LLVM-API 2020-05-12 14:57:37 +01:00
gingerBill fcdfcfce19 Let -vet ignore intentional declaration shadowing #637 2020-05-12 10:31:49 +01:00
gingerBill d49ecd9009 Merge pull request #638 from jharler/master
Fixed thread_pool not destroying threads
2020-05-11 17:38:05 +01:00
jharler 72a5030f3d Fixed thread_pool not destroying threads 2020-05-11 12:32:35 -04:00
gingerBill 197a72adde Merge pull request #616 from Tetralux/fix-sync-badopt
Fix potential bad optimization bug in sync.Ticket_Mutex
2020-05-10 10:37:11 +01:00
gingerBill f043e92650 Add strconv.unquote_string and strconv.unquote_char 2020-05-09 13:58:45 +01:00
gingerBill e3f3e715e2 Merge pull request #634 from Tetralux/enum_from_name
Add reflect.enum_from_name
2020-05-09 12:57:27 +01:00
gingerBill e8f2fb58d9 Fix strconv.parse_ usage across other packages 2020-05-09 11:54:36 +01:00
Tetralux 8d2430e54d Add reflect.enum_from_name
Provides a way to go from a enum value name string to an actual enum value.

```
E :: enum { A, B }

// ...

s := "B";
v, ok := enum_from_name(E, s);
assert(ok && v == E.B);
```
2020-05-09 07:30:07 +00:00
gingerBill dc1b3cc563 Merge branch 'master' of https://github.com/odin-lang/Odin 2020-05-08 16:09:45 +01:00
gingerBill d52695b077 Fix constant complex arithmetic bug 2020-05-08 16:09:35 +01:00
gingerBill 6adbdb1e0e Merge pull request #633 from Tetralux/fix-parseint-again
Fix parsing of single-digit numbers
2020-05-07 00:35:26 +01:00
Tetralux 7d4f9545a7 Fix parsing of single-digit numbers 2020-05-06 23:21:24 +00:00
gingerBill 4fc60601d3 Fix ABI typo 2020-05-06 20:18:43 +01:00
gingerBill 4f4c3bb03b Add -extra-linker-flags:<string> 2020-05-06 13:41:22 +01:00
gingerBill 8434cb8951 Merge pull request #630 from Tetralux/parseint
Refactor parsing procedures: Return (value, ok) instead
2020-05-05 21:05:13 +01:00
gingerBill 99ebb5af3b Support --flag as redundancy for -flag 2020-05-04 18:23:23 +01:00
gingerBill 45274868c3 Fix -subsystem:windows for normal backend 2020-05-04 18:07:49 +01:00
gingerBill 3ef9566817 Fix typo 2020-05-03 16:18:47 +01:00
gingerBill 3299d6a204 Add -ignore-vs-search 2020-05-02 18:50:38 +01:00
gingerBill e27f5796d6 Add experimental atom op tables for llvm-backend 2020-05-02 18:45:57 +01:00
gingerBill ba4363d678 Improve append_elem(s) logic 2020-05-02 12:09:25 +01:00
gingerBill eb2b3572bb Move TypeProc outside 2020-05-02 11:59:43 +01:00
gingerBill 1a9e75267b Fix rc.exe call 2020-05-02 10:00:34 +01:00
gingerBill dd0fb744fe Add missing ; 2020-04-30 19:26:31 +01:00
gingerBill 70a66cd559 Add -subsystem to odin build -help 2020-04-30 17:57:21 +01:00
gingerBill 832a586b8d Merge branch 'master' of https://github.com/odin-lang/Odin 2020-04-30 17:48:46 +01:00
gingerBill 117ade0700 Fix errors in package win32 2020-04-30 17:48:35 +01:00
Tetralux 25f77e32ee Fix doc comments 2020-04-29 23:35:26 +01:00
Tetralux 704ee9f851 Return (value: T, ok: bool) instead 2020-04-29 22:37:33 +01:00
Tetralux 190932935c Refactor parse_* procedures: arbitrary bases, and return (value, rest_of_string) 2020-04-29 21:33:33 +01:00
gingerBill a10d180d81 Merge pull request #627 from zhibog/master
Added #maybe to the builtin parser and ast for Unions
2020-04-25 17:49:06 +01:00
zhibog c704de8442 Added the #maybe directive to the union struct in the AST. Also added it to the parsing code for a union. 2020-04-25 18:21:32 +02:00
gingerBill f63b9806d2 LLVM API: Fix compound literals with constant parameters to union fields 2020-04-25 14:45:34 +01:00
gingerBill 9409f53a9b Merge branch 'master' of https://github.com/odin-lang/Odin 2020-04-24 20:42:57 +01:00
gingerBill 9faf292218 Fix @(export) for global variable declarations 2020-04-24 20:42:47 +01:00
Mikkel Hjortshøj 92f5f86193 Remove push: on nightly 2020-04-23 22:38:54 +02:00
Mikkel Hjortshøj 1e711fa5a5 Merge pull request #625 from ThisDrunkDane/nightly-build
Improve nightly builds
2020-04-23 22:38:22 +02:00
Mikkel Hjortshoej 51b346753a Github actions apparently doesn't support YAML comments 2020-04-23 22:30:44 +02:00
Mikkel Hjortshoej b63aa0520a Remove the LLVM-C.lib from nightlies and include LLVM-C.dll 2020-04-23 22:30:07 +02:00
Mikkel Hjortshoej 04e106e06a Test push 2020-04-23 22:17:49 +02:00
Mikkel Hjortshoej 5d42a6de6e Remove llvm-binaries.zip from artifacts 2020-04-23 22:17:27 +02:00
Mikkel Hjortshoej bb3e0fa03f Add sizeInBytes of zip files to nightly.json generation 2020-04-23 22:16:31 +02:00
Tetralux e7e936f480 Merge branch 'master' into fix-sync-badopt 2020-04-22 06:12:41 +01:00
gingerBill 026bb8ed6f Remove unused headers 2020-04-21 23:26:59 +01:00
gingerBill cbc3800797 Merge branch 'master' of https://github.com/odin-lang/Odin 2020-04-21 23:26:09 +01:00
gingerBill 4236e870d7 Fix type assertion bug #619 2020-04-21 23:26:02 +01:00
gingerBill b725ae5ae0 Merge pull request #617 from Tetralux/dep-yield-processor
Rename `yield_processor` to `cpu_relax`
2020-04-21 18:07:04 +01:00
Tetralux 3afa2736b7 Fix potential bad optimization bug in sync.Ticket_Mutex
When locking, we were not loading m.serving atomically and so the optimizer
could have hoisted the check out of the loop, thus resulting in an infinite loop.
2020-04-21 17:04:29 +00:00
Tetralux 8dd1b61aa2 sync.yield_processor -> sync.cpu_relax; have it call intrinsics.cpu_relax 2020-04-21 16:07:18 +00:00
gingerBill f5a1d8f2b5 Merge pull request #614 from Tetralux/patch-1
Remove outdated comment
2020-04-21 15:35:24 +01:00
Tetralux d3f2f94800 Remove outdated comment
This is what I get for removing the ability to provide a stack at the last minute.... 🤣
2020-04-21 15:22:42 +01:00
gingerBill f141e2868d container.Set 2020-04-20 00:12:01 +01:00
gingerBill 400d6014d0 container.Small_Array 2020-04-19 23:57:57 +01:00
gingerBill ab6947b2c7 container.Small_Array 2020-04-19 23:57:40 +01:00
gingerBill 52bbdefec4 container.Map 2020-04-19 23:43:02 +01:00
gingerBill 8ee67e41f4 Fix #optional_ok; Fix container.Array 2020-04-19 23:08:50 +01:00
gingerBill 0af2b38225 Merge branch 'master' of https://github.com/odin-lang/Odin 2020-04-19 21:45:14 +01:00
gingerBill 97f7a558fa #optional_ok tag for procedures 2020-04-19 21:45:04 +01:00
Mikkel Hjortshøj ab7c75860e Merge pull request #607 from ThisDrunkDane/nightly-build
Use b2 upload-file instead of b2 sync for nightly builds
2020-04-19 21:54:17 +02:00
Mikkel Hjortshoej 680d723c77 Remove push 2020-04-19 21:44:45 +02:00
Mikkel Hjortshoej 8eda24f2d1 Actually include script to delete binaries 2020-04-19 21:38:59 +02:00
Mikkel Hjortshoej 3dac1c34fa Script to delete files older than x days 2020-04-19 21:34:04 +02:00
Mikkel Hjortshoej 7fddac2c36 Fix typo in nightly.yml 2020-04-19 18:06:20 +02:00
Mikkel Hjortshoej a55975bd5a Testing 2020-04-19 18:00:54 +02:00
gingerBill 2c91c21021 Merge pull request #610 from zhibog/master
Add bool flag to AST data in the parser in the core library
2020-04-18 20:43:21 +01:00
zhibog 3a1bee19a9 Added a bool flag to the Block_Stmt struct to have information whether or not 'do' was used vs brackets in the AST 2020-04-18 21:34:14 +02:00
gingerBill 872e97dba6 Merge pull request #609 from hasenj/osx-consts
Fix darwin open flags and mode
2020-04-18 19:20:42 +01:00
Hasen Judy 705984f828 Fix darwin open flags and mode 2020-04-19 01:39:22 +09:00
gingerBill aa620e8ea1 Fix Procedure value printing in ir.cpp 2020-04-17 16:20:50 +01:00
gingerBill 1addee32b5 package container with Queue and Array 2020-04-17 15:26:50 +01:00
gingerBill 92402603b9 Change find_or_generator_context_ptr behaviours 2020-04-17 14:02:45 +01:00
gingerBill 4438b3e7af Fix LLVM API backend for procedure "constant" values 2020-04-17 13:50:28 +01:00
gingerBill 602a651613 Fix name mangling for @(private) entities 2020-04-15 21:58:16 +01:00
Mikkel Hjortshoej d0cee15317 Remove on:push in nightly.yml 2020-04-15 20:44:47 +02:00
Mikkel Hjortshoej df5626cc1f Pass the bucket to /ci/create_nightly_json.py 2020-04-15 20:13:44 +02:00
Mikkel Hjortshoej 2dcc986c4c Update /ci/build_ci.bat 2020-04-15 20:11:00 +02:00
Mikkel Hjortshoej 550df8711f Fix typo in upload-create-nightly.sh 2020-04-15 20:04:43 +02:00
gingerBill 1e321cd48c Fix reflect.capacity and reflect.index 2020-04-15 19:00:05 +01:00
Mikkel Hjortshoej 020856d91a Fix macos artifact typo 2020-04-15 19:59:00 +02:00
Mikkel Hjortshoej 1bd0e09ae1 Upload to nightly path and echo out some info 2020-04-15 19:58:11 +02:00
gingerBill dbaf8568d6 Fix reflect.length 2020-04-15 18:56:19 +01:00
Mikkel Hjortshoej 802a776330 Use the correct path during upload 2020-04-15 19:49:37 +02:00
Mikkel Hjortshoej 9170c875e1 chmod +x the script before execution 2020-04-15 19:44:26 +02:00
Mikkel Hjortshoej 5002b71670 use b2 upload-file instead of b2 sync 2020-04-15 19:38:50 +02:00
gingerBill f229084baa Basic polymorphic named procedure parameters for procedures and records 2020-04-13 15:48:56 +01:00
gingerBill f09b6a4c90 Simplify compiler's Map and create a StringMap specifically for strings 2020-04-13 13:02:30 +01:00
gingerBill 65a2125dba Add -build-mode=obj 2020-04-13 12:00:40 +01:00
gingerBill 9e698b720f Change behaviour for zero-sized value types of array-related types; Fix make behaviour to always zero memory 2020-04-12 10:41:44 +01:00
gingerBill 5157619eb7 Support endian specific float on -llvm-api; fix unary - for endian floats 2020-04-11 21:51:43 +01:00
gingerBill 90593fe6ae Endian specific floating point types (e.g. f32be) 2020-04-11 21:34:55 +01:00
Mikkel Hjortshøj 16b4178b8a Merge pull request #606 from ThisDrunkDane/nightly-build
CI for nightly builds
2020-04-11 21:52:45 +02:00
Mikkel Hjortshoej 8f2b848698 Make the json for nightly have friendly URLs 2020-04-11 21:48:44 +02:00
Mikkel Hjortshøj 9655b61c11 Setup nightly.yml to run everyday at 20:00 UTC 2020-04-11 21:47:35 +02:00
Mikkel Hjortshoej 9b9a4fcf22 Python script for creating json 2020-04-11 21:01:41 +02:00
gingerBill a736d0e83f Fix @force on non-windows platforms 2020-04-11 19:40:01 +01:00
gingerBill 7ba339e6bd Fix link_name for variables 2020-04-11 19:34:29 +01:00
gingerBill baf5b9edc3 Add runtime.bswap_* required for -llvm-api 2020-04-11 19:26:16 +01:00
Mikkel Hjortshoej a615402d7c Start on json script 2020-04-11 19:55:20 +02:00
Mikkel Hjortshøj c9bec10a8e Setup POC nightly.yml 2020-04-11 19:41:25 +02:00
Mikkel Hjortshøj df80e8752b Update nightly.yml 2020-04-11 17:36:30 +02:00
Mikkel Hjortshøj 2df0532b17 Create nightly.yml 2020-04-11 17:32:21 +02:00
gingerBill 62dc99dbef Begin to make the -llvm-api more general 2020-04-10 19:52:17 +01:00
gingerBill b925ad5927 Update README.md 2020-04-10 10:27:36 +01:00
gingerBill 090579d6b5 Update README.md 2020-04-10 10:27:15 +01:00
gingerBill 29a3cb25d3 Add extra guards for window-only performance checking 2020-04-07 11:47:28 +01:00
gingerBill 7ff690500a Fix psapi.h to be windows only 2020-04-07 11:41:55 +01:00
gingerBill d0b913dad1 Add extra internal memory analysis 2020-04-06 12:17:54 +01:00
gingerBill d659e679fd Fix defer after return for -llvm-api 2020-04-06 12:17:27 +01:00
gingerBill ae97c1111a Fix -llvm-api for typeid comparison with a Type itself 2020-04-06 11:38:53 +01:00
gingerBill f38d7b02f3 Fix phi node check with untyped types 2020-04-05 14:20:26 +01:00
gingerBill 5e706bab56 Fix typeid comparison bug in ir.cpp 2020-04-04 21:23:11 +01:00
gingerBill b362ce9a22 Fix selector expressions for map[unknown-key] expressions for -llvm-api 2020-04-04 20:56:56 +01:00
gingerBill 9961ad8e48 Merge branch 'master' of https://github.com/odin-lang/Odin 2020-04-04 19:46:00 +01:00
gingerBill b54b5aabac Fix crash on aliasing compiler-only packages (e.g. intrinsics) with _ at the global scope. 2020-04-04 19:45:54 +01:00
Mikkel Hjortshøj d214c45fe5 Merge pull request #603 from joesycalik/win32-updates
Added to core:sys win32 package
2020-04-04 15:51:34 +02:00
gingerBill 3f638f92e2 Fix -vet warning in core.odin for intrinsics not being used 2020-04-04 13:48:53 +01:00
gingerBill b0d668d254 Fix math.atan 2020-04-04 13:02:39 +01:00
gingerBill 488282409f Fix shadowing for -vet 2020-03-30 15:22:42 +01:00
gingerBill d3c2191cf7 Fix formatting 2020-03-30 12:38:09 +01:00
vassvik dd13cf637e Fix linalg.euler_angles_from_quaternion 2020-03-30 13:29:01 +02:00
gingerBill 0804be5d81 Merge branch 'master' of https://github.com/odin-lang/Odin 2020-03-30 12:21:51 +01:00
gingerBill 3c189d2cf6 Add basic support for Python-style {} printf formatting 2020-03-30 12:21:44 +01:00
Joe c83592629d Fixed duplicated WHITENESS value in BLACKNESS constant 2020-03-29 18:10:10 -04:00
Joe 2e3706e447 -Win32-
New
- Constants: WHITENESS & BLACKNESS, and WM_PAINT
- Methods: pat_blt, register_class_a, register_class_w, message_box_a, message_box_w, begin_paint, and end_paint
- Structs: Wnd_Class_A, Wnd_Class_W, Paint_Struct
Modified
- WM_INPUT : Capitalized alphabetical values for consistency with other values
2020-03-29 17:06:09 -04:00
gingerBill 1524852ffc Merge pull request #600 from kevinw/master
Add a missing space after /LIBPATH linker options.
2020-03-29 14:32:42 +01:00
Kevin Watters 957e6f7f08 Add a missing space after /LIBPATH linker options. 2020-03-28 21:05:32 -04:00
gingerBill 1b3ee7153c Fix #599 - llvm-api GEP for structs with custom alignment 2020-03-28 16:08:14 +00:00
gingerBill bda5e8cc66 Merge branch 'master' of https://github.com/odin-lang/Odin 2020-03-28 15:42:53 +00:00
gingerBill 6d6f8f8da9 LLVM API fixes: for in ^map; complex/quaternion negation 2020-03-28 15:42:46 +00:00
Mikkel Hjortshøj dca6c451da Merge pull request #598 from ThisDrunkDane/master
Switch from now removed context.stdout/stderr to os.stdout/stderr
2020-03-28 14:14:20 +01:00
Mikkel Hjortshoej a6c8dcdd21 Switch from now removed context.stdout/stderr to os.stdout/stderr 2020-03-28 14:13:47 +01:00
gingerBill b98a4c6d69 Fix #597 2020-03-27 13:33:31 +00:00
gingerBill 4be385d648 Add more helpers to package reflect 2020-03-27 13:30:22 +00:00
gingerBill 6bbecbe895 Merge pull request #595 from odin-lang/llvm-integration
LLVM C API Integration
2020-03-26 17:41:38 +00:00
gingerBill b21993a1c4 Allow ability to reference compound literals like C99 for -llvm-api 2020-03-26 17:33:54 +00:00
gingerBill dd69fcba07 Merge branch 'master' into llvm-integration 2020-03-26 15:56:55 +00:00
gingerBill 7909872877 Allow referencing a compound literal to act like C99 2020-03-26 15:56:08 +00:00
gingerBill 0a920b5439 Fix map references in selector expressions 2020-03-25 15:55:00 +00:00
gingerBill 921ee82c97 Fix range statements for enumerated arrays without an element value but with an index 2020-03-25 15:11:35 +00:00
gingerBill b7893082ce Allow map indices to be referenced &m[key] and return a valid pointer if it exists otherwise nil 2020-03-24 15:51:17 +00:00
gingerBill 6bfe9b6656 Merge branch 'master' into llvm-integration 2020-03-24 15:48:57 +00:00
gingerBill da703edbf4 Allow map indices to be referenced &m[key] and return a valid pointer if it exists otherwise nil 2020-03-24 15:48:31 +00:00
gingerBill 796331fea6 Support by-reference semantics in for value_ref, i in &some_array and for key, value_ref in &some_map 2020-03-24 15:33:34 +00:00
gingerBill 820095ddac Merge branch 'master' into llvm-integration 2020-03-24 15:29:44 +00:00
gingerBill d57fbf48f0 Support by-reference semantics in for value_ref, index in &some_array and for key, value_ref in &some_map 2020-03-24 15:28:58 +00:00
gingerBill 53c842e9ba Change to new by-reference semantics for switch v in &value 2020-03-24 14:43:28 +00:00
gingerBill 1e375ba8de Merge branch 'master' into llvm-integration 2020-03-24 14:31:09 +00:00
gingerBill 5cbb266ef5 Change behaviour of switch v in &value to make v have by-reference semantics 2020-03-24 14:29:54 +00:00
gingerBill 0730e01b24 Merge branch 'master' into llvm-integration 2020-03-22 20:57:04 +00:00
gingerBill dfc63dcb60 Fix for in for pointer to map expressions 2020-03-22 20:56:46 +00:00
gingerBill 8093062e3b Wrap all LLVM C includes 2020-03-19 15:36:13 +00:00
gingerBill 9524739dfc Revert demo.odin 2020-03-19 15:31:05 +00:00
gingerBill 054e018e23 Remove dead stuff from build.bat 2020-03-19 15:30:10 +00:00
gingerBill 3d81ad46d2 Change demo.odin to default 2020-03-19 15:29:32 +00:00
gingerBill ed4d21045b Add LLVM_BACKEND_SUPPORT macro to make the backend optional 2020-03-19 15:14:31 +00:00
gingerBill 93955a0fd8 Remove context.std* parameters; Fix unary boolean not 2020-03-19 15:03:02 +00:00
gingerBill fc0002ab67 Fix enum type info generation 2020-03-19 12:28:39 +00:00
gingerBill 04fe23a3c8 Have different categories for optimization passes 2020-03-19 10:57:14 +00:00
gingerBill 1707e004ec Merge branch 'llvm-integration' of https://github.com/odin-lang/Odin into llvm-integration 2020-03-15 14:37:46 +00:00
gingerBill 5169dc07c7 Fix lb_add_proc_attribute_at_index 2020-03-15 14:37:39 +00:00
gingerBill 18fb6a4be4 Merge branch 'master' into llvm-integration 2020-03-15 14:31:26 +00:00
gingerBill 8dba0e332c Fix #590 2020-03-15 14:29:45 +00:00
gingerBill 3951b93d0a Fix branch statements within inline for blocks (partial hack) 2020-03-15 14:27:54 +00:00
gingerBill 10bac2445b Fix ir_print for byval types 2020-03-13 16:48:10 +00:00
gingerBill 06e364b9bd Apply byval to sret for System V ABI 2020-03-13 08:52:23 +00:00
gingerBill ce90509a07 Add initial -mem2reg pass to opt 2020-03-13 00:04:03 +00:00
gingerBill a0d0e93475 Fix os.read_entire_file 2020-03-12 23:45:46 +00:00
gingerBill 2ce1f4ba9f Revert os_windows.odin behaviour 2020-03-12 23:37:24 +00:00
gingerBill a985449c31 Fix os_windows.h 2020-03-12 23:24:30 +00:00
gingerBill 6abc93ad84 Fix os.read for windows 2020-03-12 23:22:01 +00:00
gingerBill a9bc07dbff Merge pull request #586 from Tetralux/fix-reading
Fix os.read / os.read_entire_file on Windows
2020-03-12 22:35:12 +00:00
gingerBill da283d5a7f Add byval 2020-03-12 22:33:49 +00:00
Tetralux 1181d7cf90 Fix os.read / os.read_entire_file
- DWORDs are NOT i32
- os.read didn't correctly read as much as it could
2020-03-12 22:31:00 +00:00
gingerBill 2a2d3273ea Add @require for global variables 2020-03-12 14:40:13 +00:00
gingerBill 775e6caf31 Merge pull request #583 from machinamentum/llvm-integration
LLVM: speed improvement changes.
2020-03-09 08:46:27 +00:00
Joshua Huelsman 4468ddf8f8 LLVM: speed improvement changes. 2020-03-09 03:21:08 -04:00
gingerBill bf0c6f5a30 Fixes for constants and nil parameters 2020-03-08 19:38:50 +00:00
gingerBill d1e670335f Fix lb_find_or_add_entity_string_byte_slice 2020-03-08 18:50:10 +00:00
gingerBill c6c6c56ba9 Fix mem.set for LLVM C API 2020-03-08 18:44:45 +00:00
gingerBill d4e95282c2 Fix llvm.memset for both backends 2020-03-08 18:42:30 +00:00
gingerBill 5a02ebe2c8 Fix foreign import dependencies; Fix lbParamPass_Integer ABI 2020-03-08 17:57:46 +00:00
gingerBill dae817e5ab Integrate linker code with the new LLVM API backend 2020-03-08 17:44:08 +00:00
gingerBill 28502ba53b Fix context system; add more to -show-more-timings for LLVM API; Add ODIN_USE_LLVM_API global constant 2020-03-08 12:34:36 +00:00
gingerBill 8dc74a004c Fix nested type declarations name generation, to be internally consistent 2020-03-08 11:46:05 +00:00
gingerBill c584456a21 Fix logical binary expressions 2020-03-08 10:43:00 +00:00
gingerBill c74d8405ec Merge branch 'master' into llvm-integration 2020-03-08 10:13:19 +00:00
gingerBill e0a370f8f1 Remove adding to path in shell.bat 2020-03-08 10:12:56 +00:00
gingerBill 4cf70f360b Add clone for ast.Ternary_If_Expr and ast.Ternary_When_Expr 2020-03-07 21:41:27 +00:00
gingerBill a83d9f59f6 Fix typo in parser.odin 2020-03-07 21:12:52 +00:00
gingerBill 5d14189a18 Merge branch 'master' of https://github.com/odin-lang/Odin 2020-03-07 16:20:04 +00:00
gingerBill fb686bdebd Remove the need for parapoly to print an enum as a string 2020-03-07 16:19:55 +00:00
gingerBill 19b9cb7524 Merge pull request #575 from Tetralux/patch-2
Fix mem.align_backward when pointer is already aligned
2020-03-07 10:46:19 +00:00
gingerBill f92334a769 Basic functionality, except for map and correct nested typename mangling 2020-03-07 10:38:14 +00:00
gingerBill 4ee936ab8d Merge pull request #581 from terickson001/linux_stat_fix
Linux stat fix
2020-03-06 15:42:05 +00:00
gingerBill 0c21939600 Merge pull request #579 from powerc9000/patch-1
Fix issues with stat struct.
2020-03-06 15:41:54 +00:00
Tyler Erickson f6f2ab2f25 Fixed bad merge 2020-03-05 19:29:32 -08:00
Tyler Erickson 9d163fede8 Merge branch 'master' of https://github.com/odin-lang/Odin into linux_stat_fix 2020-03-05 16:52:34 -08:00
Tyler Erickson bb026c99a9 Merged with master 2020-03-05 16:49:53 -08:00
gingerBill 8d2ad0da0e Fill in more of the llvm_backend code generation 2020-03-05 22:01:07 +00:00
gingerBill db7a3ffd2a Merge branch 'master' into llvm-integration 2020-03-05 21:12:16 +00:00
gingerBill c213d72ec6 Fix #580 defer bug 2020-03-05 20:58:59 +00:00
gingerBill 01b1385672 Disable tmp_block behaviour for ir_find_or_generate_context_ptr 2020-03-05 20:36:53 +00:00
gingerBill e92fdb4a99 x if cond else y and x when cond else y expressions 2020-03-05 20:34:30 +00:00
Tyler Erickson 2817bab494 Fix os_linux stat 2020-03-05 12:13:22 -08:00
gingerBill 7d93dd6024 Move module pass to after all function passes 2020-03-05 19:00:23 +00:00
gingerBill e1da631d26 General functionality without context 2020-03-04 22:09:58 +00:00
gingerBill 6151fdb324 Merge branch 'master' into llvm-integration 2020-03-04 19:27:01 +00:00
gingerBill 2fe0eaf2ad Fix formatting 2020-03-04 13:10:39 +00:00
Clay Murray 85f2f4aa88 Fix issues with stat struct.
The stat struct was the format for the 64 bit version of stat. So we need to call stat64 to get the proper data.
Also we need to use _File_Time instead of File_Time because it is a compound value. 

These changes were tested and work on my computer, MacOS 64 bit.
2020-03-03 19:42:20 -07:00
gingerBill 3f63e12198 Add -subsystem:console and -subsystem:windows flags for windows 2020-03-02 18:54:56 +00:00
gingerBill 10cde925ca Add checks for pre-existing type declarations. 2020-03-02 18:48:52 +00:00
gingerBill 56240240f6 Range Statement support 2020-02-29 14:29:47 +00:00
gingerBill f83e1b8b0a Fix any type and casting to any; Fix switch statement 2020-02-29 12:24:52 +00:00
gingerBill a27c68f526 Type_Info initialization 2020-02-29 11:12:37 +00:00
gingerBill 8ec5987ae1 Merge branch 'master' into llvm-integration 2020-02-29 09:55:25 +00:00
gingerBill 408fa027af Merge pull request #576 from Tetralux/patch-5
Fix encoding/base64 encoding null bytes incorrectly
2020-02-29 09:53:55 +00:00
gingerBill 5e903ed2ff Merge pull request #537 from Tetralux/fix-heap-alloc
Fix heap allocator alignment on all platforms
2020-02-29 09:49:24 +00:00
gingerBill ce20604e3c Fix #578 2020-02-29 09:35:41 +00:00
Tetralux 92e1c71dd6 Fix encoding/base64 encoding null bytes incorrectly
Fixes #574.

Thanks @jroatch!
2020-02-28 14:52:16 +00:00
Tetralux 0190f90979 Fix mem.align_backward when pointer is already aligned 2020-02-28 12:22:30 +00:00
gingerBill 3d74c2f6c0 Add proc(#const x: Type) to enforce a constant parameter (but not polymorphic) to a procedure 2020-02-26 22:53:40 +00:00
gingerBill 1596bca92d Add intrinsics.cpu_relax 2020-02-26 22:29:12 +00:00
gingerBill 470508adbc Clean-up initialization code 2020-02-26 22:05:52 +00:00
gingerBill 8f42958ba3 Fix __dynamic_array_reserve 2020-02-26 12:58:22 +00:00
gingerBill 4d7270cec9 Fix __dynamic_array_reserve to allow for zero sized elements 2020-02-26 12:55:56 +00:00
gingerBill b13423d7f7 Global variable initialization support 2020-02-23 16:25:11 +00:00
gingerBill 703404a54d Merge branch 'master' into llvm-integration 2020-02-23 10:55:41 +00:00
gingerBill 15f5c85379 Fix comparison against nil for union #maybe pointers 2020-02-23 10:55:09 +00:00
gingerBill e197af766d Merge branch 'master' into llvm-integration 2020-02-23 10:39:57 +00:00
gingerBill 10fe5e97b3 Merge pull request #541 from Tetralux/getcwd
Add os.get_current_directory / os.set_current_directory
2020-02-23 10:39:21 +00:00
gingerBill 5073fcd39e Improve error message on using with procedure parameters #568 2020-02-23 10:37:27 +00:00
gingerBill a72ac6f841 Fix #572 2020-02-23 10:26:49 +00:00
gingerBill 8a67775149 Fix #571 2020-02-23 10:20:12 +00:00
gingerBill 85e331d5e2 Fix #566 2020-02-23 10:13:42 +00:00
gingerBill 81b00c7a3e Fix #563 2020-02-23 10:11:43 +00:00
gingerBill 49ecd73406 Merge pull request #562 from Tetralux/string-compare
Fix #552: Fix strings.compare for empty strings and different-length strings.
2020-02-23 10:08:50 +00:00
gingerBill 2180f4a475 Basic work on obj generation 2020-02-23 10:04:25 +00:00
Tetralux 1f0c1943da Fix #552.
- Fix comparisons involving one or more empty string.
- Fix comparisons against two strings of different lengths.
2020-02-12 11:25:12 +00:00
Mikkel Hjortshøj 0b7711684b Delete dockerimage.yml
My bad
2020-02-11 21:53:45 +01:00
Mikkel Hjortshøj 9821b2be25 Create dockerimage.yml 2020-02-11 21:52:10 +01:00
Mikkel Hjortshøj 49b42f585c Merge pull request #560 from ThisDrunkDane/master
Enhance logger interface with 'f' and not 'f' variants, also move level detection out
2020-02-10 11:55:49 +01:00
Mikkel Hjortshoej 9d5692ae68 Enhance logger interface with 'f' and not 'f' variants, also move level detection out 2020-02-10 01:26:04 +01:00
gingerBill bfda101686 Get basic IR code generation working properly 2020-02-10 00:14:43 +00:00
vassvik 6d67567453 Fix linalg.matrix_mul_vector.
Incorrect index.
2020-02-09 18:47:02 +01:00
gingerBill 35711a400c Anonymous procedure literal support 2020-02-08 12:49:38 +00:00
gingerBill 66da96284a Add defer statement for LB 2020-02-07 00:01:44 +00:00
gingerBill 7d9600b740 Ternary Expr; lbAddr extra; Phi node support 2020-02-06 23:33:41 +00:00
vassvik 0c09cb9c12 Fix math.acos and math.asin, add f64 overloads. 2020-02-06 13:35:55 +01:00
gingerBill 09e1cf0737 IfStmt 2020-02-05 23:41:10 +00:00
gingerBill 992858b687 Add ReturnStmt 2020-02-05 22:39:23 +00:00
gingerBill b555b0083a Slowly add more statements and expressions; Add header file 2020-02-05 20:18:19 +00:00
Mikkel Hjortshøj 25feb507a4 Merge pull request #556 from oskarnp/issue-555
Fix #555
2020-02-05 21:03:36 +01:00
Oskar Nordquist 0b299cb8b4 Fix https://github.com/odin-lang/Odin/issues/555 2020-02-05 20:48:18 +01:00
gingerBill fbe2366af3 Merge pull request #554 from terickson001/merge-sort-proc
Removed 'where' clause from merge_sort_proc
2020-02-04 18:46:28 +00:00
Tyler Erickson 391e2a5120 Removed 'where' clause from merge_sort_proc 2020-02-03 19:20:12 -08:00
gingerBill 0103cedad7 Port code for lb_build_call_expr 2020-02-02 23:36:15 +00:00
gingerBill d56807095a Implement constant value generation from ExactValue 2020-02-02 18:33:13 +00:00
gingerBill 5dc82c2720 Correctly generate LLVM types from Odin types. 2020-02-02 12:34:49 +00:00
gingerBill 5f1b397a05 Use lbValue to represent values everywhere 2020-02-01 23:52:22 +00:00
gingerBill 6ed6a91a64 Begin LLVM C API integration 2020-02-01 22:50:57 +00:00
gingerBill 0f399a7294 Add union #maybe 2020-02-01 11:10:28 +00:00
gingerBill 4bcb667e97 Merge branch 'master' of https://github.com/odin-lang/Odin 2020-01-31 23:34:08 +00:00
gingerBill 7e6454b2f7 Add odin [command] -help (not requiring a file to be passed) 2020-01-31 23:34:00 +00:00
gingerBill 357e72654d Merge pull request #546 from thebirk/patch-1
Update README.md to use Odin syntax highlighting instead of Go.
2020-01-31 09:46:47 +00:00
Aleksander Birkeland e9f3ebba13 Update README.md to use Odin syntax highlighting instead of Go. 2020-01-30 01:01:01 +01:00
gingerBill 3a30f9fd71 Create .gitattributes 2020-01-29 12:04:54 +00:00
gingerBill 7a4ec48389 Fix missing allocator 2020-01-26 21:10:56 +00:00
gingerBill a101e0d7ba Add utf8.string_to_runes utf8.runes_to_string 2020-01-26 20:55:46 +00:00
gingerBill 64f5c9ab58 Merge branch 'master' of https://github.com/odin-lang/Odin 2020-01-26 20:44:32 +00:00
gingerBill 0ee5a07d01 Add package unicode letter.odin 2020-01-26 20:44:27 +00:00
gingerBill d658a8fca5 Merge pull request #545 from Tetralux/patch-2
Fix `make(map[K]V, 0)` by ensuring `reserve` always sets an allocator
2020-01-26 16:19:50 +00:00
Tetralux abe8789890 Fix make(map[K]V, 0) by ensuring reserve always sets an allocator
Currently, `make(map[K]V, 0)` asserts, because trying `reserve` zero items does not set the allocator; it early-outs.

`__dynamic_map_reserve` assumed that `__dynamic_array_reserve` would always set the allocator - even if given a desired capacity of `0`.

Rather than making `__slice_resize` just _also_ set the default allocator if there isn't one, this makes `__dynamic_array_reserve` always set the allocator, even if it is about to early out.
This is because users are lead to understand that `append` will set the allocator if one is not already set - `reserve` should work the same way.
2020-01-26 01:03:14 +00:00
Tetralux a4b60b78c8 Fix heap allocator alignment on all platforms 2020-01-22 12:03:16 +00:00
Tetralux 66d1656367 Add os.get_current_directory / os.set_current_directory 2020-01-20 14:28:31 +00:00
gingerBill 14c4fed94c v0.12.0 2020-01-18 15:32:15 +00:00
gingerBill c3205316ed Remove debug printing 2020-01-18 14:53:53 +00:00
gingerBill b542ef273d Begin work on -target:windows_386 2020-01-18 14:44:53 +00:00
gingerBill 404132de17 Fix microsoft_craziness.h to work correctly 2020-01-18 12:36:18 +00:00
gingerBill cd43f4c94c Add suggestions for indexing constant values with a variable index 2020-01-18 12:09:26 +00:00
gingerBill 23ff98dea0 Fix microsoft_craziness.h 2020-01-18 12:08:45 +00:00
gingerBill c3a8e232a5 Add new intrinsics for polymorphic records:
type_is_specialized_polymorphic_record, type_is_unspecialized_polymorphic_record, type_polymorphic_record_parameter_count, type_polymorphic_record_parameter_value
2020-01-18 11:27:41 +00:00
gingerBill 7f89f6b582 Add intrinsics.type_is_specialization_of 2020-01-17 23:30:38 +00:00
gingerBill 159150c6d9 Allow not_in as keyword over notin, but still allow notin to work 2020-01-16 10:00:14 +00:00
gingerBill 527b39ce2b Merge remote-tracking branch 'origin/master' 2020-01-16 09:07:52 +00:00
gingerBill 5af3c7b0e8 Fix constant slice checking, again 2020-01-16 09:05:17 +00:00
gingerBill 5db4bd9944 Fix #536 2020-01-15 12:01:29 +00:00
gingerBill 20b410f149 Fix #540 2020-01-15 11:56:42 +00:00
gingerBill ae7cbd5171 Add debug info for enumerated arrays 2020-01-14 17:37:45 +00:00
gingerBill 04f7225ea5 Exact value zero value for T{} of basic types 2020-01-14 17:36:37 +00:00
gingerBill f0c6f29f82 Merge branch 'master' of https://github.com/odin-lang/Odin 2020-01-12 13:53:57 +00:00
gingerBill 7d9a9a2283 Add extra check for opaque types 2020-01-12 13:53:51 +00:00
gingerBill ba85e432e7 Fix Proc Type ABI printing on System V 2020-01-12 13:43:45 +00:00
gingerBill cfba29002a Add extra set_procedure_abi_types sanity checks in IR 2020-01-11 20:29:46 +00:00
gingerBill 11c7b6a2e4 Fix len of type bug 2020-01-11 20:26:36 +00:00
gingerBill 47f9876b36 Merge branch 'master' of https://github.com/odin-lang/Odin 2020-01-11 20:20:20 +00:00
gingerBill ff31f9a900 Fix @thread_local IR printing 2020-01-11 20:19:52 +00:00
gingerBill ebc4867514 Fix #521 Explicit union tag values 2020-01-11 20:16:42 +00:00
gingerBill e1ccba3de5 Improve runtime/default_allocators.odin 2020-01-11 20:12:50 +00:00
gingerBill 28570f8fa4 Merge branch 'master' of https://github.com/odin-lang/Odin 2020-01-11 20:11:47 +00:00
gingerBill 24bd370e1b Fix Panic with runtime.type_info_base #532 2020-01-11 20:11:39 +00:00
Mikkel Hjortshøj 3e67ae7339 Merge pull request #534 from ThisDrunkDane/fix-log-mistake
Fix mistake in .Short_File_Path option in file_console_logger.odin
2020-01-09 19:19:23 +01:00
Mikkel Hjortshoej 0e52c37865 Don't change delimiter as location has changed to be unified no matter the platform 2020-01-08 21:29:46 +01:00
gingerBill d520b9a1ba Fix typo 2020-01-05 12:49:32 +00:00
gingerBill 5c7d6fcfd0 Improve minimum dependency for complex numbers and quaternion numbers. 2020-01-04 18:04:12 +00:00
gingerBill 5ae924f988 Make "none" calling convention ignore return_by_pointer flag 2020-01-04 12:42:16 +00:00
gingerBill cae1e02593 Add extra in set_procedure_abi_types ir_print.cpp 2020-01-04 12:10:28 +00:00
gingerBill b09297da81 Remove -Wno-writable-strings 2020-01-04 10:59:12 +00:00
gingerBill 9abdfaaf6c Merge pull request #531 from Tetralux/fix-make-and-reserve
Fix make and reserve
2020-01-03 10:51:42 +00:00
Tetralux b32ef9e47b Fix make and reserve
- Set the allocator, even if memory allocation fails.
  Right now it doesn't, which means that if allocation fails, it'll use
  the context allocator instead. This memory will be leaked if the user
  doesn't understand that this happened.

- Only set len and cap of the array returned from make iif the memory allocation
  succeeded.
  This means that reserve will return false if you do this:
  ```
  a := make([dynamic]int, failing_allocator);
  if !reserve(&a, 5) do return; // or whatever indicates failure
  ```
2020-01-03 10:40:45 +00:00
gingerBill b8324b0776 Fix behaviour for make to return nil when alloc returns nil 2020-01-03 10:17:30 +00:00
gingerBill d0ca045586 Merge pull request #530 from KTRosenberg/unix_yield_sem_fix
Fixes for yielding and semaphore posting on unix
2020-01-03 09:50:12 +00:00
KTRosenberg 673879d1d2 added note about pthread_yield 2020-01-02 16:44:30 -05:00
KTRosenberg 5d1c9583cb added the demo to the gitignore 2020-01-02 16:42:34 -05:00
KTRosenberg d017b5de9d replaced pthread_yield with ssched_yield, fixed semaphore post:q 2020-01-02 16:25:48 -05:00
gingerBill 93ead4bcb3 Fix typo 2020-01-02 15:41:32 +00:00
gingerBill bbe9b4dee0 Merge branch 'master' of https://github.com/odin-lang/Odin 2020-01-02 15:07:58 +00:00
gingerBill 3bd00fd6b7 Add thread.Pool with example in demo.odin; Update linalg to support handness changes for projection matrices 2020-01-02 15:07:12 +00:00
gingerBill 83fec387d4 Merge pull request #529 from Tetralux/patch-1
Fix `append_string`
2020-01-02 11:39:20 +00:00
Tetralux f6f10d10e8 Fix append_string 2020-01-02 11:38:25 +00:00
gingerBill 16a7c55334 Add x y z w fields to quaternion types; Improve linalg quaternion mathematics 2020-01-01 16:14:00 +00:00
gingerBill e9e2ab240d Merge pull request #528 from oskarnp/foreign-dylib-fix
Fix dylib foreign import
2020-01-01 10:42:09 +00:00
oskarn 842281ddd3 Fix dylib foreign import 2020-01-01 11:36:42 +01:00
gingerBill 978d7fcb99 Fix typeid information for enumerated arrays 2019-12-31 16:54:50 +00:00
gingerBill b267a5964d Fix memset for unix 2019-12-31 14:28:01 +00:00
gingerBill b288613307 Add extra check for ZeroInit instruction 2019-12-31 14:21:16 +00:00
gingerBill 4591353724 Use naive definition of memset for !windows 2019-12-31 14:17:21 +00:00
gingerBill 13107628f8 Make mem.set use llvm.memset.p0i8.iXX 2019-12-31 14:09:51 +00:00
gingerBill c407687a4c Fix new changes to runtime for unix 2019-12-31 14:04:19 +00:00
gingerBill 5a50ab7a99 Add new runtime files. 2019-12-31 13:54:42 +00:00
gingerBill 4578544007 Merge pull request #526 from sci4me/unix-dynlib
Implement dynlib core library for unix/darwin
2019-12-31 13:22:48 +00:00
gingerBill bdfef08214 Fix typos in demo.odin 2019-12-31 12:54:19 +00:00
gingerBill 42678848b2 Rename math/bits package name to math_bits 2019-12-31 12:27:31 +00:00
gingerBill ab52f8d795 Move definition of mem.Allocator and log.Logger to package runtime, to reduce import cycle magic 2019-12-31 12:15:19 +00:00
Scitoshi Nakayobro d79ee7d530 Implement dynlib core library for unix/darwin; not 100% about the build tags 2019-12-30 19:09:59 -05:00
gingerBill 7e271310ff Fix constant out of bounds bug 2019-12-29 22:53:37 +00:00
gingerBill f24de51c65 Add _tls_index and _fltused for windows -no-crt 2019-12-29 21:28:50 +00:00
gingerBill 2252d992d7 Add -disable-assert to disable the code generation of the built-in run-time 'assert' procedure 2019-12-29 21:10:27 +00:00
gingerBill 2d70a784d1 Add quaternion_look_at orientation procedure to package math/linalg 2019-12-29 20:35:27 +00:00
gingerBill a8a4dc1eb1 Make default context.temp_allocator thread safe when using package thread 2019-12-29 18:08:48 +00:00
gingerBill 9e9e905431 Add @(private="file") and @(private="package") 2019-12-29 15:39:20 +00:00
gingerBill 8ee41c20af Add more to package math 2019-12-28 23:48:15 +00:00
gingerBill 11c705508d Split linalg into general and specific parts 2019-12-28 23:09:43 +00:00
gingerBill 267ae0b4a2 Disallow enumerated array literals without field = value 2019-12-28 23:07:54 +00:00
gingerBill 1bc6e6a7cc Add linalg.vector_lerp, linalg.vector_unlerp 2019-12-28 23:07:31 +00:00
gingerBill 33a458c520 Update package math/linalg 2019-12-28 23:00:13 +00:00
gingerBill 6a7ccd8c0a Add new procedures for package math: atan2, asin, acos, atan, sin_bit, ldexp 2019-12-28 18:12:27 +00:00
gingerBill 9ba2926e7e Fix enumerated array contiguous error 2019-12-28 16:31:15 +00:00
gingerBill a50b2d5d04 Fix enumerated array literal check 2019-12-28 14:05:55 +00:00
gingerBill 7f9626e5c7 Improve 'cannot slice' error message 2019-12-27 17:53:05 +00:00
gingerBill 7140c95c55 Fix slicing of pointer to array 2019-12-27 17:47:55 +00:00
gingerBill ceef5db547 Support for and inline for for enumerated arrays 2019-12-27 17:16:43 +00:00
gingerBill 5ec8dd166a Add #partial tag for enumerated arrays to prevent common errors using non-contiguous enumerations 2019-12-27 16:55:32 +00:00
gingerBill 80a32a8182 Fix missing case 2019-12-27 16:01:58 +00:00
gingerBill c2b3056094 Fix enumerated array compound literals IR 2019-12-27 15:53:35 +00:00
gingerBill f99f351e01 Add constant literal expressions 2019-12-27 15:49:52 +00:00
gingerBill 880c7f01a8 Fix array lengths with enum value counts. 2019-12-27 13:55:18 +00:00
gingerBill 10f0961184 Enumerated arrays [Enum_Type]Elem_Type 2019-12-27 12:51:02 +00:00
gingerBill eea403d0ab Fix #514 2019-12-27 10:18:32 +00:00
gingerBill 2cc5c4eed3 Fix https://github.com/odin-lang/Odin/issues/522 2019-12-27 10:11:13 +00:00
gingerBill f308d8d73e Merge pull request #520 from SrMordred/memcpy
minor details ;)
2019-12-26 12:09:44 +00:00
Patric Dexheimer ff0bc3ccad minor details ;) 2019-12-24 11:50:26 -03:00
gingerBill 072979c6d2 Merge pull request #519 from Tetralux/remove-prints
remove errorneous prints
2019-12-24 12:54:00 +00:00
Tetralux a3d2c40da0 whoops 2019-12-24 12:51:27 +00:00
gingerBill 5b1312342e Fix runtime.mem_copy_non_overlapping to be like C's memcpy 2019-12-24 08:07:43 +00:00
gingerBill 85e31e1b69 Fix os.open 2019-12-23 18:10:09 +00:00
gingerBill fb0fb4767b Merge pull request #517 from SSStormy/fix-os-linux-fs-stuffs
Unix: Fix improper _unix_open binding; make write_entire_file set sane file permissions.
2019-12-23 18:07:59 +00:00
Justas Dabrila 38a9a2b7fc Linux: write_entire_file sets 644 permissions on open. 2019-12-23 16:35:10 +02:00
Justas Dabrila 005c6af302 Fix improper _unix_open binding that was ignoring the mode arg 2019-12-23 16:34:20 +02:00
gingerBill 1d14b3059e Fix Internal Compiler Error: Type_Info for 'XXX' could not be found #507 2019-12-22 14:16:56 +00:00
gingerBill cc2fa8f756 Fix thread/thread_unix.odin to use the new switch conventions 2019-12-22 12:11:54 +00:00
gingerBill d1c9fd4e01 Implement #complete switch by default, replace with #partial switch #511 2019-12-22 12:03:48 +00:00
gingerBill 4593730632 Fix Trying to get a pointer to a struct field that does not have a size generates an LLVM error #509 2019-12-22 11:40:30 +00:00
gingerBill f62a0891bd Fix Crash when compiling for loop with parens around array expression #506 2019-12-22 11:33:33 +00:00
gingerBill 4f2d4716ad Fix Internal error when accessing polymorphic struct parameters (also provide suggestions?) #513 2019-12-22 10:40:34 +00:00
gingerBill 022b793a7d Merge branch 'master' of https://github.com/odin-lang/Odin 2019-12-22 10:28:55 +00:00
gingerBill 7267004a55 Remove import "core:runtime" in integers.odin to make -vet happy 2019-12-22 10:28:48 +00:00
vassvik 786c9dfe07 Add the ability to toggle release mode externally when calling build.bat
The following cases builds Odin with optimizations:

    build.bat 1
    build.bat release

Any other options, or the lack thereof, will build without optimizations.
2019-12-22 11:19:42 +01:00
gingerBill 81b24594ce Add udivmod128.odin 2019-12-21 19:49:09 +00:00
gingerBill 995ba0df9a Fix using on array in struct 2019-12-21 14:42:08 +00:00
gingerBill 08392d885e Add strconv/integers.odin 2019-12-21 14:01:29 +00:00
gingerBill d462dbb5be Deprecate using import 2019-12-21 12:11:16 +00:00
gingerBill 19c32ecb81 Add extra to -help output 2019-12-21 11:27:55 +00:00
gingerBill 494b1e7eaa Add -help which prints information about the compiler flags 2019-12-21 11:22:46 +00:00
gingerBill c43d17bfec Merge pull request #505 from Tetralux/patch-2
Fix mem.Arena
2019-12-16 08:05:39 +00:00
Tetralux c9723e2dc0 Fix mem.Arena 2019-12-15 21:36:40 +00:00
gingerBill 4ba579bc25 Also allow #no_bounds_check on an expression #499 2019-12-15 11:41:21 +00:00
gingerBill 58d4d424c6 Replace #vector[N]T with #simd[N]T to reduce confusion #498 2019-12-15 11:30:09 +00:00
gingerBill 89ccb5b99f Add assert into scratch_allocator_proc to prevent initialization cycles #504 2019-12-15 11:20:06 +00:00
gingerBill 7f5021c8e9 Disallow procedure calls with an associated deferred procedure to be used in logical binary expressions (short-circuiting) 2019-12-15 11:10:50 +00:00
gingerBill 8bec324779 Fix Duplicate integer switch case values incorrectly consider its absolute value #502
(Hashing proc was wrong for big ints)
2019-12-15 09:56:11 +00:00
gingerBill e6f26b9931 Fix Unable to initialize a typeid field in a struct literal #501 2019-12-15 09:48:05 +00:00
gingerBill b8c534eba9 Merge pull request #500 from SSStormy/fix-string_to_enum_value
Fix 'fmt.string_to_enum_value' not compiling
2019-12-15 09:38:37 +00:00
Justas Dabrila 95d3f43e15 Fix 'string_to_enum_value' not compiling 2019-12-14 01:08:47 +02:00
vassvik 2d97e1dee3 Fix NaN checks in core:math.classify
Currently the classify procedures checks for NaNs using the check `x != x`, which is always false for NaNs and therefore that case is never entered. Using `!(x == x)` will work on the other hand.
2019-12-12 19:12:12 +01:00
gingerBill be2dfd42fd Merge pull request #493 from ThisDrunkDane/master
Fix #399 by removing unused parameter
2019-12-08 14:35:18 +00:00
Mikkel Hjortshoej 851118faf4 Fix #399 by removing unused parameter 2019-12-08 02:09:03 +01:00
gingerBill 53cd7a3d0c Fix transmute from uintptr to/from proc 2019-12-07 15:44:28 +00:00
gingerBill f170648629 Fix issue with -thread-count flag with <= 0 count 2019-12-03 18:23:14 +00:00
gingerBill 42def957d5 Fix append_elem_string, again 2019-12-03 09:35:24 +00:00
gingerBill 6433a0d31e Fix append_elem_string 2019-12-03 09:16:11 +00:00
gingerBill 359e5d9e15 Fix append_elem_string 2019-12-03 09:07:15 +00:00
gingerBill e229885b2b Remove addressing mode Addressing_Immutable 2019-12-01 19:11:00 +00:00
gingerBill ee78374281 Fix typo 2019-12-01 18:57:43 +00:00
gingerBill ebe152a155 Disable aligned heap allocations hack in os.heap_allocator_proc 2019-12-01 18:53:27 +00:00
gingerBill 46582a45bd Fix IR string interning type 2019-12-01 18:18:03 +00:00
gingerBill 6b5ea011e7 Add strings.ptr_from_string 2019-12-01 18:06:49 +00:00
gingerBill 9503440eb0 Add strings.unsafe_string_to_cstring 2019-12-01 17:45:07 +00:00
gingerBill 3fa4c5043a Fix crash caused by not checking for correct SOA kind on polymorphic parameters 2019-12-01 16:05:48 +00:00
gingerBill 9db81498d8 Make the string type elements "immutable", akin to char const * in C
Allows for extra security and optimization benefits
2019-12-01 14:10:59 +00:00
gingerBill 7fbe0a6f23 Fix nil comparisons for soa slices and dynamic arrays 2019-12-01 11:56:08 +00:00
gingerBill 3fd5c3cd85 Merge pull request #458 from Tetralux/linux-threads
Implement core:thread and core:sync on Unix using pthreads
2019-12-01 11:33:23 +00:00
Tetralux 99121d6ff2 Implement core:thread and core:sync on Unix using pthreads
Also do some cleanup and refactoring of the thread, sync and time APIs.

- remove 'semaphore_release' because 'post' and 'wait' is easier to understand

- change 'semaphore_wait' to '*_wait_for' to match Condition

- pthreads can be given a stack, but doing so requires the user to set up the guard
  pages manually. BE WARNED. The alignment requirements of the stack are also
  platform-dependant; it may need to be page size aligned on some systems.
  Unclear which systems, however. See 'os.get_page_size', and 'mem.make_aligned'.
  HOWEVER: I was unable to get custom stacks with guard pages working reliably,
  so while you can do it, the API does not support it.

- add 'os.get_page_size', 'mem.make_aligned', and 'mem.new_aligned'.

- removed thread return values because windows and linux are not consistent; windows returns 'i32'
  and pthreads return 'void*'; besides which, if you really wanted to communicate how the
  thread exited, you probably wouldn't do it with the thread's exit code.

- fixed 'thread.is_done' on Windows; it didn't report true immediately after calling 'thread.join'.

- moved time related stuff out of 'core:os' to 'core:time'.

- add 'mem.align_backward'

- fixed default allocator alignment
  The heap on Windows, and calloc on Linux, both have no facility to request alignment.
  It's a bit of hack, but the heap_allocator now overallocates; `size + alignment` bytes,
  and aligns things to at least 2.
  It does both of these things to ensure that there is at least two bytes before the payload,
  which it uses to store how much padding it needed to insert in order to fulfil the alignment
  requested.

- make conditions more sane by matching the Windows behaviour.
  The fact that they were signalled now lingers until a thread tries to wait,
  causing them to just pass by uninterrupted, without sleeping or locking the
  underlying mutex, as it would otherwise need to do.
  This means that a thread no longer has to be waiting in order to be signalled, which
  avoids timing bugs that causes deadlocks that are hard to debug and fix.
  See the comment on the `sync.Condition.flag` field.

- add thread priority: `thread.create(worker_proc, .High)`
2019-12-01 00:46:23 +00:00
gingerBill 0c0c83ee29 Disable find_visual_studio_and_windows_sdk_utf8 temporarily 2019-11-28 21:07:06 +00:00
gingerBill b75d59d6e0 Make sort.merge_sort in place; Add sort.heap_sort 2019-11-27 16:06:07 +00:00
gingerBill 71c8a3456e Update package odin/parser for #soa and #vector 2019-11-27 15:23:54 +00:00
gingerBill 37e3e081c6 Update microsoft_craziness.h to work correctly with the rest of the codebase (and not use WIN32_LEAN_AND_MEAN) 2019-11-27 15:18:32 +00:00
gingerBill 5ea9fc3fb0 Merge pull request #478 from castano/auto-search-sdk
Allow running Odin compiler without using visual studio command prompt or setting up environgment variables.
2019-11-26 22:29:08 +00:00
Mikkel Hjortshøj 53f65224f6 Merge pull request #459 from zhibog/master
Base32 added for core:encoding
2019-11-26 19:45:52 +01:00
gingerBill 902d313c6a Fix issue with os.write on *nix with writing nothing 2019-11-24 10:08:08 +00:00
gingerBill 45d844f9d2 Disable #soa compound literals 2019-11-21 20:05:45 +00:00
gingerBill 9b58781122 #soa[dynamic]Type (Experimental) 2019-11-21 19:36:07 +00:00
gingerBill b74f8f2047 Fix SOA entity usage error on -vet 2019-11-21 18:21:27 +00:00
gingerBill 88c90cf99a Update demo.odin 2019-11-21 14:41:33 +00:00
gingerBill 321dcc60e3 Update fmt.odin 2019-11-21 14:41:12 +00:00
gingerBill 400f12f31f Update demo.odin 2019-11-21 14:23:59 +00:00
gingerBill 2c5a84bb78 #soa[]Type (Experimental) 2019-11-21 00:07:21 +00:00
gingerBill e01d8a04a9 Fix String causes a crash when used in a polymorphic type #483 2019-11-20 22:07:12 +00:00
gingerBill 69afa33fa5 Fix Implicit Selector Expressions do not work at the global/package scope #484 2019-11-20 21:56:37 +00:00
gingerBill 44e0e96612 Prepare SOA Struct code for slices and dynamic arrays *to be implemented* 2019-11-19 23:54:36 +00:00
gingerBill 0839dccfdc Fix Compiler panic with SIMD Vector debug information #481 2019-11-19 23:24:49 +00:00
zhibog 2484f4d04b Removed CSV stuff. 2019-11-17 20:09:00 +01:00
gingerBill d22e5b697d Add new #soa and #vector syntax 2019-11-17 10:30:37 -08:00
gingerBill 301ee664e9 Add Handmade Seattle 2019 Demos 2019-11-16 06:59:48 -08:00
gingerBill 9b4d4a2c61 Minor fix to os.write on darwin 2019-11-16 06:59:14 -08:00
gingerBill d9647174a3 Merge pull request #479 from ThisDrunkDane/master
Fix CI badge on README.md
2019-11-14 22:57:08 +00:00
gingerBill 4d29b64196 Merge pull request #475 from hasenj/reverse
fix string reversal
2019-11-14 22:52:01 +00:00
gingerBill 8be1b2e1b1 Merge pull request #476 from castano/symlink-fix
Add support for running odin through a symlink.
2019-11-14 22:50:17 +00:00
Mikkel Hjortshoej b85258a9fc Add event query param to CI badge 2019-11-14 14:47:01 -08:00
gingerBill 07897ed78e Fix System V bitcast/transmute bug 2019-11-14 14:45:23 -08:00
Mikkel Hjortshoej 8115386217 Add branch query to CI badge 2019-11-14 14:39:11 -08:00
castano f8dd4816ff Integrate microsoft_craziness better. 2019-11-14 09:30:05 -08:00
castano 928a445a14 Fix definition. GB_SYSTEM_WINDOWS is not defined yet. Ideally microsoft_crazines.h should be included after common, but conflicts with defer macro. 2019-11-14 09:29:59 -08:00
castano 42cd78497a Use Jon's single file lib to find the latest compiler and SDK paths instead of relying on environment variables.
This allows you to run the odin compiler without having to use the visual studio command prompt or setting up environment variables. It would be nice to not rely on the automatic search exclusively, but allow specifying the desired compiler or SDK version.

This change introduces various library dependencies in order to interact with COM objects. Not sure if there's a way around that.
2019-11-14 09:29:45 -08:00
castano 813f5d211f Fix linux build. 2019-11-14 09:22:37 -08:00
castano 71d129a709 Add support for running odin through a symlink. Use realpath when obtaining root dir. 2019-11-14 00:50:26 -08:00
Hasen Judy c35762528c fix string reversal 2019-11-13 23:36:52 +09:00
gingerBill aa796a1032 v0.11.1 2019-11-12 21:20:40 +00:00
gingerBill 5bf71ba75c big_int addition overflow rules 2019-11-11 22:47:25 +00:00
gingerBill 967981aacd Add -show-more-timings 2019-11-10 21:49:02 +00:00
gingerBill 33d05a07de Fix big_int_or and big_int_xor 2019-11-10 20:06:04 +00:00
gingerBill 8da8301b09 Fix big subtraction for very large numbers on edges of overflow. 2019-11-10 19:55:26 +00:00
gingerBill 536cceeef9 Add intrinsics.type_is_unsigned 2019-11-10 18:51:21 +00:00
gingerBill 098684a6fe Add 128-bit random procedures to package math/rand 2019-11-10 18:47:16 +00:00
zhibog 694ee02247 Missed one 2019-11-09 18:06:33 +01:00
zhibog 0451c88ab6 Fixed indenting 2019-11-09 18:04:30 +01:00
gingerBill 2ef7bfc06e Remove debug message 2019-11-09 10:45:03 +00:00
gingerBill 7bfdb4f9f4 Fix Compile time assert on non-constant boolean parameters #467 2019-11-09 10:44:42 +00:00
gingerBill 0a35b13411 Fix inline for bug for #468 2019-11-09 10:24:27 +00:00
zhibog 803f6a6651 Added procs to read and write just the data, without any file loading / writing 2019-11-08 22:17:24 +01:00
zhibog 672cfd51c3 Added names to return values 2019-11-08 20:21:18 +01:00
zhibog 80cdf8b6a8 Should be row_count obviously 2019-11-08 20:16:56 +01:00
zhibog dc2d5239c5 Removed comments regarding RFC test vectors 2019-11-08 20:06:58 +01:00
gingerBill dacfc9de15 Fix //+build for ! e.g. //+build !windows amd64, linux !amd64 2019-11-05 20:09:09 +00:00
gingerBill 689aa4d734 Fix //+build system 2019-11-05 20:02:11 +00:00
gingerBill 8a46b493fd Fix Slice passed incorrectly in LLVM IR to procedure called via procedure pointer #465 2019-11-05 19:40:08 +00:00
gingerBill 86abdc0603 Merge branch 'master' of https://github.com/odin-lang/Odin 2019-11-05 19:37:30 +00:00
gingerBill a634444f99 Fix "Polymorphic parameter declared in return type doesn't compile #464" by giving a conversion error (code wasn't handling polymorphic result types as intended) 2019-11-05 19:37:19 +00:00
vassvik 04a25b11ad Fix incorrect math.linalg.cross3 indices. 2019-11-04 17:39:26 +01:00
gingerBill 40546fbde2 Use runtime.mem_copy in package me 2019-11-03 19:59:41 +00:00
gingerBill c1176c2bcb Fix typeid comparison bug; Add extra messages for pointer address errors 2019-11-03 19:49:21 +00:00
gingerBill 57853fe1b1 Add SOA Struct Layout (experimental) to demo.odin 2019-11-03 12:52:13 +00:00
gingerBill 013b3b9fb3 Fix for -vet 2019-11-03 11:42:00 +00:00
gingerBill dc0f04e53b Fix typo in fmt 2019-11-03 00:50:47 +00:00
gingerBill 40606d9272 Fix fmt printing of anonymous SOA structs 2019-11-03 00:47:27 +00:00
gingerBill ebf7926fa4 SOA support of Structures and Arrays; Runtime information for SOA structs; fmt printing support for SOA structs 2019-11-03 00:32:22 +00:00
gingerBill dfb3101ecf SOA Struct support intrinsics.soa_struct 2019-11-02 21:08:51 +00:00
gingerBill e3d3a81617 multivalued procedure calls allows in for in to allow a pseudo-iterator; @thread_local for variables in procedure 2019-11-02 16:36:46 +00:00
gingerBill dbdbbcd60f Fix range in statement bug caused by incorrectly assigned addressing mode #461 2019-11-02 10:57:42 +00:00
gingerBill f9aaff99c6 Fix linalg.mul; add linalg.Matrix1xN 2019-11-02 10:30:11 +00:00
zhibog 4b718aae75 Added an implementation for reading and writing csv files 2019-11-01 22:35:46 +01:00
zhibog 20db0e7f09 Added Base32 + official test vectors from the RFC 2019-11-01 22:35:09 +01:00
zhibog 614ea5c168 Added official test vectors from the RFC 2019-11-01 22:34:19 +01:00
gingerBill 57565b78a6 v0.11.0 2019-11-01 19:45:39 +00:00
gingerBill b5b085914a Merge pull request #404 from hazeycode/master
Impl time for macOS
2019-11-01 19:44:50 +00:00
Chris Heyes 044e64beb0 Add missing foreign import to time_darwin 2019-11-01 19:39:26 +00:00
Chris Heyes adca5b57cd Move time code from os to time package 2019-11-01 19:33:48 +00:00
gingerBill 3b898e5224 Add @force to foreign import 2019-11-01 19:26:22 +00:00
Chris Heyes 153e7525b5 Merge remote-tracking branch 'upstream/master' 2019-11-01 19:18:33 +00:00
gingerBill 44a303e577 Add dummy packages purely for documentation of builtin and intrinsics 2019-11-01 19:00:23 +00:00
gingerBill d63878d0dd Merge pull request #437 from nakst/master
updated os_essence.odin
2019-11-01 10:20:29 +00:00
gingerBill a20c31d6b5 Fix polymorphic record parameter determination bug caused by polymorphic constants not being handled correctly #447 2019-10-31 22:58:38 +00:00
gingerBill 560bdc339b Fix stack overflow bug caused by polymorphic record with polymorphic constant parameters. #447
DOES NOT FIX THE UNDERLYING BUG
2019-10-31 22:39:12 +00:00
gingerBill 01dfb1dac8 Fix double calling of lhs of logical binary expressions 2019-10-31 20:17:50 +00:00
gingerBill ee8d3e03f8 Delay determination of procedure abi types until as late as possible to prevent type undetermination in self-referential data types #454 2019-10-31 18:25:39 +00:00
gingerBill 4aad45e3e7 Merge pull request #453 from kevinw/master
Remove unused variables in utf8.odin.
2019-10-29 11:47:37 +00:00
gingerBill fe5c642d9f Fix runtime.cstring_len 2019-10-29 08:47:05 +00:00
Kevin Watters b5fdb3f855 Remove unused variables in utf8.odin. 2019-10-28 11:13:47 -04:00
gingerBill 416ff149bd Fix procedure group "best fit" algorithm for polymorphic procedures 2019-10-27 19:42:21 +00:00
gingerBill 233c6e2d3a Merge branch 'master' of https://github.com/odin-lang/Odin 2019-10-27 18:43:53 +00:00
gingerBill a29a6d9285 Fix typos in package linalg; Fix norm_float64 in package rand 2019-10-27 18:43:40 +00:00
Mikkel Hjortshøj a7a31e4c23 Set CI shell on windows to cmd.exe 2019-10-27 18:12:23 +01:00
Mikkel Hjortshøj 72cad591bd Update ci.yml 2019-10-27 18:07:14 +01:00
Mikkel Hjortshøj 684bf7aa61 Update ci.yml 2019-10-27 18:04:14 +01:00
Mikkel Hjortshøj d760b95e4f Update ci.yml 2019-10-27 18:02:39 +01:00
gingerBill 5e81fc72b9 New package math and package math/linalg 2019-10-27 10:35:35 +00:00
gingerBill 0977ac111a Fix typo in package utf8; add wchar_t to package c 2019-10-27 08:34:20 +00:00
gingerBill 2db16d6a32 Add for package utf8: rune_at_pos, rune_string_at_pos, rune_at, rune_offset 2019-10-26 15:05:36 +01:00
gingerBill 5aa46d31b2 Move package decimal to be a subpackage of package strconv 2019-10-26 14:46:21 +01:00
gingerBill 14e8b299b7 Fix slice and dynamic array lengths determined from ranged compound literals 2019-10-26 14:43:06 +01:00
gingerBill c7cb754514 Fix typos 2019-10-26 14:37:27 +01:00
gingerBill a5e42a0465 Add ranged_fields_for_array_compound_literals 2019-10-26 14:36:28 +01:00
gingerBill d808f9eccf Add range_cache.cpp 2019-10-26 14:29:04 +01:00
gingerBill 1734eb949f Update utf8.accept_sizes to use ranged fields 2019-10-26 14:18:38 +01:00
gingerBill 7fae890ef9 Allow ranges for array-like compound literals 2019-10-26 14:06:29 +01:00
gingerBill 94879ed149 Fix Compiler assertion when applying using to _ procedure parameter. #451 2019-10-26 12:14:04 +01:00
gingerBill 2c75fe2314 Allow for cycles in record polymorphic parameters but not in actualized fields 2019-10-26 11:50:42 +01:00
gingerBill 1da0668653 Add utf8.rune_index 2019-10-26 11:50:01 +01:00
gingerBill c60fb10a6a Move old demos and old stuff to /misc 2019-10-26 10:40:17 +01:00
gingerBill 7140f42915 Modify runtime to reduce dependencies on other packages 2019-10-23 21:43:13 +01:00
gingerBill ad92fbfd4e Merge branch 'master' of https://github.com/odin-lang/Odin 2019-10-23 21:42:42 +01:00
gingerBill 1416946757 Add token.odin 2019-10-23 21:42:28 +01:00
gingerBill 6a8c4ee04c Merge pull request #450 from ThisDrunkDane/master
Setup Github Actions instead of Travis and Appveyor
2019-10-21 22:17:05 +01:00
Mikkel Hjortshøj 516df9123d Update README.md 2019-10-21 23:08:16 +02:00
Mikkel Hjortshøj 818d6dbbea Update README.md with new CI badge 2019-10-21 23:05:18 +02:00
Mikkel Hjortshoej 286c5b7b24 Remove old CI runners 2019-10-21 23:01:32 +02:00
Mikkel Hjortshøj c0e8113f6f Add github CI action 2019-10-21 23:00:24 +02:00
gingerBill e15dfa8eb6 Fix missing check for zero elements 2019-10-20 18:26:30 +01:00
gingerBill f12ded54f2 Support for named indices for array-like compound literals {3 = a, 1 = b} 2019-10-20 13:11:28 +01:00
gingerBill b4951c9b39 Merge branch 'master' of https://github.com/odin-lang/Odin 2019-10-20 10:50:30 +01:00
gingerBill 9f0a28017d Fix typo in string_to_string16 #444 2019-10-20 10:50:18 +01:00
Mikkel Hjortshøj d7c8a3a9dd Merge pull request #445 from Tetralux/patch-2
Clarify that you can pass a directory to `odin build`
2019-10-19 18:57:23 +02:00
Tetralux 10b109e25f Clarify that you can pass a directory to odin build
Changes the usage information to this:
```
D:\Software\odin\odin.exe is a tool for managing Odin source code
Usage:
        D:\Software\odin\odin.exe command [arguments]
Commands:
        build     compile .odin file, or directory of .odin files, as an executable.
                  one must contain the program's entry point, all must be in the same package.
        run       same as 'build', but also then runs the newly compiled executable.
        check     parse and type check .odin file
        query     parse, type check, and output a .json file containing information about the program
        docs      generate documentation for a .odin file
        version   print version
```
2019-10-19 17:55:05 +01:00
gingerBill 2afe4bea67 Add instrincs.type_is_valid_map_key 2019-10-15 22:43:04 +01:00
gingerBill 12ae5ed09e Fix missing typeid conversion case for variadic parameters 2019-10-15 20:47:27 +01:00
gingerBill 0bdc3b4f21 Fix Values coerce to typeid #443 2019-10-15 17:54:37 +01:00
gingerBill eaabb888d4 Update Odin Logo 2019-10-15 17:42:55 +01:00
gingerBill b53fe14c22 Change error to syntax_error in parser 2019-10-13 16:06:41 +01:00
gingerBill 45683703ea Fix System V for certain structs 2019-10-13 14:29:56 +01:00
gingerBill 03053a18ce Fix IR generation bug for nested foreign procedure declaration 2019-10-13 12:51:47 +01:00
gingerBill 2a6d9e8927 #panic; Minor change to demo.odin; Fix #assert bug at file scope 2019-10-13 12:38:23 +01:00
gingerBill fa81061db0 Minor fix to Odin types with System V ABI 2019-10-10 21:50:20 +01:00
gingerBill 39b3c8c80f Update System V ABI to for more Odin types 2019-10-10 21:39:46 +01:00
gingerBill 3139151935 Minor fix to systemv_distribute_struct_fields 2019-10-10 21:24:32 +01:00
gingerBill 672a8f5dbd Add Odin types for System V ABI 2019-10-10 21:13:06 +01:00
gingerBill 8672ff1c55 Fix typo in System V ABI determination 2019-10-10 20:57:31 +01:00
gingerBill abfa894566 Fix general IR parameter case 2019-10-10 20:52:07 +01:00
gingerBill 5b52fed268 Correct (experimental) System V AMD64 ABI support 2019-10-10 20:41:16 +01:00
Mikkel Hjortshøj 94a638b436 Update README.md
Remove license badge (Github shows it themselves now) and add discord badge
2019-10-10 11:10:10 +02:00
gingerBill 1b8c3ca22a Fix typos and make demo work with -vet 2019-10-08 20:28:45 +01:00
gingerBill 71b32ae117 Update demo.odin 2019-10-06 19:20:00 +01:00
gingerBill 939459b635 Change implicit semicolon rules for record types within procedure bodies; Update package odin/* 2019-10-06 19:16:55 +01:00
gingerBill 562b518394 Change print*_err to eprint* in core library 2019-10-06 18:54:29 +01:00
gingerBill d62503d031 Change precedence for in and notin to match + - | ~ 2019-10-06 18:14:02 +01:00
gingerBill 4e8a801b35 strings.split; strings.index; eprint* over print*_err; 2019-10-06 18:13:15 +01:00
gingerBill e1b711b3b3 Update demo.odin with more information 2019-10-06 15:07:16 +01:00
gingerBill 6c69e8c043 Make typeid semantics consistent across variables and constants 2019-10-06 14:55:25 +01:00
gingerBill 7fa2d25eea Fix #complete switch with pointer case doesn't compile #416 2019-10-05 10:22:41 +01:00
gingerBill dae514a2c9 Fix Using any in if statement asserts compiler #441 2019-10-05 09:40:05 +01:00
gingerBill 068993a819 Remove os_osx.odin 2019-10-01 20:55:15 +01:00
gingerBill 66ae4e5afc Change ODIN_OS string for osx from "osx" to "darwin" to allow for other platforms 2019-10-01 20:38:50 +01:00
gingerBill 218d1131e8 Change how foreign imports work for mac 2019-09-29 09:25:33 +01:00
gingerBill f4f6e9ad49 Fix -debug crash on windows caused by missing debug info for files. 2019-09-25 21:07:56 +01:00
gingerBill 48ab7f876c Fix Implicit Selector Expressions do not work for parameteric struct parameters. #438 2019-09-25 20:52:47 +01:00
nakst 1e53a6fa96 updated os_essence.odin 2019-09-18 16:19:19 +01:00
gingerBill 4cef160c87 Merge branch 'master' of https://github.com/odin-lang/Odin 2019-09-17 19:47:13 +01:00
gingerBill 68582c5ad1 Add suggestions to errors on casts and assignments. 2019-09-17 19:47:04 +01:00
gingerBill a9a2dafca5 Merge pull request #430 from nakst/master
New Essence OS layer; cross-compiling improvements
2019-09-09 14:39:35 +01:00
gingerBill da3467c25f Merge pull request #434 from odin-lang/ThisDrunkDane-patch-1
Make `odin run` return the process exit code
2019-09-08 20:28:10 +01:00
gingerBill 5fc42bf9c9 Update demo.odin 2019-09-08 19:15:12 +01:00
gingerBill 42bbd31df1 Disallow where clauses on non-polymorphic records 2019-09-08 19:03:57 +01:00
gingerBill c7cc38b7d8 Remove assert 2019-09-08 15:47:57 +01:00
gingerBill 4afc78efc6 Add where clauses to struct and union 2019-09-08 12:12:41 +01:00
Mikkel Hjortshøj bc34083c9c Also return on unix 2019-09-08 01:10:54 +02:00
Mikkel Hjortshøj 08dd8414c1 Make odin run return the process exit code 2019-09-08 01:09:04 +02:00
gingerBill d54255505a Fix Compiler does not complain about missing semicolon #433 2019-09-04 18:10:02 +01:00
gingerBill d4914c3546 Fix Ir panic on using append() from within anonymous function #432 2019-09-04 18:06:02 +01:00
gingerBill 772c8779fa Clean up thread pool code 2019-09-03 22:11:21 +01:00
gingerBill c92b2e9612 Fix semaphore posting 2019-09-03 21:17:46 +01:00
gingerBill 1af143b749 Fix debug mode for build.bat 2019-09-02 21:16:17 +01:00
gingerBill 1370c10d1b Fix Converting addresses to function pointers produces llvm-opt error #431 2019-09-02 18:59:07 +01:00
gingerBill 1348d8a8cd Improve thread pool (volatile hints, etc) 2019-09-02 18:49:23 +01:00
gingerBill 495aaacb81 Fix build.bat 2019-09-02 18:35:00 +01:00
nakst 22e982c8fb New Essence OS layer; cross-compiling improvements 2019-09-02 16:46:50 +01:00
gingerBill 6d614ef07c Remove thread naming on thread pool 2019-09-01 23:16:01 +01:00
gingerBill 723f351a6d Remove custom allocator for thread pool 2019-09-01 23:13:29 +01:00
gingerBill c93872cc13 Thread pool fixes 2019-09-01 22:57:53 +01:00
gingerBill 97dece15d7 Minor changes 2019-09-01 22:18:55 +01:00
gingerBill 657103c4cf ThreadPool for the parser 2019-09-01 20:02:39 +01:00
gingerBill b9d3129fb3 where clauses for procedure literals 2019-08-31 20:13:28 +01:00
gingerBill b311540b16 Make require_results an attribute rather than a suffix tag for procedures 2019-08-31 14:48:56 +01:00
gingerBill 07ced1cf0e Fix variable dependency ordering issues caused by procedure literals 2019-08-31 11:12:41 +01:00
gingerBill a1d4ea7718 Merge pull request #425 from thebirk/parser-threading
Fixed parser creating a new thread for each file.
2019-08-29 20:44:48 +01:00
thebirk f921a91fc8 Properly removed the semaphore. 2019-08-29 20:35:12 +02:00
thebirk 4dade34603 Removed unused semaphore on Parser. 2019-08-29 20:34:09 +02:00
thebirk d76249d90b Cleaned up parse_packages and the worker proc. 2019-08-29 20:27:38 +02:00
gingerBill d118fc569a Add intrinsincs.type_is_quaternion 2019-08-29 16:45:36 +01:00
gingerBill 2dc39a5cbd Improve demo.odin 2019-08-29 15:25:46 +01:00
gingerBill c89fc35e94 Fix global variable initialization ordering
(related to #427)
2019-08-29 14:36:42 +01:00
gingerBill 614d209824 Add debug information for quaternion types (fixes #428) 2019-08-29 10:39:03 +01:00
gingerBill f1a7b31209 Fix nested raw_union with using #428 2019-08-28 13:34:55 +01:00
thebirk 6a8b3fee38 Removed gb_thread_set_name because it segfaults on linux. 2019-08-26 20:23:52 +02:00
thebirk 4551521b2c Im just trying things at this point, Bill should just squash this PR at merge time ;) 2019-08-26 19:51:33 +02:00
thebirk 97dfcffa76 Fixed error where the parser would end early. 2019-08-26 19:09:52 +02:00
gingerBill 6d3feb4531 Fix typo in tokenizer (no actual bug) 2019-08-26 16:18:26 +01:00
thebirk c44d25d14f Fixed parser creating a new thread for each file. 2019-08-26 16:47:41 +02:00
gingerBill 25dd00cd0b Add complex/quaternion raw layouts to mem/raw.odin 2019-08-26 14:40:04 +01:00
gingerBill 01c10aa944 inline for loops (only for 'in' based for loops) 2019-08-26 13:54:35 +01:00
gingerBill 4908d1ebdd Update odin_tokenizer to support quaternion literals 2019-08-26 11:56:04 +01:00
gingerBill 7bc146e6fd Built-in Quaternions (Not just an April Fool's Joke any more) 2019-08-26 11:33:05 +01:00
gingerBill 59ab51acec Fix typo 2019-08-23 11:54:23 +01:00
gingerBill cf23954297 Improve #assert to show the procedure and signature it was called with; Allow the ability to print ExactValue correct now. 2019-08-23 11:51:04 +01:00
gingerBill d1cc6534cd Remove the rule that made any declaration prefixed with an underscore private to that package. 2019-08-23 10:32:05 +01:00
gingerBill 1b454c7ded Merge branch 'master' of https://github.com/odin-lang/Odin 2019-08-23 10:24:25 +01:00
gingerBill 150d4e343d Fix ~(1 << x) type inference bug 2019-08-23 10:24:18 +01:00
gingerBill 28ada801a0 Merge pull request #419 from zhibog/master
Added an implementation for Base64. Also provides the ability to supp…
2019-08-16 19:42:03 +01:00
zhibog a7676bff6e Added an implementation for Base64. Also provides the ability to supply your own alphabet and decoding table. 2019-08-15 22:05:06 +02:00
gingerBill 4369298e96 Add reflect/types.odin 2019-08-13 23:21:51 +01:00
gingerBill a58c29582e Add new stuff to package reflect; fix -vet for odin_parser 2019-08-13 23:21:33 +01:00
gingerBill 3ad20a2d2d Remove package types and merge with package reflect 2019-08-13 22:59:07 +01:00
gingerBill b86dfa7af7 Fix compiler crash with #defined #417 2019-08-13 22:51:04 +01:00
gingerBill 980890ee8a Make -vet happy on *nix 2019-08-13 22:39:53 +01:00
gingerBill 0a63690b39 Fix typo in ? array lengths error 2019-08-13 22:34:02 +01:00
gingerBill 0076a4df62 Fix compound literal printing for structs with custom alignment requirements 2019-08-13 22:33:05 +01:00
gingerBill 4c065a7e99 Keep -vet happy 2019-08-13 22:27:52 +01:00
gingerBill 04036aba9c package reflect; fix substring type bug; fix scoping rules for using on procedure parameter 2019-08-11 23:58:49 +01:00
gingerBill b08aa857b3 Remove dead keywords in odin_token 2019-08-09 23:01:22 +01:00
gingerBill 2d26278a65 Make structs with the same fields but with different tags distinct types 2019-08-09 22:52:19 +01:00
gingerBill 27a3c5449a Fix global variable initialization for certain types. 2019-08-09 22:35:48 +01:00
gingerBill 9c63212824 Struct field tags 2019-08-09 21:59:58 +01:00
gingerBill 65d41d4248 Fix bit_field comparison against nil #414 2019-08-09 20:31:11 +01:00
gingerBill b04231dd95 Improve implementation of intrinsics.type_* procedures 2019-08-04 14:54:23 +01:00
gingerBill 37633c1d2a intrinsics.type_* constant evaluation procedures 2019-08-04 11:02:00 +01:00
gingerBill 5877017d30 Add error message for non-constant polymorphic name parameters 2019-08-03 10:15:31 +01:00
gingerBill 132fdf14b8 Fix min, max, clamp final type bug 2019-08-03 10:07:09 +01:00
gingerBill e7d3001dd1 Fix constant default value error #408 (typo) 2019-07-29 18:33:06 +01:00
gingerBill f163181204 Add extra hints for LLVM for implicit reference parameters 2019-07-29 10:43:07 +01:00
gingerBill 2c5c8192f8 Fix parsing for procedure literals expression statements; improve assert performance; other minor fixes 2019-07-28 22:58:56 +01:00
gingerBill 162c87b1b8 Minor code clean-up 2019-07-28 18:44:50 +01:00
gingerBill 77734ea967 Improve the performance of simple array comparisons 2019-07-27 11:59:50 +01:00
gingerBill 912fc2890b Fix array comparisons and fix f32 literal LLVM issue regarding accurate representation 2019-07-27 11:33:22 +01:00
gingerBill 14059583cd Fix array comparisons 2019-07-27 10:44:40 +01:00
gingerBill f3bffb9810 Improvement to the Odin calling conventions to pass certain things by "implicit reference" (const & in C++) 2019-07-27 10:20:11 +01:00
gingerBill 540730c0be Merge branch 'master' of https://github.com/odin-lang/Odin 2019-07-27 00:45:44 +01:00
gingerBill 40f0e74b8c Change scoping rules to allow for shadowing of procedure parameters but not named return values 2019-07-27 00:45:36 +01:00
Mikkel Hjortshøj 5ca0cd60d0 Merge pull request #406 from JoshuaManton/master
Fix `scale_f32` and `scale_vec3` returning the wrong variable
2019-07-20 22:21:58 +02:00
Joshua Mark Manton 96f0a08725 Fix scale_f32 and scale_vec3 from returning the wrong variable. 2019-07-20 13:15:51 -07:00
Chris Heyes d85893954d Impl time for macOS 2019-07-16 23:49:53 +01:00
gingerBill d26033eb23 Revert demo.odin 2019-07-15 22:41:25 +01:00
gingerBill c7a70be824 Fix __get_map_key 2019-07-15 22:38:51 +01:00
gingerBill 08c490d9ac Fix bounds checking on slices for constant parameters 2019-07-15 22:26:51 +01:00
gingerBill 8ee7ee7120 Fix core library for the new procedure parameter addressing mode 2019-07-15 22:16:27 +01:00
gingerBill d471a59041 IR fix array comparisons 2019-07-15 21:32:38 +01:00
gingerBill f25818e923 Make procedure parameters just named values rather than copied variables 2019-07-15 21:18:37 +01:00
gingerBill 3d531be711 Improve type hinting for named parameters in call expressions 2019-07-13 15:38:50 +01:00
gingerBill 56d365a4e7 Improve type inference for procedure group parameters 2019-07-13 13:34:21 +01:00
gingerBill 308300c1fc Add extra error handling for parsing slices 2019-07-09 11:18:50 +01:00
gingerBill 927d6814f2 slice_data_cast 2019-07-09 11:09:46 +01:00
gingerBill 7c99f52187 Add minimum requirement of 2 variants for #no_nil 2019-07-09 10:49:45 +01:00
gingerBill 4ab9edeb53 union #no_nil 2019-07-09 10:28:13 +01:00
gingerBill c5b3d7a736 Update package odin_parser 2019-07-07 16:20:58 +01:00
gingerBill d7172e168e Fix target list branch rules for name-labelled block/if statements 2019-07-07 16:06:41 +01:00
gingerBill d99ffe604f Fix unions with zero variants 2019-07-07 14:38:11 +01:00
gingerBill b77c79294c Merge branch 'master' of https://github.com/odin-lang/Odin 2019-07-07 14:14:36 +01:00
gingerBill 8e722274f0 Disallow blank identifier polymorphic types $_ 2019-07-07 14:14:28 +01:00
gingerBill ebe7fc23a5 Merge pull request #400 from asmoaesl/patch-1
Correct two typos
2019-06-29 12:09:46 +01:00
Luke I. Wilson 4d40f564ef Correct two typos 2019-06-28 20:42:59 -05:00
gingerBill fd62959bf4 Fix procedure constant declaration value type assignment checking 2019-06-21 23:11:14 +01:00
gingerBill 8b8cada33e Fix procedure group compiler assert with no matching arguments #393 2019-06-21 22:55:00 +01:00
gingerBill aaa24894b6 Fix double-pointer indexing bug #396 2019-06-21 22:50:29 +01:00
gingerBill 2af19c496e Fix comparison for bit field values #386 2019-06-21 22:48:37 +01:00
gingerBill fea34b32ea Merge branch 'master' of https://github.com/odin-lang/Odin 2019-06-21 22:40:20 +01:00
gingerBill b891c0feab Fix ranges in switch statement for strings 2019-06-21 22:40:11 +01:00
gingerBill 9f039c323e Update FUNDING.yml 2019-06-20 09:29:18 +01:00
gingerBill b0dd3ac599 v0.10.0 2019-06-02 12:27:36 +01:00
gingerBill b38a8cfb12 Move internal 128-bit stuff to a windows specific file 2019-06-01 12:26:54 +01:00
gingerBill 4c79b52867 Update README.md 2019-05-30 18:08:35 +01:00
gingerBill 6dba05b00d Update README.md 2019-05-30 18:07:54 +01:00
gingerBill 32a29d627a Create FUNDING.yml 2019-05-30 17:42:15 +01:00
gingerBill caf9bc6be9 Pedantic conversions on query data 2019-05-29 16:59:28 +01:00
gingerBill 654740d5b1 Fixes to ABI 2019-05-29 16:49:26 +01:00
gingerBill b894e2b378 Fix bit set size with 128-bit integers 2019-05-28 20:57:02 +01:00
gingerBill c40acd008e Add i128/u128 support for bit sets 2019-05-28 20:53:56 +01:00
gingerBill 3d2279fba0 Support 128-bit integers i128 u128 2019-05-28 20:27:45 +01:00
gingerBill 2b080dbbc2 sync_atomic_* make most ordering parameters compile-time constant 2019-05-28 15:57:06 +01:00
gingerBill 9cadd58465 Improve tokenizer slightly 2019-05-28 14:44:32 +01:00
gingerBill 65e9b4d5f0 Update parsers 2019-05-28 12:55:55 +01:00
gingerBill fb3d73cb20 Make core library use a..<b rather than doing a..b-1 2019-05-28 12:52:20 +01:00
gingerBill 222941727f Add ..< operator for ranges; Add extra checking for bit set assignments 2019-05-28 12:45:20 +01:00
gingerBill 5697d6df74 -go-to-definitions (OGTD file format) 2019-05-26 15:16:45 +01:00
gingerBill 426c1ed6f4 -compact flag for 'odin query' 2019-05-25 20:28:49 +01:00
gingerBill 458ec5922e odin query
Output .json file containing information about the program
2019-05-25 20:24:19 +01:00
gingerBill f5fdd031f9 Fix polymorphic procedure return by pointer values #374 2019-05-19 10:45:27 +01:00
gingerBill ceb58ae04f Change import name rules 2019-05-19 10:01:35 +01:00
gingerBill 868603f617 Merge pull request #375 from Zilarrezko/master
make_builder function now properly uses given allocator
2019-05-19 09:55:03 +01:00
Zilarrezko d2faa9bef1 make_builder function now properly uses given allocator 2019-05-18 18:57:34 -07:00
gingerBill b1663a14e9 Add an error for C-style pointer selector expressions using '->' when parsing 2019-05-09 22:59:17 +01:00
gingerBill 3fc60930e6 Fix constant representability rules 2019-05-09 22:46:50 +01:00
gingerBill 665734f04f Fix package odin/parser 2019-05-09 16:35:35 +01:00
gingerBill 16f3bc2c0b Allow comparisons with bit field values 2019-05-09 13:18:57 +01:00
gingerBill 71a733e3b5 Allow booleans to be assigned to a 1-bit bit field value 2019-05-09 13:04:15 +01:00
gingerBill a66612e8ae Remove test code 2019-05-09 11:07:26 +01:00
gingerBill 00c0ce45b3 Fix bug with clamp 2019-05-06 18:29:22 +01:00
gingerBill ab0afa548b Fix ||= and &&= 2019-05-06 11:32:35 +01:00
gingerBill ea1690b7a1 Improve type inference for variadic parameters 2019-05-04 14:01:04 +01:00
gingerBill a5ff983266 Fix parapoly related bugs #370 2019-05-04 13:11:56 +01:00
gingerBill a46a1f5f34 Minor change to bit_field assignment rules 2019-05-04 13:02:15 +01:00
gingerBill 40135cbc66 Add float64_range and float32_range to package math/rand 2019-04-28 20:35:14 +01:00
gingerBill c61fd3a70a Modify type_set_offsets to patch minor bug 2019-04-28 20:34:51 +01:00
gingerBill 45fbc4e8c5 Add #load to package odin/parser 2019-04-21 22:36:52 +01:00
gingerBill 9ce8f124bb Slight change to determine_path_from_string rules 2019-04-20 16:52:09 +01:00
gingerBill 63bbb9b62f Change the file name rules for imports (use / rather than \ on windows) 2019-04-20 16:47:28 +01:00
gingerBill 56c4039e72 #load directive (request from #368) (Basic implementation) 2019-04-20 15:05:35 +01:00
gingerBill 0755dfbd5d Merge branch 'master' of https://github.com/odin-lang/Odin 2019-04-19 11:39:12 +01:00
gingerBill 2780f82f30 Fix is_operand_value to support more addressing modes 2019-04-19 11:39:01 +01:00
Jeroen van Rijn 5dcb5c2ba3 Merge pull request #367 from kevinw/fix-json-parsing
Fix some JSON parsing bugs.
2019-04-06 16:35:46 +02:00
Jeroen van Rijn 9d552d04ea Merge pull request #358 from kevinw/master
Fix some -vet warnings; change import to core:math/bits
2019-04-06 16:34:01 +02:00
Kevin Watters 88e1b93786 Fix som JSON parsing bugs.
- Single digit integer keys `{"a": 5}`
` Negative float keys `{"b": -42.0}`
2019-04-06 09:24:53 -04:00
Kevin Watters 62f5eb5bca Fix som JSON parsing bugs.
- Single digit integer keys `{"a": 5}`
` Negative float keys `{"b": -42.0}`
2019-04-06 09:19:09 -04:00
Kevin Watters 6ab471ff87 Merge branch 'master' of github.com:odin-lang/Odin 2019-04-06 08:41:56 -04:00
Jeroen van Rijn 155b138aa4 call_external_process cleanup 2019-04-05 13:18:50 +02:00
Jeroen van Rijn a730b04bf1 Add helpers to launch process and open website. 2019-04-05 13:02:49 +02:00
Kevin Watters 957e1e1f07 Merge branch 'master' of github.com:odin-lang/Odin 2019-04-01 09:34:25 -04:00
gingerBill 133f88406f The Proposal Process 2019-03-31 23:50:56 +01:00
gingerBill ecd2eacd75 Remove dead keywords; Fix min and max for enum types 2019-03-31 22:35:05 +01:00
gingerBill 2614830c69 Minor code organization change 2019-03-31 18:29:57 +01:00
Kevin Watters 381fbd3daf Merge branch 'master' of github.com:odin-lang/Odin 2019-03-31 12:03:22 -04:00
gingerBill dd9113786c Remove -keep-temp-files from the build.bat 2019-03-31 13:06:01 +01:00
gingerBill 1354f53d02 Remove derived from context; Fix parsing issue for typeid specializations in record parameters; Fix runtime printing of types 2019-03-31 11:58:54 +01:00
gingerBill 564e85ee29 Modify ir_generate_array name logic slightly 2019-03-31 11:22:27 +01:00
gingerBill ef04d13337 Use context for assert-based things. 2019-03-30 15:10:40 +00:00
gingerBill 68d4bde82f Overrideable stdin, stdout, stderr at the context level 2019-03-30 14:51:42 +00:00
gingerBill a019059975 Fix -vet for demo.odin 2019-03-30 10:52:53 +00:00
gingerBill 7580ec494b Disallow ambiguous singularly variadic polymorphic parameters #361 2019-03-30 10:43:53 +00:00
gingerBill a9b20c29b1 Fix slicing issue; Change path of math/bits in package json #363 2019-03-30 10:17:31 +00:00
Kevin Watters 76a2807b56 Remove unused import from demo.odin. 2019-03-26 11:20:49 -04:00
Kevin Watters 14ff561f6c Merge branch 'master' of github.com:odin-lang/Odin 2019-03-26 11:17:58 -04:00
gingerBill 1fd677b42e Remove *_remove from demo and use built-in versions 2019-03-25 21:29:21 +00:00
gingerBill 6b18b90222 Fix possible buffer overflows in package strconv 2019-03-25 21:26:23 +00:00
gingerBill 9e6d488063 Modify slice_expr_error_* logic to change depending on which parameters are passed 2019-03-25 21:20:12 +00:00
gingerBill 4a15689776 Remove bounds checks for slice expressions with both indices empty 2019-03-25 21:00:45 +00:00
gingerBill c785c3569f Fix runtime.*_expr_error error 2019-03-25 20:42:47 +00:00
Kevin Watters e6f9b4fb11 Fix some -vet warnings; change import to core:math/bits 2019-03-25 09:23:46 -04:00
gingerBill b978959fae Improve package strconv 2019-03-24 20:58:01 +00:00
gingerBill 8b09ab6fe7 Move core:bits to core:math/bits 2019-03-24 20:39:01 +00:00
gingerBill 2347dca9d9 Improve package math/rand 2019-03-24 20:36:39 +00:00
gingerBill 2ada90e094 Improve a tokenizer error message; Add extra tokens for in and notin for fun! 2019-03-24 19:12:41 +00:00
gingerBill a137a06b00 Allow implicit selectors to unions with only one enum variant 2019-03-24 12:14:45 +00:00
gingerBill b1684fe455 @(private) for foreign blocks; Improve foreign signature similarity rules 2019-03-24 11:58:26 +00:00
gingerBill 886054f0f8 Add error message for when trying to assign a type to a variable. 2019-03-22 13:55:29 +00:00
gingerBill 0e1cfa5a0a Disallow casting to and from cstring/pointers
TODO: get a better error message
2019-03-19 20:34:06 +00:00
gingerBill 400558abcd Fix fmt.println a rawptr causes access violation #356 2019-03-19 20:27:29 +00:00
gingerBill d75634ff5e Merge branch 'master' of https://github.com/odin-lang/Odin 2019-03-19 20:22:32 +00:00
gingerBill 0c04b9398a Fix bug with assigning certain integers to a bit_field #353 2019-03-19 20:22:25 +00:00
Brendan Punsky e3d1d1d85c Merge branch 'master' into master 2019-03-18 17:22:57 -04:00
Brendan Punsky b6ea7b7418 Fix temp allocation on linux 2019-03-18 17:19:21 -04:00
Brendan Punsky 7426f3b092 Fix null termination detection, win32 namespacing 2019-03-18 17:11:17 -04:00
Brendan Punsky 299c299dff Add linux support 2019-03-18 17:07:36 -04:00
Jeroen van Rijn 290c111206 Merge pull request #355 from mattt-b/master
Replace calls to deprecated string functions on linux
2019-03-18 15:27:07 +01:00
matt 314d5a778e Replace calls to deprecated string functions on linux 2019-03-18 07:13:52 -07:00
Jeroen van Rijn dc706d8a6b Vet CEL 2019-03-17 23:27:13 +01:00
gingerBill a6fb2dd587 Fix Erroneous redeclaration error with using import #354 2019-03-17 20:43:54 +00:00
gingerBill 4e93b70f8a Fix bit_field scoping bug 2019-03-17 14:48:32 +00:00
gingerBill 1eaa47ebae Fix using import behaviour - #352 2019-03-17 13:03:39 +00:00
gingerBill 3a31444656 Minor changes to fmt of auto deferencing 2019-03-16 11:00:37 +00:00
gingerBill f7efaf2ba2 fmt.printf support for pointer to container (one level deep) 2019-03-16 00:10:57 +00:00
gingerBill 14c6f2f258 Add extra pointer printing options to fmt.printf 2019-03-15 23:49:47 +00:00
gingerBill 231f3cc15a %h support in fmt.printf for hexadecimal floats 2019-03-15 23:22:05 +00:00
gingerBill 332e598357 %e and %g support in fmt.printf 2019-03-15 23:13:06 +00:00
gingerBill 716373836c Disallow attributes on alias declarations 2019-03-15 19:01:36 +00:00
gingerBill fdb60b2d51 Improve package strings 2019-03-15 18:30:39 +00:00
gingerBill 885c5dc8b7 Fix issue with deferred_* attributes 2019-03-15 16:39:49 +00:00
gingerBill 394baa9ddd Merge branch 'master' of https://github.com/odin-lang/Odin 2019-03-15 15:41:15 +00:00
gingerBill 3d86fc2f2f Minor adjustments 2019-03-15 15:41:06 +00:00
Jeroen van Rijn 61b07335d8 Fix build error on !Windows. 2019-03-15 07:37:20 +01:00
gingerBill 712744ef36 Fix ir_copy_value_to_ptr usage in ir_emit_call #350 2019-03-14 23:41:48 +00:00
gingerBill dbcd49acfc Add -pdb-name for custom names of PDBs 2019-03-14 23:26:32 +00:00
gingerBill 291bf0c143 Fix #raw_union bug caused by typo #349 2019-03-14 23:25:55 +00:00
Brendan Punsky e398c074db Fix typo 2019-03-13 18:37:01 -04:00
Brendan Punsky eadb66c9ef Merge branch 'master' into master 2019-03-13 16:45:46 -04:00
Brendan Punsky 9d7e1c17cc Update kernel32.odin
Add Win32 path functions
2019-03-13 16:44:11 -04:00
Brendan Punsky 775b544326 Update path_windows.odin
Updated `long`, `short`, `full`, `current` to be cleaner, use `win32` for platform procs, and `strings.trim_null` to clean resulting strings
2019-03-13 16:40:26 -04:00
Brendan Punsky da26e14959 Update path.odin
Fix allocator usage for `rel_current` and `rel_between`
2019-03-13 16:38:02 -04:00
gingerBill bdab5e00da Minor code clean up 2019-03-11 19:52:40 +00:00
gingerBill e781056df1 Merge branch 'master' of https://github.com/odin-lang/Odin 2019-03-11 09:32:24 +00:00
gingerBill b08d944c33 Fix typo in demo.odin 2019-03-11 09:32:15 +00:00
Jeroen van Rijn 4f24f1172e Stylistic improvements to new comdlg helpers. 2019-03-09 13:48:48 +01:00
Jeroen van Rijn 4446a1431a Merge pull request #348 from Kelimion/master
Add win32.get_cwd for current working directory and convenience functions for open + save dialogs.
2019-03-09 12:51:14 +01:00
Jeroen van Rijn 090937f8af Add convenience functions for open + save dialogs. 2019-03-09 12:45:17 +01:00
Jeroen van Rijn d852b0c948 Add win32.get_cwd to return the current working directory 2019-03-09 11:08:50 +01:00
gingerBill 007a7989b8 Add implicit selector expression examples to demo.odin 2019-03-06 20:06:37 +00:00
gingerBill 5c04800831 Add type inference to index expressions for maps 2019-03-06 20:01:46 +00:00
gingerBill c634d4a96d Using implicit selector expressions in the core library 2019-03-06 19:13:50 +00:00
gingerBill c67ea97845 Add implicit selector expressions for in/notin 2019-03-06 19:08:37 +00:00
gingerBill 15d3f4c190 Allow implicit selector expressions in switch statements 2019-03-06 16:23:50 +00:00
gingerBill 1b3ec66fa2 Merge branch 'master' of https://github.com/odin-lang/Odin 2019-03-06 16:19:55 +00:00
gingerBill ad3b6ab718 Implicit Selector Expressions: .A 2019-03-06 16:19:47 +00:00
Jeroen van Rijn 8c618225bf Merge pull request #347 from Kelimion/master
Fix typo in `cel` tokeniser.
2019-03-04 13:46:51 +01:00
Jeroen van Rijn 1f5ab0b5f1 Fix typo in cel tokeniser. 2019-03-04 13:41:47 +01:00
gingerBill 1652d5033b Merge branch 'master' of https://github.com/odin-lang/Odin 2019-03-03 12:09:06 +00:00
gingerBill 9b4b20e8b1 package dynlib 2019-03-03 12:08:26 +00:00
Jeroen van Rijn 8fb8b5ed7e Merge pull request #346 from Kelimion/fix-issue-345
Fix #345: panic when using enum as map key
2019-03-03 13:00:00 +01:00
Jeroen van Rijn 7bd86bb3ec well, that was a stupid copy/paste bug 2019-03-02 13:24:11 +01:00
Jeroen van Rijn b6d6eb6ae2 Fix #345: Panic when using enum as map key
Also add a little map demo.
2019-03-02 13:21:01 +01:00
Jeroen van Rijn a126d2ba16 Merge remote-tracking branch 'upstream/master' into fix-issue-345 2019-03-02 12:31:45 +01:00
Jeroen van Rijn 6faab8e47a Fix #345: panic when using enum as map key 2019-02-26 13:51:56 +01:00
gingerBill 76a6757ee9 Add os.file_size_from_path 2019-02-25 18:03:44 +00:00
gingerBill 0c8746ada6 Add support for custom keywords in core:odin/* packages 2019-02-25 12:41:43 +00:00
gingerBill a0c81c79ad Fix bugs: Array Literals with constant elements; IR printing of raw procedure types 2019-02-24 10:30:58 +00:00
gingerBill cdfaa643cc Reimplement -collection; remove static from Odin tokenizer/parser in core library 2019-02-23 23:30:03 +00:00
gingerBill 989cc893ef FIX TYPO! 2019-02-23 23:25:46 +00:00
gingerBill 2878cd8241 New build flag: -define:foo=123 2019-02-23 23:21:27 +00:00
gingerBill a9ab90bd24 Make static an attribute rather than a keyword prefix 2019-02-23 22:17:27 +00:00
gingerBill e551d2b25e Replace foreign export {} with @export 2019-02-23 21:39:47 +00:00
gingerBill 38ae2e9efa Allow basic arithmetic operations for vectors 2019-02-23 18:05:41 +00:00
gingerBill 684945ea57 Fix calling conventions for simd vector types 2019-02-23 17:45:30 +00:00
gingerBill 4c51384ad6 intrinsics.vector type (Experimental) 2019-02-23 16:44:16 +00:00
gingerBill 64bd884d94 Add "none" calling convention 2019-02-23 14:42:44 +00:00
gingerBill a07232ea63 Fix missing break in switch statement for deferred_in in the IR 2019-02-23 14:11:48 +00:00
gingerBill 79b585ada8 Add minor additions to mem, sync, and sys/win32 2019-02-21 21:45:33 +00:00
gingerBill f917935f9d Disallow compound literals for struct #raw_union (fix) 2019-02-19 10:04:36 +00:00
Brendan Punsky 222e5c8ae9 Delete path_linux.odin
Delete useless path_linux.odin stub
2019-02-14 20:25:13 -05:00
gingerBill dbd0638853 Fix untyped ternary string IR conversion 2019-02-14 11:11:05 +00:00
Brendan Punsky 772dc47f55 Oops, I forgot to stage core/strings/strings.odin 2019-02-12 17:30:46 -05:00
Brendan Punsky 0777351482 Added path lib "core:path", as well as single- and multiple-splitset string split proc variants to "core:string" 2019-02-12 17:27:54 -05:00
gingerBill 53d8216311 Reorganize package mem 2019-02-10 22:15:34 +00:00
gingerBill 6a0c3d5599 Add default_parser procedure to package odin_parser 2019-02-10 22:05:18 +00:00
gingerBill 9647fb2a4b Add Stack and Small_Stack allocators to package mem 2019-02-10 22:04:58 +00:00
gingerBill 42f936742e Add extra dead code elimination 2019-02-10 21:23:02 +00:00
gingerBill e2d4667639 Fix data layout issue on Windows; Remove unused loads in SSA 2019-02-10 20:51:19 +00:00
gingerBill b74d828af7 Merge branch 'master' of https://github.com/odin-lang/Odin 2019-02-09 22:34:37 +00:00
gingerBill e16409f88a Fix package odin_parser bugs 2019-02-09 22:34:27 +00:00
thebirk 6571f07c7e Fixed typo in copy_sign_f64. 2019-02-08 12:58:30 +01:00
gingerBill 4b7a09b92e Merge branch 'master' of https://github.com/odin-lang/Odin 2019-02-06 22:45:04 +00:00
gingerBill 26fb1fa18c Fix lead_comment issue is package odin_parser 2019-02-06 22:44:54 +00:00
Mikkel Hjortshøj 24c43d33bb Export LLVM path on macOS (CI) 2019-02-06 19:08:32 +01:00
Mikkel Hjortshøj 7343f0c7ff Fix recursive variable in makefile on macOS 2019-02-06 18:56:02 +01:00
Mikkel Hjortshøj 3c8cda514b Fix makefile for macOS 2019-02-06 18:49:21 +01:00
gingerBill bc954df80e Merge branch 'master' of https://github.com/odin-lang/Odin 2019-02-06 16:07:32 +00:00
gingerBill e1ae359a77 Replace redundant code 2019-02-06 16:06:48 +00:00
Mikkel Hjortshoej c9602953aa last fixes to bats and README 2019-02-06 15:53:40 +01:00
Mikkel Hjortshoej 0185b43c2f Create CI files 2019-02-06 15:53:40 +01:00
gingerBill bc5c37ebb1 Extra checks to reduce mem.zero calls 2019-02-06 13:47:52 +00:00
gingerBill 0133dd9034 Merge branch 'master' of https://github.com/odin-lang/Odin 2019-02-06 13:33:52 +00:00
gingerBill a194aa5a9e Minimize mem.zero use 2019-02-06 13:33:31 +00:00
gingerBill 766f3e259f Merge pull request #334 from odin-lang/ThisDrunkDane-patch-1
Add issue templates
2019-02-05 22:21:27 +00:00
Mikkel Hjortshøj 6092cc0497 Add issue templates 2019-02-05 21:19:56 +01:00
gingerBill fa5d00521b Remove inline from many of the mem.* procedures 2019-02-04 12:15:51 +00:00
gingerBill d1e29400d3 Merge pull request #331 from thebirk/fix-out-linux
Fixed macOS not compiling
2019-02-02 23:14:26 +00:00
gingerBill 2dc7aaec82 Merge pull request #332 from thebirk/fix-big-string-printing
Fix #322, now correctly printing big strings.
2019-02-02 23:14:08 +00:00
thebirk b7242f9d4b Fix #322, now correctly printing big strings. 2019-02-02 00:11:41 +01:00
thebirk 7ea7fc10db Fixed macOS not compiling. 2019-02-01 15:33:27 +01:00
gingerBill 141da818ba Merge pull request #330 from thebirk/fix-out-linux
Fixed -out dropping extension on linux. Issue #305
2019-02-01 14:25:36 +00:00
thebirk dc3d62d437 Fixed -out dropping extension on linux. 2019-02-01 15:12:20 +01:00
gingerBill dee28d998f Allow for @indent for attributes that don't require any parameters; Add -ignore-unknown-attributes 2019-01-30 14:24:14 +00:00
gingerBill 96ef6aa7f3 Merge pull request #327 from Tetralux/tet/pass-args-to-run
Provide a way to pass arguments to compiled executable during 'odin run program.odin'.
2019-01-29 22:12:01 +00:00
gingerBill 238a40321a inline certain mem.* procedures 2019-01-29 22:08:48 +00:00
gingerBill 1aea59a0fc Fix typo in parser.cpp 2019-01-29 21:53:36 +00:00
gingerBill c6dee52abe Finish up package odin_parser 2019-01-29 21:53:16 +00:00
Tetralux 1e180d611d Allow 'odin run program.odin -- <args-for-program.exe> 2019-01-28 17:58:48 +00:00
gingerBill e452765d28 Patch minor IR bug 2019-01-28 12:13:37 +00:00
gingerBill 2b80683fc7 Vet odin/* packages 2019-01-27 19:01:33 +00:00
gingerBill 5f840ea2fc package odin_parser 2019-01-26 20:17:03 +00:00
gingerBill c72427fd1e package odin_parser 2019-01-26 20:14:06 +00:00
gingerBill 44b959648c Pass any and union "by pointer" to make the tag a pointer 2019-01-26 20:13:43 +00:00
gingerBill a96bf08266 Fix tokenizer.odin bugs 2019-01-24 21:40:09 +00:00
gingerBill ebaf48c07d Fix subtyping rules for heavily nested using in structs 2019-01-24 21:17:30 +00:00
gingerBill c197a27185 Merge branch 'master' of https://github.com/odin-lang/Odin 2019-01-24 15:53:27 +00:00
gingerBill 5ccccf8816 Add package odin/token; package odin/tokenizer 2019-01-24 15:53:17 +00:00
gingerBill 345e790f52 Remove dead code 2019-01-24 15:52:51 +00:00
gingerBill fd529b97be Merge pull request #324 from Tetralux/tet/ptr-endianness
Fix assert when printing IR of pointer with endianness
2019-01-18 14:24:19 +00:00
Jeroen van Rijn be1a3488a4 Initial support for GetVersionExA 2019-01-18 13:37:40 +01:00
Tetralux 46c610d6e5 Fix printing IR of integer as a pointer with endianness.
When converting an integer value into a pointer and writing out the IR
for it in 'ir_print_exact_value', 'is_type_integer_endian_{little,big}'
did not correct handle being asked about pointer types.

They now reply with whether the endianness of 'uintptr' matches the
endianness being asked about.
2019-01-16 17:22:25 +00:00
gingerBill db2eff6847 Fix typo in json/parser.odin 2019-01-14 20:44:27 +00:00
gingerBill e047d9eb5e Update package json parser to store the end position on the values 2019-01-14 15:51:52 +00:00
gingerBill 3113e8c892 Minimize buffer size for write_u64 and write_i64 2019-01-13 21:40:18 +00:00
gingerBill 19e37c852e Change deferred_* scoping behaviour for if 2019-01-13 20:51:26 +00:00
gingerBill 8fc24fd6f2 Replace deferred with deferred_none, deferred_in, deferred_out 2019-01-13 19:34:08 +00:00
gingerBill 493f11521d Check for _ for import names too 2019-01-13 17:44:38 +00:00
gingerBill 3363e2c199 Change import name determination rules
Use custom name if given, then directory name, then the package name
2019-01-13 11:54:25 +00:00
gingerBill cf94d1735d Add extra explicit entity usage 2019-01-13 11:24:03 +00:00
gingerBill d9245a6af3 Update Makefile to reflect build.sh 2019-01-13 11:19:01 +00:00
gingerBill d453b9a5b1 Fix checking _ constant declarations with a procedure 2019-01-10 11:22:52 +00:00
gingerBill 5af20aa467 Make encoding/json use []byte rather than string 2019-01-07 23:08:38 +00:00
gingerBill cd2c4c02e1 Merge pull request #320 from thebirk/add-diff-to-time
Added diff() to core:time.
2019-01-07 15:52:33 +00:00
gingerBill 6c21e99832 json.marshal 2019-01-06 23:32:50 +00:00
gingerBill 08598b9425 Support NaN and Infinity for JSON5 2019-01-06 22:25:02 +00:00
gingerBill 6295f6747f strings.write_quoted_string 2019-01-06 22:16:14 +00:00
gingerBill 64f84ef9a3 fmt.printf("%q", str); (quotes strings) 2019-01-06 22:11:45 +00:00
gingerBill d1b9f3ac74 package json; JSON5 support 2019-01-06 21:48:13 +00:00
gingerBill d732a51587 Add json.is_valid file 2019-01-06 20:44:52 +00:00
gingerBill 9487f8c92e Add json.is_valid 2019-01-06 20:44:39 +00:00
gingerBill c5def60224 Begin work on package json 2019-01-06 20:37:12 +00:00
thebirk ca2220214e Added diff() to core:time. 2019-01-06 19:40:57 +01:00
gingerBill 6e6a053823 Add strings.destroy_builder 2019-01-06 17:59:42 +00:00
gingerBill 686e0ef3d1 Merge pull request #319 from mattt-b/master
Vet time_linux
2019-01-06 15:22:21 +00:00
gingerBill 594238a86c Reorganize fmt and strings; Replace fmt.String_Buffer with strings.Builder 2019-01-06 14:41:42 +00:00
matt c60766f8e6 Vet time_linux 2019-01-06 05:25:27 -07:00
gingerBill 5acea1bceb Source_Code_Location.hash; %#v printing for Source_Code_Location; allow typeid for map keys 2019-01-05 15:56:47 +00:00
gingerBill aac643f476 Remove debug printing text 2019-01-05 11:30:13 +00:00
gingerBill 37edbfeb74 Add missing types for min dep 2019-01-05 11:18:43 +00:00
gingerBill 51da3e469b Add win32 cursor stuff 2019-01-05 11:16:14 +00:00
gingerBill 9156af2bab Add missing types to minimum dependency checking 2019-01-05 11:15:23 +00:00
gingerBill 3a18ae3978 Remove alignment experiment 2019-01-04 17:39:20 +00:00
gingerBill f294c1adee ir_print: Ignore load's align
(experimental idea as it might not be needed)
2019-01-04 10:39:39 +00:00
gingerBill bb93a8b131 Fix TODO ParameterValue_Location 2019-01-04 10:19:39 +00:00
gingerBill 5bfe5ad82e Remove unused directive 2019-01-03 12:21:11 +00:00
gingerBill dd28fe6e82 Update CEL 2019-01-03 00:12:24 +00:00
gingerBill cda0f4d8f3 Fix using struct cycle check 2019-01-02 23:55:21 +00:00
gingerBill 0546b5c218 Add sys/win32/comdlg32.odin 2019-01-02 20:51:48 +00:00
gingerBill 61a3e50d1b Reorganize sys/win32 2019-01-02 19:17:27 +00:00
gingerBill 75aeb02c39 Merge pull request #315 from thebirk/fix-bud-for-lazy-bill
Fixed bug for Bill because he is a lazy boi.
2019-01-02 15:20:35 +00:00
thebirk a32f024d94 Fixed bug for Bill because he is a lazy boi. 2019-01-02 16:18:55 +01:00
gingerBill 37d993c417 Merge pull request #314 from thebirk/int_from_arg_fix
Fixed int_from_arg not consuming argument.
2019-01-02 15:01:45 +00:00
thebirk bcbb59dc11 Fixed int_from_arg not consuming argument. 2019-01-02 15:56:35 +01:00
gingerBill c1ec45dc0a Update sys/win32; Add Menu stuff 2019-01-01 20:18:48 +00:00
gingerBill 0778d18bc7 Fix using with bit_field 2019-01-01 15:11:54 +00:00
gingerBill d7e9b8d374 Update README.md 2019-01-01 14:06:15 +00:00
gingerBill f647187e53 Fix defer on branching with new scoping rules 2019-01-01 11:59:09 +00:00
gingerBill 9dabbc2c95 Add entity use when using is applied to a variable declaration 2018-12-31 16:43:58 +00:00
gingerBill 4167168c63 Fix vetting 2018-12-31 16:37:27 +00:00
gingerBill aa156e4bfc Vet demo.odin 2018-12-31 15:51:53 +00:00
gingerBill 1c9656aedb Vet core library 2018-12-31 15:50:49 +00:00
gingerBill 8b2f902f3d Fix parsing issue with stray } and case at the file scope 2018-12-31 15:20:47 +00:00
gingerBill bbece7e910 Remove some unneeded zero emits 2018-12-31 13:00:55 +00:00
gingerBill e5f188241c Move error handling for bounds checking into separate procedures (eliminate caching issues) 2018-12-31 11:41:56 +00:00
gingerBill 6d3203c11b Remove useless assertion in find_import_path 2018-12-30 15:40:45 +00:00
gingerBill 5ba3d90893 Fix os_windows.odin bugs 2018-12-30 14:43:39 +00:00
gingerBill 894f267bbf Merge pull request #311 from mattt-b/master
Fix bugs and inconsistencies with linux versions of os package
2018-12-30 09:50:00 +00:00
matt e084799b31 Fix bugs and inconsistencies with linux versions of os package 2018-12-30 02:06:41 -07:00
gingerBill 3ba3421f5f Fix static procedure name mangling 2018-12-29 19:57:25 +00:00
gingerBill 2bbad5903f Add static to fix_advance_to_next_stmt 2018-12-28 13:32:59 +00:00
gingerBill a240a3d146 static variable declarations (Experimental) 2018-12-28 13:31:06 +00:00
gingerBill 775f1e2c95 Fix default parameter assignment checking 2018-12-28 11:20:31 +00:00
gingerBill 7c982b6e10 min & max for types 2018-12-27 12:12:14 +00:00
gingerBill cc14180e9d Update README.md 2018-12-27 10:51:15 +00:00
gingerBill b2d40680c8 Fix join and concatenate to use the supplied allocator 2018-12-26 19:38:05 +00:00
gingerBill 8662df2b7f Update package strings 2018-12-26 19:33:56 +00:00
gingerBill 6abbc9f1b5 Merge pull request #310 from mattt-b/master
Fix os.open on linux/osx
2018-12-26 17:37:20 +00:00
gingerBill 66a9fde12c Remove #[...] attribute syntax.
(Not really worth the change)
2018-12-26 16:23:25 +00:00
gingerBill eb5af2876a Support #[...] as an alternative attribute syntax
(Experimentation between `@()` and `#[]`)
2018-12-26 12:19:12 +00:00
gingerBill 1f2fdddc6d Support #! comments 2018-12-26 12:00:16 +00:00
matt 0bcf53b513 Fix os.open on linux/osx 2018-12-26 04:31:12 -07:00
gingerBill 956dd26aa0 Fix race condition; Change for in addressing mode 2018-12-24 16:11:24 +00:00
gingerBill b504d6e12a notin operator 2018-12-21 11:34:15 +00:00
gingerBill b4e83a430a Add card procedure to measure cardinality of a bit_set 2018-12-21 10:31:10 +00:00
gingerBill e3d7e6f76a Fix typo in modf_f32 2018-12-20 18:11:27 +00:00
gingerBill 5c3dc30dc0 More correct floor and ceil procedures. 2018-12-20 10:54:56 +00:00
gingerBill c508e46ed9 Merge pull request #308 from hasenj/master
fix missing declaration in osx
2018-12-18 13:05:44 +00:00
Hasen Judy 9d85f236b8 fix missing declaration in osx 2018-12-18 21:47:23 +09:00
gingerBill 3a05a2e562 Fix not for bit sets 2018-12-17 13:12:48 +00:00
gingerBill 68384a452f Fix scoping determination for IR 2018-12-17 11:36:15 +00:00
gingerBill 34b6486361 Fix constant out of bounds bug 2018-12-15 22:30:52 +00:00
gingerBill 1ce90b2166 Remove weird bit_set shorthand; Add extra type hinting 2018-12-15 21:46:27 +00:00
gingerBill 9d6666f333 Disallow casting between cstring and []u8 2018-12-14 21:58:12 +00:00
gingerBill d29335ecec Add deferred procedure associations to demo.odin 2018-12-14 21:17:32 +00:00
gingerBill 95873e66ab deferred procedure attribute 2018-12-14 21:05:02 +00:00
gingerBill b7eebe5d00 Fix polymorphic record types with constant value parameters 2018-12-14 18:36:06 +00:00
gingerBill 57d4333ed3 Fix polymorphic procedure generation with debug information 2018-12-14 15:45:14 +00:00
gingerBill 26f11f12ab Fix polymorphic type parameter argument count checking #298 2018-12-14 15:05:26 +00:00
gingerBill 0b6fc19fb0 Allow polymorphic cast on fields with _ #302 2018-12-14 14:57:04 +00:00
gingerBill f2dae7023f Fix polymorphic cast with pointers #303 2018-12-14 14:53:31 +00:00
gingerBill f36775ffd8 Add endian specific integers to ir_debug_encoding_for_basic #307 2018-12-14 14:46:26 +00:00
gingerBill 8702a8a477 Merge pull request #299 from CaptainKraft/master
Add the missing INVALID_HANDLE so that the demo will build and run on Linux
2018-12-14 14:44:34 +00:00
gingerBill 47e31c3de8 Remove return value from append 2018-12-14 14:40:27 +00:00
gingerBill b1d0d82254 Fix #raw_union bug #306 2018-12-14 14:38:38 +00:00
gingerBill 542e524a87 Merge branch 'master' of https://github.com/odin-lang/Odin 2018-12-14 14:35:48 +00:00
gingerBill b54c35639b Fix issue with mixture of named and unnamed parameters for a struct literal 2018-12-14 14:35:23 +00:00
CaptainKraft cfcb0514bf Add the missing INVALID_HANDLE so that the demo will build and run on Linux. 2018-12-09 20:52:03 -06:00
Mikkel Hjortshoej 1a6b7f9945 set time_linux IS_SUPPORTED to true 2018-12-08 21:12:01 +01:00
Mikkel Hjortshoej 03957cee64 Merge branch 'log_pr' 2018-12-08 21:08:27 +01:00
Jeroen van Rijn 1584260886 Add Linux support for core:time
In addition to sleep() and now(), it also defines nanosleep(), boot_time() and seconds_since_boot()
2018-12-08 20:39:33 +01:00
Mikkel Hjortshoej a565d842da Copy instead of loop 2018-12-08 16:12:20 +01:00
Mikkel Hjortshoej 411d1450b0 Add timestamp support using the new core:time 2018-12-08 16:02:33 +01:00
Mikkel Hjortshoej 984fa1c672 remove ident from logger struct 2018-12-08 15:32:53 +01:00
Mikkel Hjortshoej 12c810f85d Add a file-, console- and multi-logger 2018-12-08 15:32:53 +01:00
gingerBill 3bf01c8498 package time (windows only at the moment) 2018-12-08 14:32:00 +00:00
gingerBill d05837ab6d Labels for block and if statements (break only) 2018-12-08 14:12:52 +00:00
gingerBill 4369a1714e Fix automatic subtype casting bug 2018-12-08 13:31:25 +00:00
gingerBill 13f084a219 Fix foreign export #294 2018-12-08 11:45:08 +00:00
gingerBill 4205f0f0b1 Remove dummy testing code 2018-12-08 11:26:13 +00:00
gingerBill bd62bceca6 Fix BigInt normalization issue #293 2018-12-08 11:25:35 +00:00
gingerBill ff6ec860b3 Fix typo 2018-12-08 11:06:32 +00:00
gingerBill 2bf60d3337 Merge pull request #291 from dimenus/master
fixed typo in 'GetMonitorInfoA' & added additional window styles
2018-12-08 11:05:59 +00:00
dimenus f288614eaf style fixes & PR changes 2018-12-06 11:44:59 -06:00
dimenus 9761d54c24 added win32 vk codes 2018-12-05 14:37:47 -06:00
dimenus 3794914478 fixed typo in 'GetMonitorInfoA' & added additional window styles 2018-12-05 11:13:43 -06:00
gingerBill 3e11b4fe1e Reorganize decl attribute code 2018-12-04 21:02:12 +00:00
gingerBill 50c3f4d74e Add package encoding/cel 2018-12-03 20:26:10 +00:00
gingerBill 304c7594cd Ignore ir_emit_byte_swap for constant values 2018-12-02 20:59:08 +00:00
gingerBill d02b050850 Fix typos for OS X debug builds 2018-12-02 19:39:21 +00:00
gingerBill 17b0e3a1a1 Fix bit sets with custom endian underlying type 2018-12-02 19:27:42 +00:00
gingerBill 28583bfff8 Change procedure group syntax from proc[] to proc{}; deprecate proc[] (raises warning currently) 2018-12-02 18:01:03 +00:00
gingerBill b2df48dadb Fix typo for little endian integers 2018-12-02 16:14:57 +00:00
gingerBill 04a853c6fe Fix double declarations of bswaps in LLVM IR 2018-12-02 16:02:00 +00:00
gingerBill 84f0c975b5 Merge branch 'master' of https://github.com/odin-lang/Odin 2018-12-02 15:54:04 +00:00
gingerBill 00161023cd Endian specific integers: e.g. i32 i32le i32be 2018-12-02 15:53:52 +00:00
gingerBill 7f063eb5e7 Add new demonstration for Packages, Bit Sets, and cstring 2018-12-02 13:18:55 +00:00
gingerBill 784c48c9e3 Redefine how union tag size is calculated to match alignment of the union 2018-11-29 23:00:16 +00:00
gingerBill 008d8f25c8 Fix assertion on union assignment in compound literal 2018-11-29 22:50:08 +00:00
gingerBill 7ffcf34dca Modify how custom alignment is printed for LLVM IR 2018-11-29 22:47:08 +00:00
gingerBill f3a4904f21 Hack: union compound literal fix 2018-11-29 22:23:30 +00:00
gingerBill 3aec78b1d4 Lock on possible race condition in parser 2018-11-29 20:27:48 +00:00
gingerBill a3e6e8d304 Allow single field struct #raw_union 2018-11-29 19:46:45 +00:00
gingerBill a747c03f29 Fix #complete switch on pointers to unions #286 2018-11-29 18:36:45 +00:00
gingerBill 2301ae157c Fix recursive loop bug for is_type_polymorphic 2018-11-28 16:47:20 +00:00
gingerBill d3c7d6d485 Fix #284 2018-11-26 10:55:15 +00:00
gingerBill 9b063ad9a3 Fix poly proc determination by cloning the signature node 2018-11-25 17:57:49 +00:00
gingerBill c2f9bf489e Fix debug information for entities without an associated identifier 2018-11-25 17:31:53 +00:00
gingerBill e496b95881 Subset and superset operators for bit_set: < <= > >= 2018-11-25 16:19:17 +00:00
gingerBill 444f4f446a -vet flag to do basic vetting of code 2018-11-25 14:14:58 +00:00
gingerBill 41ad896f3f Update README.md 2018-11-25 11:21:11 +00:00
gingerBill 0a4b88f9a6 Fix Issue with referencing a polymorphic struct in another package referencing itself #283 2018-11-25 10:35:49 +00:00
gingerBill 4c2f03b1f2 Fix compile time bounds check test 2018-11-23 10:38:17 +00:00
gingerBill 52dcaeb1e9 Fix transmute with cstring and integers 2018-11-22 20:59:24 +00:00
gingerBill f96fbc94c8 v0.9.0 Release 2018-11-22 10:25:01 +00:00
gingerBill bb62bed981 Remove assert that should have never been there 2018-11-22 09:53:08 +00:00
gingerBill bc6b8c5332 Remove dead code 2018-11-22 09:52:25 +00:00
gingerBill 6ab6447791 Fix is_type_polymorphic infinite recursion bug 2018-11-22 09:41:08 +00:00
gingerBill f61c4715c1 Allow opaque to be polymorphic 2018-11-17 10:08:06 +00:00
gingerBill 3061bc8478 Fix error with polymorphic structs #279 2018-11-17 10:05:35 +00:00
gingerBill d035d48c8e Fix issue #280 2018-11-17 09:45:52 +00:00
gingerBill b55b1ffe14 opaque keyword and type 2018-11-11 17:08:30 +00:00
gingerBill 620d5d34f7 Fix issue with complication of -debug that is caused sometimes due to lambda procedures. 2018-11-11 11:44:55 +00:00
gingerBill f9654b6c36 Fix package usage with when on import #278 2018-11-07 16:11:14 +00:00
gingerBill 6659ceb551 Allow comparisons of cstring; Add resize 2018-10-31 10:04:30 +00:00
gingerBill 5aa591d884 Fix debug info issue 2018-10-29 22:16:43 +00:00
gingerBill efe91b1f91 Disable debug info for bit fields 2018-10-29 18:10:44 +00:00
gingerBill 7c99884afb Fix CompositeType for zero length arrays 2018-10-29 12:52:41 +00:00
gingerBill dfd7a194ed Fix big int shifts of 0 2018-10-28 09:32:59 +00:00
gingerBill 2ddb27869b Built-in procedure #defined 2018-10-27 18:44:28 +01:00
gingerBill 5c608b01ba Place optimization level flag in condition again; -memcpyopt -die only in non-debug builds 2018-10-24 10:19:01 +01:00
gingerBill 2bd85e764e Merge pull request #260 from lachsinc/master
[WIP] Provide llvm with more debug info (for Visual Studio debugger support)
2018-10-24 09:40:05 +01:00
gingerBill 822e4894f2 Minor logic change for reserved package names 2018-10-20 21:19:40 +01:00
gingerBill ce2e23849e Fix context initialization 2018-10-20 16:34:56 +01:00
gingerBill 099995e7dd Add basics for context-based Logger 2018-10-20 13:02:30 +01:00
gingerBill 72f4186b21 Fix atomic.odin 2018-10-20 12:55:48 +01:00
gingerBill 3742d9e7e9 Move atomic intrinsics to the new built-in package intrinsics 2018-10-20 10:44:02 +01:00
gingerBill 4ac1218bf8 sync atomics "wrapper" procedures 2018-10-17 21:43:05 +01:00
gingerBill b171cc41e6 __atomic_* "intrinsics" using LLVM instructions 2018-10-17 21:16:01 +01:00
gingerBill efc3a9e69d Merge pull request #274 from hazeycode/fix/245
Use name of source file as output_name
2018-10-17 15:29:56 +01:00
gingerBill 307c58d908 Fix compilation error #272 2018-10-17 15:27:36 +01:00
Chris Heyes ae02e9c34a Use name of source file as output_name 2018-10-16 23:56:19 +01:00
Chris Heyes 139fa55c27 Merge pull request #1 from hazeycode/fix/272
Fix syntax error in core/os/os_linux.odin
2018-10-16 19:30:02 +01:00
Chris Heyes 562bb6e4c4 Fix syntax error in core/os/os_linux.odin 2018-10-15 21:24:42 +01:00
gingerBill ef2931d4a5 Remove AstTypeType 2018-10-13 14:07:00 +01:00
gingerBill 2d4aa2be6d Remove type as being a keyword 2018-10-13 14:04:34 +01:00
gingerBill 42b42db675 Add unimplemented and unreachable procedures; make os.exit a diverging procedure 2018-10-13 13:19:52 +01:00
gingerBill 73e9dbbf8c switch on typeid with type cases 2018-10-13 11:07:56 +01:00
gingerBill 0971a59493 Update runtime printing code 2018-10-11 18:19:29 +01:00
gingerBill 627c91124a Merge pull request #271 from Breush/267-bugfix-linux-heap-alloc-zero
Fixed heap alloc not allowing empty structs on Linux
2018-10-09 21:49:14 +01:00
Alexis Breust 4eba717281 Fixed heap alloc not allowing empty structs on Linux - Fixes #267 2018-10-09 08:34:48 +02:00
gingerBill 9623e5e032 Merge pull request #270 from Breush/263-bugfix-leading-zeros-count
Replaced __builtin_clz by long long version
2018-10-08 09:39:43 +01:00
Alexis Breust 805cc48f03 Replaced __builtin_clz by long long version - Fixes #268 2018-10-08 08:23:50 +02:00
lachsinc d894fb3708 Cleanup comments. 2018-10-06 09:09:12 +10:00
lachsinc b6ca913cff Cleanup hack as all types appear to be handled!.. 2018-10-06 08:58:39 +10:00
lachsinc 39db428603 Add complex debug info. 2018-10-05 17:10:58 +10:00
lachsinc 992502f03b Add debug info for proc ptrs. 2018-10-05 16:49:48 +10:00
lachsinc edc3a9392a Cleanup. 2018-10-05 15:03:13 +10:00
lachsinc f881ebd007 Cleanup unused AllProcs. 2018-10-05 14:51:08 +10:00
lachsinc 11ea03d2e8 Tuple debug info (untested). Generated locals now flow through debug info. 2018-10-05 14:33:39 +10:00
lachsinc 99b4d59f44 Add arg # for proc param locals. 2018-10-05 12:57:06 +10:00
lachsinc dfeefc5179 Fix dgb.declare using different location to it's associated instructions. 2018-10-05 12:46:53 +10:00
lachsinc ab46406f4d Fix debug info for unnamed aggregate types. 2018-10-05 12:27:36 +10:00
lachsinc 48ad147818 Cleanup; Move enums/globals di inside CompileUnit. Minor comment cleanup. 2018-10-04 14:09:17 +10:00
lachsinc 79d49f1955 Lexical block debug info. 2018-10-04 13:43:52 +10:00
lachsinc 1ccc8700e4 bit_set / bit_field debug info. 2018-10-02 10:06:48 +10:00
lachsinc f38d70a235 Cleanup. 2018-10-01 01:21:15 +10:00
lachsinc b37b7a0f72 Cleanup. 2018-10-01 01:10:22 +10:00
lachsinc f8d7f42208 Minor cleanup. 2018-10-01 00:17:42 +10:00
lachsinc db0756a119 Stepping working. Cleanup. 2018-10-01 00:02:41 +10:00
gingerBill 1a4e25f141 Prefix runtime procedures 2018-09-29 21:09:19 +01:00
lachsinc 79ade6ac7b Add various debug location stuff. 2018-09-30 04:47:21 +10:00
lachsinc ecce1d9974 Add debug location stack. 2018-09-30 04:24:24 +10:00
gingerBill 834308d8ce Fix using import override "bug" 2018-09-29 13:07:46 +01:00
lachsinc 9e73189d63 Tagged union debug info. Aggregate type fixes (unions inside structs etc.). 2018-09-27 21:50:57 +10:00
lachsinc 11bddf270c Cleanup debug info 'name' stuff. 2018-09-27 18:34:59 +10:00
lachsinc 0818a272e2 Cleanup hardcoded bytes to bits 2018-09-27 17:55:37 +10:00
lachsinc 9750b1162a Cleanup. 2018-09-27 01:34:15 +10:00
lachsinc 3106aaaa3d Fix pointers to all things debug info. Cleanup param order. Make scope/file optional for relevent types. 2018-09-27 00:02:35 +10:00
lachsinc d31d4c9bd6 (Basic) Map debug info support. Minor slice fix. 2018-09-26 07:51:16 +10:00
lachsinc 6993777d36 Slices. Fix dynamic array data ptr size. 2018-09-26 06:04:33 +10:00
lachsinc 54c044ee09 Add support for any. Fix rawptr debug type. 2018-09-26 05:43:58 +10:00
lachsinc 2e5cecf9e6 Cleanup dynamic array/string bloat. 2018-09-26 04:01:16 +10:00
lachsinc 7acb49eefb Cleanup comments/todos. 2018-09-26 02:17:05 +10:00
lachsinc 0f6c1f3482 Add debug info for globals. Misc debug info cleanup. 2018-09-26 02:01:03 +10:00
lachsinc 1ee0fe7457 Add DebugInfoArray as separate debug info type. Minor cleanup of various debug infos. 2018-09-25 21:24:15 +10:00
gingerBill 1a18481d8b Fix context assignment with selector expressions 2018-09-24 12:04:26 +01:00
gingerBill 28c61c0f5d Merge branch 'master' of https://github.com/odin-lang/Odin 2018-09-24 10:22:33 +01:00
gingerBill 597fb452b1 Minor fixes 2018-09-24 10:22:22 +01:00
lachsinc 5961a63880 Expose dynamic array data/len/cap debug info. Minor cleanup of odin string debug info. 2018-09-19 13:16:56 +10:00
lachsinc cce5e595e5 String debug info. Minor cleanup of derived / composite debug info output. 2018-09-19 01:52:08 +10:00
lachsinc e7d72f6848 Static array debug info. Temporary dynamic array debug info (pointer to data, no len/cap info provided yet). 2018-09-18 23:21:44 +10:00
lachsinc 7dcad45e0d Add proper procedure type support (return types and param proc signature) 2018-09-18 21:28:28 +10:00
lachsinc 3772ea6ae1 Enum debug info support. 2018-09-18 20:12:36 +10:00
lachsinc 2cc2eb1ec0 Fix stepping/jumping between procedures/files. 2018-09-18 18:10:03 +10:00
lachsinc 8a789e33b0 Remove llc/opt hack. XX.bc now contains useful debug info thanks to removal of optimization flags in debug builds. 2018-09-18 14:17:43 +10:00
lachsinc 2f86f8f8e0 Provide llvm ir with more debug info (for Visual Studio debugger support). 2018-09-18 10:50:56 +10:00
gingerBill 02f9a27f46 Merge pull request #264 from lunaticLipid/master
Remove reference to the runtime package within itself
2018-09-16 22:26:34 +01:00
Lipid 6cb605a025 Remove reference to the runtime package within itself 2018-09-16 08:19:33 +02:00
gingerBill 9f3e42e4ef Fix delete_key #262 2018-09-15 11:21:02 +01:00
gingerBill 71d987bd2e Fix runtime proc names; Change calling convention of context parameter 2018-09-15 10:46:46 +01:00
gingerBill 637899467c Merge branch 'master' of https://github.com/odin-lang/Odin 2018-09-15 10:14:40 +01:00
gingerBill 5bdb424c6b context.allocator = a; Remove __ from runtime procs; improve division for complex numbers 2018-09-15 10:14:24 +01:00
gingerBill c62cfddb9c Merge pull request #263 from hasenj/master
fix macos thread_count value
2018-09-14 17:48:34 +01:00
Hasen Judy 14a4c28f8f fix macos thread_count value 2018-09-15 01:46:50 +09:00
gingerBill f1e1814ff9 Syntactic sugar for anonymous enum within a bit set 2018-09-11 12:10:32 +01:00
gingerBill b468cf141b Fix are_types_identical for bit_set 2018-09-11 11:14:46 +01:00
gingerBill 787ea1feba Fix polymorphic constant parameters for procedures 2018-09-11 11:09:42 +01:00
gingerBill 91477e9e69 Allow for optional ok for return 2018-09-11 10:55:30 +01:00
gingerBill cfd0dfd2bf Remove assertion from constant parameter 2018-09-10 21:56:16 +01:00
gingerBill 46b1868185 Constant polymorphic names 2018-09-10 14:21:19 +01:00
gingerBill 4c4de1d6c4 Fix cloning of auto_cast Ast 2018-09-10 08:50:20 +01:00
gingerBill c8b30de771 Update compiler flags for build.bat 2018-09-09 15:06:04 +01:00
gingerBill 4f3837f0e6 Procedure inlining on call site 2018-09-09 14:46:28 +01:00
gingerBill 76848e8807 Disallow inline for recursive procedures 2018-09-09 13:58:23 +01:00
gingerBill 12902821d6 Make diverging procedure types different from ones without a return type 2018-09-09 13:48:33 +01:00
gingerBill f5549f6bde Make panic a diverging procedure 2018-09-08 12:17:16 +01:00
gingerBill 3825eab989 Diverging procedures proc() -> ! (no return) 2018-09-08 12:16:03 +01:00
gingerBill 3cd6ae311d Parametric polymorphic union type 2018-09-08 12:02:25 +01:00
gingerBill 26cfc0257d Fix array_ordered_remove typo 2018-09-08 10:44:18 +01:00
Ginger Bill 1d31eabb6e Fix minor parsing issue for polymorphic identifiers 2018-09-04 13:47:24 +01:00
Joshua Mark Manton 8cd2797b2e Fixed core library bugs after recent changes. (#257)
* Fix `delete_map` calling `delete_dynamic_array` instead of `delete_slice for its hashes.

* Removed print statements from `__dynamic_map_rehash`
2018-09-02 22:18:32 +02:00
gingerBill 11f5236434 Add $T: typeid/[]$E; Deprecate T: type/[]$E
`type` as a keyword will soon be removed in favour of polymorphic names (identifiers) in procedures
2018-09-02 16:33:54 +01:00
gingerBill 220485a2d2 typeid as keyword (ready to implement polymorphic name parameters) 2018-09-02 15:56:36 +01:00
gingerBill eb274cf316 Remove test code 2018-08-30 19:33:16 +01:00
gingerBill aa542980ce Change memory layout of map to be 3 words smaller 2018-08-30 19:14:10 +01:00
gingerBill e0240c186f Rename buffer entity 2018-08-30 12:53:07 +01:00
gingerBill ae58502a21 Make free_all built-in 2018-08-30 12:21:16 +01:00
gingerBill 6a3697279c Place assertf and printf to package fmt 2018-08-30 12:10:16 +01:00
gingerBill c19ec5d65d Fix delete for dynamic array and map 2018-08-30 12:00:51 +01:00
gingerBill 15dca449c9 Add assertf and panicf 2018-08-30 11:46:57 +01:00
gingerBill dda985f49d Add extra nil check for assert and panic 2018-08-30 11:16:06 +01:00
gingerBill 12256beeb2 Prevent other parameters being the default value 2018-08-30 11:12:57 +01:00
gingerBill 0858ae2024 Add utf8_to_ucs2 for package win32 so that the wide procedures can used by default 2018-08-30 10:59:46 +01:00
gingerBill 6c18864291 Add default_assertion_failure_proc to the minimum dependency build 2018-08-29 21:15:11 +01:00
gingerBill ae57284912 Add Assertion_Failure_Proc to context 2018-08-29 21:10:13 +01:00
gingerBill 001837e6bb Temporary allocator for context 2018-08-29 19:55:55 +01:00
gingerBill 28523f17e2 Add default allocator to allocation related procedures e.g. alloc, free, delete, make 2018-08-28 20:14:56 +01:00
gingerBill ae2af8315e Allow for default parameters that are non-constant entities, but not any non-constant expression 2018-08-28 20:03:27 +01:00
gingerBill adbb3bb75f Add -lld flag for using "bin\lld-link.exe" on Windows 2018-08-28 19:28:34 +01:00
gingerBill 6181c4edb3 Update 2018-08-28 19:26:05 +01:00
gingerBill 830c194da5 Allow enums for array lengths 2018-08-26 18:23:17 +01:00
gingerBill 1830c1e57c Allow bitwise operation on enums 2018-08-26 18:05:59 +01:00
gingerBill e5735af6d6 Disable for in over cstring 2018-08-26 15:10:23 +01:00
gingerBill a6b0ae71b2 Remove assert 2018-08-26 10:56:33 +01:00
gingerBill 3365baee8f runtime.Typeid_Bit_Field layout to store more information into the typeid 2018-08-25 12:11:48 +01:00
gingerBill cc88dd0b71 Allow for variadic min max procs
Request #252
2018-08-25 11:12:52 +01:00
gingerBill f050bfe872 Fix comparisons with union 2018-08-25 10:39:19 +01:00
gingerBill ab71acc3a5 Disable abs for arrays #254 2018-08-25 10:27:44 +01:00
gingerBill 0a85d1af6b Improve error messages for using on fields 2018-08-24 22:28:00 +01:00
gingerBill 68adadb01a Allow using in structs on arrays with count <= 4 2018-08-24 22:12:30 +01:00
gingerBill d56f458d11 Fix file scope #assert 2018-08-24 17:42:13 +01:00
gingerBill a65eadee63 Fix for in enum iteration 2018-08-22 18:56:41 +01:00
gingerBill 16dfae62bc Allow casting to and from rawptr and cstring #249 2018-08-22 15:19:04 +01:00
gingerBill fe680a8b1f Fix default return values #250 2018-08-22 15:17:29 +01:00
gingerBill 54fe9f3eb1 Improve min dep for min/max/abs/clamp 2018-08-21 21:43:38 +01:00
gingerBill cbc6c2666b Improve proc group scoring algorithm 2018-08-21 14:11:18 +01:00
gingerBill a4d0ac1802 Merge branch 'master' of https://github.com/odin-lang/Odin 2018-08-20 19:20:44 +01:00
gingerBill 0dc29a7208 Implement suggestions from #247 2018-08-20 19:20:28 +01:00
gingerBill a9321bc73f Update README.md 2018-08-20 10:27:48 +01:00
gingerBill e3f0ab7c3d Parallelize parser on *nix 2018-08-19 10:58:57 +01:00
gingerBill 5643ea1ba2 Fix typo 2018-08-19 10:56:23 +01:00
gingerBill 3b6523fbd9 Fix gbMutex for *nix 2018-08-19 10:34:31 +01:00
gingerBill ffc4f01470 All enums in array indices 2018-08-17 19:38:15 +01:00
gingerBill e326f41d16 Fix demo 2018-08-17 15:26:29 +01:00
gingerBill 1d0ac72e4a Disable non-comparison operations for enum (use bit_set for flags) 2018-08-17 15:24:44 +01:00
gingerBill b216e44870 Add underlying type for bit_set 2018-08-17 15:11:41 +01:00
gingerBill 7d39b26cf4 Minor refactor 2018-08-16 20:52:46 +01:00
gingerBill 884d5fed9f bit_set['A'..'Z'], bit_set[0..8] 2018-08-16 15:16:57 +01:00
gingerBill ec84188597 Fix typos in parser 2018-08-16 10:30:44 +01:00
gingerBill 85ac95f81b Constant evaluation for in expression for bit_sets 2018-08-16 00:07:26 +01:00
gingerBill 042550cf87 Fix default value bug 2018-08-15 19:36:32 +01:00
gingerBill b3ebff715a Fix defer ir bug 2018-08-15 15:44:41 +01:00
gingerBill 1ee60663bb Fix issue #244 with constant array comparisons 2018-08-14 19:43:36 +01:00
gingerBill 59da98d3f0 Improve type hinting for compound literals 2018-08-14 19:39:28 +01:00
gingerBill 2d41a42f61 Cleaning type hinting for assignments 2018-08-14 19:33:42 +01:00
gingerBill e1e4a916a5 Fix demo and improve type hinting 2018-08-14 19:29:31 +01:00
gingerBill 71f94bff76 Minor sanity features for bit_set 2018-08-14 19:22:48 +01:00
gingerBill c7d6467cfa Fix assigning issue for bit sets 2018-08-14 18:43:47 +01:00
gingerBill 79a3c0b36c Fix bit_set range 2018-08-14 18:35:14 +01:00
gingerBill 966249c10a bit_set constants 2018-08-14 18:32:34 +01:00
gingerBill acc010cba5 Add bit_set type 2018-08-14 17:07:56 +01:00
gingerBill 89f4e7a8db -no-crt flag for windows amd64 2018-08-13 01:22:14 +01:00
gingerBill 55f4eabecd Fix map addressing mode bug 2018-08-10 18:22:37 +01:00
gingerBill d0fc9aa069 Allow for '\"' 2018-08-10 17:48:29 +01:00
gingerBill 8be9b5082c Fix default make parameters for dynamic arrays 2018-08-09 18:15:49 +01:00
gingerBill 708907df31 auto_cast for named parameters 2018-08-09 17:59:18 +01:00
gingerBill 70586b1cf8 auto_cast prefix for procedure parameters 2018-08-09 17:58:11 +01:00
gingerBill 877a78d6ba Fix make error messages 2018-08-08 23:07:51 +01:00
gingerBill 3928614326 Merge pull request #241 from thebirk/fix-sh-main-not-found
Fixed 'sh: main: command not found' error on linux.
2018-08-08 22:41:42 +01:00
thebirk 5e5f5bfa8d Fixed 'sh: main: command not found' error on linux. 2018-08-08 17:48:17 +02:00
gingerBill 3a1a7b40f9 Add runtime messages for make for the len/cap parameters 2018-08-08 13:04:40 +01:00
gingerBill 835d7dcab2 make as a user-level procedure rather than a built-in procedure 2018-08-08 13:04:40 +01:00
gingerBill 28816dc491 Fix parenthesis warning on clang 2018-08-08 13:04:40 +01:00
gingerBill ccdc3438be Refactor handle_parameter_value code 2018-08-06 00:26:38 +01:00
gingerBill 60711dd355 Refactor default parameter values 2018-08-05 23:57:34 +01:00
gingerBill fad3947e26 Add *with_allocator procedures to mem 2018-08-05 23:40:19 +01:00
gingerBill d8e5b2d1a4 Fix cstring cast operation 2018-08-05 19:07:03 +01:00
gingerBill 2d26ad0226 Remove opengl package 2018-08-05 19:01:15 +01:00
gingerBill 45d3c6c0d3 Fix cstring to string conversion 2018-08-05 18:58:35 +01:00
gingerBill c6bffd7c35 Change build.bat to use release_mode=1 by default 2018-08-05 10:37:09 +01:00
gingerBill 462d81430c Fix map runtime issue regarding erasing a key 2018-08-05 10:31:20 +01:00
gingerBill d3cada5bd6 Change rules for how context and defer interact 2018-08-04 23:46:46 +01:00
gingerBill cdbf831a7a Replace context <- c {} with context = c;. context assignments are scope based 2018-08-04 23:14:55 +01:00
gingerBill 0718f14774 Reduce number of range and slice operators #239
Replace .. and ... with : and ..
2018-08-01 21:34:59 +01:00
gingerBill a6fe656f21 foreign import x {"foo.lib", "bar.lib"} 2018-07-29 20:56:09 +01:00
gingerBill dc5da7933a Add older demos 2018-07-29 11:36:24 +01:00
gingerBill 96fc9138d4 Do using Foo :: enum at the type_decl stage 2018-07-29 11:29:20 +01:00
gingerBill 6512a3e5f2 using Foo :: enum {A, B, C}; len(Foo) 2018-07-29 10:50:15 +01:00
gingerBill 49f2124df0 Support larger integer literals to work with the new BigInt system 2018-07-29 10:22:17 +01:00
gingerBill a11d6e696a expand_to_tuple for fixed arrays 2018-07-28 20:56:27 +01:00
gingerBill 1705ba8069 Fix typos 2018-07-28 19:44:00 +01:00
gingerBill 8d2c4a78a1 Merge pull request #238 from odin-lang/big-int
Big int
2018-07-28 18:39:15 +01:00
gingerBill 8504ff920b Correctly handle bitwise operations for negative BigInt 2018-07-28 18:36:45 +01:00
gingerBill e34a9e6185 Fix big_int_shr 2018-07-28 00:48:36 +01:00
gingerBill c3c7834246 BigInt support in the constant system 2018-07-28 00:41:31 +01:00
gingerBill 1ab40d8600 Merge pull request #237 from lunaticLipid/master
Add mat3_mul and generic transpose to math.odin
2018-07-17 08:25:21 +01:00
Lipid 92ce02dab0 Fix indent characters 2018-07-16 20:30:49 +02:00
Lipid 8abe9ef507 Add mat3_mul and generic transpose to math.odin 2018-07-16 20:27:29 +02:00
gingerBill d0e04bf569 Merge pull request #236 from hasenj/master
Fix build errors on osx
2018-07-14 19:39:11 +01:00
Hasen Judy b92599879a free -> delete in os_osx and os_linux 2018-07-13 11:25:46 -06:00
gingerBill 0e91298fd1 Rename free to delete for non pointer types 2018-07-08 11:03:56 +01:00
gingerBill e515220694 Improve array arithmetic inlining 2018-07-08 10:15:46 +01:00
gingerBill a55683d287 Remove allocator parameters in ir.cpp 2018-07-07 11:29:45 +01:00
gingerBill fa4e95105f Loop array arithmetic on large arrays 2018-07-07 11:13:20 +01:00
gingerBill 1e01085ef7 Merge branch 'master' of https://github.com/odin-lang/Odin 2018-07-07 08:12:48 +01:00
gingerBill 04a1f869b5 Fix when statements within a foreign block 2018-07-07 08:11:31 +01:00
Morten Vassvik e04ba7530d Updated makefile to run demo package instead of demo.odin 2018-07-05 15:48:55 +02:00
Morten Vassvik ea055f1465 Surrounded explicit link paths (.a and .so) and the exe path for 'odin run' in quotes, so that it works in paths containing characters that must be escaped (like spaces) 2018-07-05 15:46:11 +02:00
Morten Vassvik 3b2c867817 Replaced CLOCK_PROCESS_CPUTIME_ID with CLOCK_MONOTONIC in calls to clock_gettime and clock_getres to make timings on calling external executables accurate instead of showing them taking negligible time on linux. 2018-07-04 21:04:48 +02:00
gingerBill 3de23eb0bf Merge pull request #233 from zangent/master
Make macOS builds work again
2018-07-02 08:57:22 +01:00
Zachary Pierson 5de3b07e2b Made os_osx.odin use the new-style runtime.args__ and added read_directory for macOS 2018-07-02 02:50:08 -05:00
gingerBill c0ca4d4635 Uncomment code 2018-07-01 18:31:31 +01:00
gingerBill efe4b71bae Fix build.sh 2018-07-01 17:17:31 +01:00
gingerBill bc37bd5429 Merge branch 'packages' of https://github.com/odin-lang/Odin into packages 2018-07-01 17:14:43 +01:00
gingerBill 5f20e04259 Fix on *nix 2018-07-01 17:14:22 +01:00
gingerBill 9bef5ec01a Fix anonymous procedures 2018-07-01 16:21:32 +01:00
gingerBill cdf873542b Add read_directory for linux 2018-06-21 08:39:52 +01:00
gingerBill 4742690dec Fix is_excluded_target_filename 2018-06-21 08:39:07 +01:00
gingerBill 3a16f1e854 Minor style change 2018-06-17 22:25:28 +01:00
gingerBill 877400dd12 Scope to use flags rathers than booleans 2018-06-17 22:22:30 +01:00
gingerBill a4e3201113 Minor cleanup for builtin scope/pkg 2018-06-17 22:07:27 +01:00
gingerBill a99cc2fd70 Clean up import lookup code 2018-06-17 21:50:40 +01:00
gingerBill 5fe4c33d0e Allow importation of core:builtin to get built-in entities 2018-06-17 21:46:37 +01:00
gingerBill 4d9d38cc28 Move TypeAndValue to Ast from Map 2018-06-17 16:35:22 +01:00
gingerBill 5b71ffd4f9 Rename clone_ast_node to clone_ast 2018-06-17 11:03:26 +01:00
gingerBill c2ca24a486 Big renaming: AstNode to Ast 2018-06-17 10:58:59 +01:00
gingerBill e5aff6fd6d Minimize AstNode size 2018-06-17 10:48:50 +01:00
gingerBill 3eb8aa8268 Modify CommentGroup parsing 2018-06-17 10:29:20 +01:00
gingerBill 6d1c32eb77 Add escape code for ESC \e 2018-06-15 23:13:26 +01:00
gingerBill ba776a3c9f Fix bitwise not for signed integers 2018-06-15 23:01:12 +01:00
gingerBill cd7e260f4e Fix cyclic polymorphic procedure usage and improve its error message 2018-06-15 22:49:06 +01:00
gingerBill ba67e474d3 Make source code compile with 32 bit (but not build 32 bit code) 2018-06-15 21:46:03 +01:00
gingerBill b92a8c513e Modify how build settings are handled 2018-06-15 21:38:22 +01:00
gingerBill 13572aeef0 Fix gb.h 2018-06-15 20:26:39 +01:00
gingerBill 5081ea1a0c Fix type aliasing comparison; Fix gb_utf8_decode 2018-06-15 19:59:35 +01:00
gingerBill e9e7ce2606 Allow .allocator for dynamic arrays; Add mem.Pool 2018-06-12 19:10:14 +01:00
gingerBill 915dcb0c28 Fix min dependency check 2018-06-11 22:57:40 +01:00
gingerBill 8236c6d4b7 Allow for base enum type with an enum declaration 2018-06-11 22:50:13 +01:00
gingerBill 555fe37ad8 Remove the need for a look ahead 2018-06-11 18:06:58 +01:00
gingerBill 881f667558 Change how context <- is parsed to remove the need for a look-ahead 2018-06-11 18:02:04 +01:00
gingerBill 0a99595efe Remove using in stuff 2018-06-11 17:34:57 +01:00
gingerBill 268491b224 Use global arena for AstNode allocations 2018-06-09 19:53:06 +01:00
gingerBill 49ea9ed722 Entity aliasing clean up 2018-06-09 10:08:17 +01:00
gingerBill d7108416c9 Remove dead code 2018-06-07 23:52:13 +01:00
gingerBill b136630856 Fix type info generation for empty structs 2018-06-07 23:24:37 +01:00
gingerBill fa6f31186a Merge pull request #228 from shuaDev/shwadev-packages
Fix some core lib errors on packages branch
2018-06-03 21:09:57 +01:00
gingerBill b027b1d60f Fix min type info for polymorphic procedures and named types 2018-06-03 21:09:08 +01:00
Joshua Mark Manton 7ed1d931cb fix quick_sort_proc calling quick_sort instead of recursively calling itself 2018-06-03 11:27:57 -07:00
Joshua Mark Manton 2570296b01 fix core opengl ODIN_OS reference and pointer math stuff 2018-06-03 11:25:46 -07:00
Joshua Mark Manton f0a4526250 Fix alloc.odin using old raw file 2018-06-03 11:22:42 -07:00
gingerBill c39332c7e7 Revert name mangling 2018-06-03 19:18:47 +01:00
gingerBill 3f4b6b22dc Change our IR name mangling rules 2018-06-03 17:55:13 +01:00
gingerBill e0549df03e Fix minor possible issue 2018-06-03 17:44:10 +01:00
gingerBill e46662a546 Rename os.default_allocator to os.heap_allocator 2018-06-03 16:40:58 +01:00
gingerBill 360a74e2fe Merge pull request #226 from BrettRToomey/packages
Dsymutil fixes
2018-06-03 16:35:43 +01:00
Brett R. Toomey 597c4591bc Merge branch 'packages' of github.com:odin-lang/Odin into packages 2018-06-03 17:13:11 +02:00
Brett R. Toomey 80833ed703 Dsymutil fixes for macOS 2018-06-03 17:12:30 +02:00
gingerBill 106302189c Use gbString for opt_flags 2018-06-03 16:09:24 +01:00
gingerBill 05c5f98e8e Add -debug-compile parameter for llc 2018-06-03 15:55:14 +01:00
gingerBill d556fa2cd8 Remove special shared scope for runtime stuff 2018-06-03 15:06:40 +01:00
gingerBill 9bd7f023b2 Split up init_preload into specific parts 2018-06-03 11:38:02 +01:00
gingerBill 398109ac84 Remove need for __llvm_core 2018-06-03 10:51:43 +01:00
gingerBill 12b870ba66 Use const & for Array<AstNode *> parameters 2018-06-03 10:30:31 +01:00
gingerBill 6202fb8373 Re-allow when statements at the file scope 2018-06-02 19:44:34 +01:00
gingerBill ced818ad54 Remove dead code from checker 2018-06-02 11:58:35 +01:00
gingerBill ccbb6df749 Handle multiple +build package tags with '!' (nots) 2018-05-28 21:25:08 +01:00
gingerBill 6eb505a677 Comment based build tags for packages (basic and temporary) 2018-05-28 20:59:06 +01:00
gingerBill 619783ca1b Remove clutter parameters and begin parallelizing the type checker 2018-05-28 18:46:39 +01:00
gingerBill 642aa0bc4b Refactor: use CheckerContext rather than Checker in type checking part 2018-05-28 15:57:53 +01:00
gingerBill 45b3067068 Remove tmp_allocator from Checker 2018-05-28 14:15:08 +01:00
gingerBill b7858a66b9 Parallelize per file rather than per package 2018-05-28 12:06:50 +01:00
gingerBill 4e203feaf4 Change import lookup 2018-05-27 23:46:08 +01:00
gingerBill a513b47780 Remove unused packages 2018-05-27 23:33:10 +01:00
gingerBill 547a2831c7 Clean up name mangling by using unique package names per project 2018-05-27 22:09:11 +01:00
gingerBill 5c52ffe24e Reorganize runtime package 2018-05-27 21:22:25 +01:00
gingerBill a5763d6fee Err on empty directory packages 2018-05-27 14:12:10 +01:00
gingerBill 95482c554d Fix build.bat 2018-05-27 13:53:46 +01:00
gingerBill 10758710d4 Fix demo.odin 2018-05-27 13:53:19 +01:00
gingerBill 86cf9383ea Fix delayed assert collection 2018-05-27 13:49:55 +01:00
gingerBill 307977d4cf Remove dead code 2018-05-27 13:30:18 +01:00
gingerBill 1beff539d7 Single file "main" file 2018-05-27 13:22:24 +01:00
gingerBill df578d6ec5 Allow for either .odin file or directory as the initial start 2018-05-27 11:40:27 +01:00
gingerBill 6aae381e83 Move ODIN_* platform constants to core:os 2018-05-27 11:03:46 +01:00
gingerBill 7ee9051a56 IR now builds with the new package system 2018-05-27 10:49:14 +01:00
gingerBill eb11edabe0 Add file scopes for the packages 2018-05-27 00:10:38 +01:00
gingerBill c067b90403 Add basic package support (no IR support yet) 2018-05-26 23:12:55 +01:00
gingerBill 5b6770f3d2 Parse directories to be packages 2018-05-21 20:47:52 +01:00
gingerBill 718b80ba39 Fix demo for removing default struct values 2018-05-20 17:39:49 +01:00
gingerBill 4d052d5119 Remove code relating to default struct values 2018-05-20 17:31:46 +01:00
gingerBill 7e4c643401 Disable default struct field values; Update README.md 2018-05-20 16:00:39 +01:00
gingerBill e920338f21 Remove old dependency 2018-05-20 08:58:48 +01:00
gingerBill af2048570c Merge pull request #222 from shuaDev/master
added compiler command for only parsing and typechecking
2018-05-17 10:33:23 +01:00
Joshua Mark Manton 1ee4f849cb now return 1 if there were errors 2018-05-17 02:08:04 -07:00
Joshua Mark Manton 703393fc63 whitespace 2018-05-16 23:08:01 -07:00
Joshua Mark Manton 81420ab246 removed unneeded block 2018-05-16 23:07:27 -07:00
Joshua Mark Manton c94d19718b added compiler command for only parsing and typechecking 2018-05-16 23:03:05 -07:00
gingerBill e25c72ecdd Fix #219 and #220 2018-05-14 17:05:52 +01:00
gingerBill 780b81a59f Allow for NO_DEFAULT_STRUCT_VALUES
(will decide later if I want them or not)
2018-05-13 21:09:49 +01:00
gingerBill 9f1dda701d Comment out test 2018-05-13 18:43:21 +01:00
gingerBill e597a8d72e Fix issues with exact integer bounds and remove dead code 2018-05-13 17:38:35 +01:00
gingerBill de9a4b5164 Disable pointer arithmetic 2018-05-13 16:10:02 +01:00
gingerBill 319aca3101 Merge pull request #218 from hasenj/osx-timing
Fix timing on macos
2018-05-13 11:45:05 +01:00
Hasen Judy 9dc2c01aaa Fix timing on macos 2018-05-13 19:33:08 +09:00
gingerBill 6164672421 Change FreeAll to Free_All 2018-05-13 10:14:32 +01:00
gingerBill 61906613b0 Add typeid to Type_Info struct 2018-05-13 10:09:21 +01:00
gingerBill 3b48fa8e7d Fix default initialized values for globals (#217) 2018-05-12 21:22:39 +01:00
gingerBill 324b7d65e7 Use __type_info_of internally 2018-05-12 20:17:12 +01:00
gingerBill 373a60b9ef type_info_of allows typeid; typeid_of allows ^Type_Info; Otherwise only allow type 2018-05-12 19:54:16 +01:00
gingerBill 2ef22e86e0 Make any use typeid rather than ^Type_Info 2018-05-12 18:40:49 +01:00
gingerBill 830f4f540f typeid 2018-05-12 17:39:04 +01:00
gingerBill 56ff5496bc Minimal Type Info Dependency handling 2018-05-12 16:53:44 +01:00
gingerBill 20fbece14c Change semantics for distinctness for pointers, arrays, dynamic arrays, and maps. 2018-05-12 10:47:32 +01:00
gingerBill 9fbfd86cde Add log to math.odin 2018-05-12 10:46:00 +01:00
gingerBill 7547bc66cf Complete remove all non required preload stuff from min dep and only use what is used. 2018-05-12 10:38:40 +01:00
gingerBill 18a9fa7355 Improve minimal dependency system 2018-05-12 10:27:55 +01:00
gingerBill b32af841c5 Merge branch 'master' of https://github.com/odin-lang/Odin 2018-05-06 15:31:32 +01:00
gingerBill 66b4252931 Fix #210 2018-05-06 15:31:18 +01:00
gingerBill 2c95eaa418 Merge pull request #216 from lunaticLipid/master
Fix copy-and-forget in math.odin
2018-05-02 19:40:59 +01:00
Lipid 7382f52dc9 Fix copy-and-forget in math.odin 2018-05-02 18:04:50 +02:00
gingerBill 49dd299999 Merge pull request #204 from ThisDrunkDane/master
Added more function to windows.odin
2018-04-14 19:45:00 +01:00
Mikkel Hjortshoej e391b05513 Merge branch 'master' of github.com:ThisDrunkDane/Odin 2018-04-13 22:39:17 +02:00
Mikkel Hjortshoej 2de62910fc Added more function to windows.odin 2018-04-13 22:38:58 +02:00
gingerBill fc77b5b4ac Try to fix internal compiler error in #208 2018-04-10 21:03:51 +01:00
gingerBill a83d916fad Fix immutable context to any assignment #214 2018-04-10 20:51:44 +01:00
gingerBill e71a641379 Fix internal compiler error trigger for issue #212 2018-04-10 20:46:32 +01:00
gingerBill e2eca45188 Fix race condition caused by parallelized parser: #211 2018-04-10 20:35:05 +01:00
gingerBill 4d78540658 Fix #210 2018-04-10 20:20:33 +01:00
gingerBill b83c3f265b Fix #209 #assert bug 2018-04-10 20:18:16 +01:00
gingerBill 30f5a3bb93 Move cycle checking to much earlier on in the semantic stage 2018-03-23 20:48:30 +00:00
gingerBill 2e1e1e6034 Type caching 2018-03-23 16:35:41 +00:00
gingerBill 991479fbf9 Remove allocator parameter to types.cpp functions 2018-03-23 16:01:23 +00:00
gingerBill 5660f98cc3 Merge branch 'master' of https://github.com/odin-lang/Odin 2018-03-23 15:23:31 +00:00
gingerBill 5bf0f9d630 Fix type cycle bug 2018-03-23 15:23:14 +00:00
Mikkel Hjortshoej 15b72119eb Added more function to windows.odin 2018-03-21 19:30:27 +01:00
gingerBill dc30e7a200 Merge pull request #201 from nakst/master
update essence bindings
2018-03-11 20:52:58 +00:00
Nakst db2293144a update essence bindings 2018-03-10 21:33:59 +00:00
gingerBill 5016f45429 Merge pull request #200 from nakst/master
fix compile warnings on linux
2018-03-10 20:50:46 +00:00
Nakst 9fa4aa40b7 fix compile warnings on linux 2018-03-10 20:29:43 +00:00
gingerBill 52f60c706a Merge pull request #199 from ThisDrunkDane/resource
Resource Compiler calling
2018-03-10 13:42:25 +00:00
gingerBill fff4ead96a Fix gb_alloc_str_len 2018-03-07 20:36:15 +00:00
Mikkel Hjortshoej 3574341b6b Missing .rc error message 2018-03-05 13:10:01 +01:00
Mikkel Hjortshoej cbabc80d92 Calls rc.exe if -resource specified 2018-03-05 11:46:50 +01:00
gingerBill f4cf88c2ca Move os_*.odin files to os/ 2018-03-04 11:38:49 +00:00
gingerBill 6db95b554f __args__: []cstring 2018-03-04 11:25:23 +00:00
gingerBill 105de7705a Add unselector_expr 2018-03-04 11:06:59 +00:00
gingerBill 584dffea14 Remove dead code; fix referencing of a type assertion in a selector expression 2018-03-04 09:25:02 +00:00
gingerBill 41b6d215bb Fix using determination order 2018-03-03 20:07:12 +00:00
gingerBill 9274f29ca9 deprecated attribute for procedure declarations 2018-03-03 11:16:48 +00:00
gingerBill 08c87e57f8 Remove cwd in odin run for Linux 2018-03-03 10:26:25 +00:00
gingerBill b21cdd5037 Merge branch 'master' of https://github.com/odin-lang/Odin 2018-03-03 10:25:13 +00:00
gingerBill 63ab8b2418 Make irGen.output_base use full path rather than relative 2018-03-03 10:23:27 +00:00
Morten Vassvik cb7a343caf Fixed '_alloc_command_line_arguments()' in os_linux.odin to use the new cstrings, and made 'odin run' use the full executable path. 2018-03-01 12:58:57 +01:00
gingerBill 40542e6e26 Fix comparison against nil for cstring 2018-02-28 12:01:26 +00:00
gingerBill 9da05dd4cb Update core library with cstring 2018-02-28 11:44:41 +00:00
gingerBill ae9da0abfb Merge branch 'master' of https://github.com/odin-lang/Odin 2018-02-28 11:20:31 +00:00
gingerBill d3ea334e7a cstring 2018-02-28 11:20:11 +00:00
gingerBill d76132a3fb Merge pull request #198 from ThisDrunkDane/terminate_thread
Added terminate_thread to thread.odin
2018-02-26 10:06:08 +00:00
gingerBill 223c473cf6 Demo fix 2018-02-25 20:57:34 +00:00
gingerBill fd57cfa1ae Fix build_settings.cpp 2018-02-25 20:52:06 +00:00
gingerBill f23bd2dc27 Revert demo 2018-02-25 20:46:32 +00:00
gingerBill 69062ba3ab More code tidying with Array 2018-02-25 20:24:38 +00:00
gingerBill e75563cb32 Minor code rearrangement 2018-02-25 19:42:12 +00:00
gingerBill d63885a495 array_make 2018-02-25 19:23:52 +00:00
gingerBill f28a34fa99 Use Array<irValue *> in ir.cpp 2018-02-25 15:31:00 +00:00
gingerBill a1e8de4e00 Fix ir_emit_slice_bounds_check 2018-02-25 15:11:20 +00:00
gingerBill d247ba4751 Hexadecimal floats for "perfect values" 0h42f60000 == 123; use bit_cast in compiler 2018-02-25 15:09:16 +00:00
gingerBill 27b7dc336a Change parsing for floats and disallow x.0 2018-02-25 14:36:41 +00:00
gingerBill 60a7c68aa6 Minor code reorganization 2018-02-25 14:23:45 +00:00
Mikkel Hjortshoej 78c103e62c Merge branch 'terminate_thread' of github.com:ThisDrunkDane/Odin into terminate_thread 2018-02-25 14:57:22 +01:00
Mikkel Hjortshoej ffec1c77f2 Added terminate_thread to thread.odin 2018-02-25 14:56:50 +01:00
gingerBill 5357181484 Multithreaded parser (windows only) 2018-02-25 13:45:44 +00:00
Mikkel Hjortshoej 33ddb3ad4d Added terminate_thread to thread.odin 2018-02-25 14:38:55 +01:00
gingerBill 1cd453db14 Remove unneeded disabled warnings for MSVC 2018-02-25 12:29:48 +00:00
gingerBill 3b5932699c Fix #assert in opengl.odin 2018-02-25 12:14:35 +00:00
gingerBill bada81159d Add #no_bounds_check to __dynamic_map_* procedures 2018-02-25 12:13:45 +00:00
gingerBill 652da98c70 Fix slice bounds checking 2018-02-25 12:10:19 +00:00
gingerBill e14e2c3b4d -out and generate executable in the current working directory 2018-02-25 11:49:44 +00:00
gingerBill f96a897821 Make switch in f { valid 2018-02-25 10:55:18 +00:00
gingerBill b74ae77745 Merge pull request #197 from bpunsky/context-bug-fix
Context bug fix
2018-02-25 00:13:02 +00:00
Brendan Punsky 564226be02 fixed issues with uninitialized contexts
also, `any_to_bytes` I think, and maybe some bindings in `core:sys/windows.odin`
2018-02-24 18:58:22 -05:00
Brendan Punsky f6c45fc68a Merge remote-tracking branch 'origin/master' 2018-02-24 14:29:30 -05:00
gingerBill 35ba5771a5 Replace compile_assert with #assert 2018-02-24 19:03:29 +00:00
gingerBill b2461f7192 Fix issue #195 2018-02-24 18:19:11 +00:00
Brendan Punsky 60a54f404b Auto stash before merge of "master" and "origin/master" 2018-02-22 20:11:17 -05:00
gingerBill 921f261377 Fix os.args on Windows #143 2018-02-22 21:34:09 +00:00
gingerBill d70a555c1c Fix issue #192 2018-02-22 21:24:38 +00:00
gingerBill 4c339360e9 auto_cast 2018-02-18 15:14:13 +00:00
gingerBill 731dad480d Fix issue regarding nullptr Type * 2018-02-18 14:37:58 +00:00
gingerBill a0f2357cb3 Minor fix to demo 2018-02-17 19:40:33 +00:00
gingerBill e86ac75e9c Merge branch 'master' of https://github.com/odin-lang/Odin 2018-02-17 19:24:15 +00:00
gingerBill f51de2e488 Disallow #complete switch ranges 2018-02-17 19:24:02 +00:00
gingerBill 5efefdcf16 Merge pull request #189 from ThisDrunkDane/master
Pretty readme header
2018-02-17 19:16:51 +00:00
gingerBill cabb2bb992 Commit 1000 🎉🎂 2018-02-17 19:15:58 +00:00
gingerBill d560f6c920 Fix compile time issue regarding switch ranges 2018-02-17 19:05:14 +00:00
gingerBill 21432ba96e Clean up range code for switch 2018-02-17 18:34:14 +00:00
gingerBill c341597657 Remove constant from switch for strings 2018-02-17 18:22:43 +00:00
Mikkel Hjortshøj 2a1420d4e7 Update README.md 2018-02-17 15:03:26 +01:00
Mikkel Hjortshoej 28d88f6af4 rounded logo 2018-02-17 15:03:16 +01:00
gingerBill c4d2d287fc #complete switch; Removal of dyncall 2018-02-17 11:54:08 +00:00
gingerBill 6a85546b76 Fix #187 2018-02-14 21:46:39 +00:00
gingerBill 2e92d0c821 Remove old procedures 2018-02-13 22:05:25 +00:00
gingerBill a499a3aa5e Merge pull request #184 from ThisDrunkDane/master
Added widechar versions of functions, plus cursor functions
2018-02-13 22:02:43 +00:00
gingerBill 23ab3c4713 Replace [...] with [?] 2018-02-13 21:59:49 +00:00
gingerBill da300aa9c3 Fix enum #export does not work with export #185 2018-02-13 18:01:42 +00:00
ThisDrunkDane e225158a6f Merge branch 'master' of https://github.com/odin-lang/Odin 2018-02-12 06:07:15 +01:00
gingerBill 2ce55783d2 Fix make 2018-02-11 23:47:46 +00:00
gingerBill 14eeee40b2 Update demo.odin 2018-02-11 11:16:17 +00:00
gingerBill 038dea9202 v0.8.1
Fix initialization values for variables
2018-02-11 11:15:53 +00:00
gingerBill 0ae3484171 Fix zero value initialization in IR 2018-02-11 11:13:52 +00:00
gingerBill 54976c3249 v0.8.0 2018-02-09 18:03:06 +00:00
Mikkel Hjortshoej 4c06b44315 Merge branch 'master' of github.com:odin-lang/odin 2018-02-07 21:23:28 +01:00
Mikkel Hjortshoej 678b58e0b1 Added widechar versions of functions, plus cursor functions 2018-02-07 21:17:59 +01:00
gingerBill 8f913c656c Fix error reporting for assignment to a built-in procedure (#183) 2018-02-07 18:55:01 +00:00
gingerBill 001b48a5c6 Change local variable alignment to 16 bytes for the time being 2018-02-05 23:27:18 +00:00
gingerBill 54929a1b92 Minor context fix 2018-02-05 23:09:34 +00:00
gingerBill 92780e2683 distinct keyword for type declarations 2018-02-05 22:46:30 +00:00
gingerBill 2891988d3b Add extra check to ir_emit_zero_init 2018-02-05 22:26:22 +00:00
gingerBill c1728914c6 Fix typos #type_alias 2018-02-04 21:34:45 +00:00
gingerBill ed2f49e8d2 Remove dead code; Fix issue regarding order of evaluation of function parameters (in C++) depending on the compiler (clang vs gcc vs msvc) 2018-02-04 20:07:05 +00:00
gingerBill 8a76a370a9 Merge pull request #182 from ThisDrunkDane/master
Functions, structs and constants related to getting file notifications
2018-02-04 19:49:04 +00:00
Mikkel Hjortshoej 1160fd4331 functions, structs and constants related to getting file notifications 2018-02-03 21:56:15 +01:00
gingerBill 0134c38759 Fix issue #181 2018-02-03 10:32:47 +00:00
gingerBill d079095517 Fix bug #179 2018-02-03 10:27:33 +00:00
gingerBill 028d628e9f Add extra zero init for IR 2018-01-31 18:27:08 +00:00
gingerBill 5e4b62acfe Fix literal 2018-01-28 15:59:37 +00:00
gingerBill 9366fa8e95 Simplify printing for float and complex types 2018-01-28 15:58:34 +00:00
gingerBill 369db3a8e3 Add __print_type to runtime 2018-01-28 15:55:37 +00:00
gingerBill 8c360b2a3c Reduce type info data size in IR 2018-01-28 15:43:58 +00:00
gingerBill b66e7bed45 Improve min-dep for Type Info 2018-01-28 15:37:15 +00:00
gingerBill e919482aa8 Add ir_emit_store_union_variant to reduce alloca use 2018-01-28 15:09:07 +00:00
gingerBill dce45e7d58 Add ODIN_DEBUG 2018-01-28 14:42:22 +00:00
gingerBill 1a0877e965 Fix minimum dependency generation for foreign entities 2018-01-28 14:39:18 +00:00
gingerBill 0361a18551 Remove old math constants 2018-01-28 11:59:28 +00:00
gingerBill 83d90f1463 Extra check for type_info cycle checking 2018-01-28 09:51:52 +00:00
gingerBill f661ae9d09 Fix issue with proc group cycles #176 2018-01-28 09:19:23 +00:00
gingerBill bee4cb57f2 Fix printf bug #177 2018-01-28 09:13:29 +00:00
gingerBill 53b670b889 Merge branch 'master' of https://github.com/odin-lang/Odin 2018-01-28 08:59:31 +00:00
gingerBill e2600a3e44 Fix #178 2018-01-28 08:59:10 +00:00
gingerBill 25101b2ae0 Merge pull request #175 from ThisDrunkDane/windows.odin-adds
More file handling functions
2018-01-25 14:02:32 +00:00
Mikkel Hjortshoej 4e7867fcc1 More file handling functions 2018-01-25 00:00:34 +01:00
gingerBill 101ee64165 Merge pull request #174 from ThisDrunkDane/windows.odin-adds
Added stuff to windows.odin
2018-01-24 09:41:09 +00:00
Mikkel Hjortshoej 4c3e65791e added stuff to windows.odin 2018-01-24 07:26:29 +01:00
gingerBill a9c8031b61 Fix sync_windows.odin 2018-01-21 21:21:57 +00:00
gingerBill afb3033913 Change thread.odin to use a rawptr rather than any 2018-01-21 21:19:03 +00:00
gingerBill 2ad26640a2 Revert back to gb_memmove 2018-01-21 19:30:05 +00:00
gingerBill 2c0b08145f Fix nested defer blocks 2018-01-21 19:26:55 +00:00
gingerBill aa9c9eda9e Fix boolean casting 2018-01-21 18:41:21 +00:00
gingerBill 1353d61894 Minor parsing change 2018-01-21 16:45:29 +00:00
gingerBill 88ba6d8015 enum #export 2018-01-21 14:30:48 +00:00
gingerBill 8b288a2072 Reimplement opt stage 2018-01-20 16:16:59 +00:00
gingerBill 4e90644527 Remove timing for llvm-opt 2018-01-20 16:15:05 +00:00
gingerBill 6651b65373 Remove need for opt 2018-01-20 16:13:36 +00:00
gingerBill 705352099f Remove #endif 2018-01-20 16:10:26 +00:00
gingerBill 2e28c9d793 Cache type size/align; Improve speed of ir_print.cpp 2018-01-20 15:12:44 +00:00
gingerBill 2fe660a1d7 Fix empty union IR bug 2018-01-19 17:11:28 +00:00
gingerBill b03ce0e9b4 Modify implicit semicolon rules 2018-01-18 17:28:07 +00:00
gingerBill 386f5f596d Change to HeapAlloc et al on Windows 2018-01-18 13:11:51 +00:00
gingerBill add53228b2 -no-bounds-check 2018-01-18 12:22:27 +00:00
gingerBill d90008cc52 Add basic debug information needed for stepping over code 2018-01-18 12:12:18 +00:00
gingerBill dbf8f9ab38 Add extra comments for clarity 2018-01-17 21:22:45 +00:00
gingerBill 81a99cf67b Debug fix target triple and procedure positioning 2018-01-17 20:57:54 +00:00
gingerBill 876af6fb02 Modify boolean conversion in IR 2018-01-17 19:27:13 +00:00
gingerBill b3734a5f77 Add math/rand.odin 2018-01-17 19:09:22 +00:00
gingerBill 419ab6f00c Named return value act as variables; Code reorganization 2018-01-17 19:07:38 +00:00
gingerBill 5558b55e9f Fix ir_emit_store for booleans 2018-01-17 14:06:06 +00:00
gingerBill 4b14d608f4 Update sys/windows.odin to use Bool :: b32; rather than i32 2018-01-17 14:02:19 +00:00
gingerBill 9428d86f2b Specific sized booleans: b8, b16, b32, b64 2018-01-17 14:00:49 +00:00
gingerBill ddebf0daf2 Merge branch 'master' of https://github.com/odin-lang/Odin 2018-01-17 13:16:59 +00:00
gingerBill 3a44c62ecf Remove old "macro" parsing code 2018-01-17 13:16:43 +00:00
gingerBill 184efd4f49 Update demo for using in 2018-01-13 22:42:05 +00:00
gingerBill 6b3c4cc379 Remove u128 and i128 2018-01-13 22:26:37 +00:00
gingerBill 0b137e087c Fix mem.odin #173 2018-01-12 11:44:09 +00:00
gingerBill 37790c13a0 Fix issue #170 2018-01-10 21:17:09 +00:00
gingerBill 82057f08ce Fix issue #172 2018-01-10 21:13:20 +00:00
gingerBill 1553421e1a Fix typo in error 2018-01-01 22:15:43 +00:00
gingerBill f3ea109e6f Fix min/max for floats 2018-01-01 11:41:32 +00:00
gingerBill 90dbfe7660 Fix issue #167 regarding abs, min, and, max for floats 2017-12-27 20:35:50 +00:00
gingerBill 125bad3154 Fix 'llvm bool' emit store 2017-12-23 09:46:28 +00:00
gingerBill 30c83d6c81 Fix map internals 2017-12-23 09:30:40 +00:00
gingerBill 4f12c118a5 Fix Type info bug for 'llvm bool' 2017-12-23 09:06:49 +00:00
gingerBill 423775d50e Merge branch 'master' of https://github.com/odin-lang/Odin 2017-12-22 18:14:50 +00:00
gingerBill 860a5c3e86 "Fix" LLVM boolean bug (more like a bodge) 2017-12-22 18:14:35 +00:00
gingerBill 649e02f209 Add basic example to README.md 2017-12-22 11:29:33 +00:00
gingerBill b449305cc1 Fix free_map 2017-12-21 21:05:53 +00:00
gingerBill 49bee6bad0 Fix free_map 2017-12-21 21:01:28 +00:00
gingerBill ac277a1cce Revert map to be a value type and not a reference type
(Implement code for "const ref" parameters)
2017-12-21 20:59:23 +00:00
gingerBill a17310a83c Fix len, cap, comparison against nil for map 2017-12-18 20:43:02 +00:00
gingerBill b509946b13 Fix fallthrough within a nested block 2017-12-17 21:55:20 +00:00
gingerBill a69ea58388 map is internally backed by a pointer (i.e. a "reference type") 2017-12-17 19:25:35 +00:00
gingerBill 30530d058c Remove struct #ordered 2017-12-17 14:53:40 +00:00
gingerBill 436928d06a Fix "using in import" 2017-12-17 12:12:24 +00:00
gingerBill 32a502d14e using x in bar; 2017-12-17 11:44:26 +00:00
gingerBill 0d665c637f using in importation statements 2017-12-17 11:17:54 +00:00
gingerBill 1b6a14ac39 Fix lhs < rhs bug (#164) 2017-12-14 19:56:32 +00:00
gingerBill 367013f589 Change Map and PtrSet grow rate 2017-12-12 23:39:20 +00:00
gingerBill c980a30bad Merge branch 'checker-optimizations' into explicit-overloading
# Conflicts:
#	examples/demo.odin
2017-12-12 21:22:46 +00:00
gingerBill 78b459590c Print nil for nil procedures in fmt.odin 2017-12-12 21:21:55 +00:00
gingerBill 054e241033 Localize checker data 2017-12-12 20:23:36 +00:00
gingerBill f7e9649be4 Disable struct field reordering (for the time being) 2017-12-12 18:21:40 +00:00
gingerBill fd1f6ec75c Merge branch 'master' into explicit-overloading 2017-12-11 11:13:22 +00:00
gingerBill 6b0d7cb26c Fix issue #162 regarding empty unions 2017-12-11 11:08:02 +00:00
gingerBill 3aea08df78 Change how abs, min, max, and clamp are implemented for floats 2017-12-11 11:06:43 +00:00
gingerBill 3c6f90e552 Fix proc groups from import names 2017-12-10 11:35:11 +00:00
gingerBill 3703ca4df4 Explicit procedure group; Remove implicit procedure overloading 2017-12-09 18:11:36 +00:00
gingerBill 41b8281c73 Set type of a procedure grouping to nullptr 2017-12-06 11:13:00 +00:00
gingerBill acd1f83bd0 Fix procedure groupings 2017-12-06 11:11:53 +00:00
gingerBill ba8371104d Set procedure grouping type to t_invalid 2017-12-06 11:01:52 +00:00
gingerBill 991682e9fd Fix write_entire_file 2017-12-06 10:58:02 +00:00
gingerBill f0de994059 Make core library use procedure groupings rather than normal overloading 2017-12-04 22:01:51 +00:00
gingerBill ebb2a9812c Merge pull request #160 from thebirk/patch-1
Added skip for Entity_ProcedureGrouping
2017-12-04 15:07:09 +00:00
Aleksander Birkeland 265c05927f Added skip for Entity_ProcedureGrouping 2017-12-04 16:05:42 +01:00
gingerBill 05ad38ae2d Fix procedure grouping 2017-12-03 23:19:25 +00:00
gingerBill 596a2c8355 Procedure grouping foo :: proc[foo16, foo32]; 2017-12-03 23:03:40 +00:00
gingerBill 9f52b2c283 Update demo.odin 2017-12-03 22:28:54 +00:00
gingerBill 8035a407a6 Remove dead code 2017-12-03 20:59:48 +00:00
gingerBill 97760c3fa4 Fix union_tag_size; Fix constant array of array literal printing with scalar contents 2017-12-03 20:49:19 +00:00
gingerBill d75291097e &x.(type) 2017-11-30 23:09:21 +00:00
gingerBill db632b7e22 buffer_from_slice 2017-11-30 20:42:16 +00:00
gingerBill 1a75dfe075 Remove vector type (will be replaced by something else in the future) 2017-11-30 20:34:42 +00:00
gingerBill e00d88d82e Fix issue #157 2017-11-30 19:53:40 +00:00
gingerBill 04cce1826b Fix map IR bug 2017-11-28 23:46:01 +00:00
gingerBill cc28cda053 Fix issue #156 2017-11-28 22:49:34 +00:00
gingerBill cfabc0e61f Remove using in arrays; Remove _ non-exported struct fields
Start determining slow parts of the compiler
2017-11-28 22:12:33 +00:00
gingerBill 91b534d128 Fix transmute 2017-11-27 23:00:23 +00:00
gingerBill 3268f43340 Update ABI for basic types 2017-11-27 20:37:09 +00:00
gingerBill 05e374934d Change proc ABI for Odin specific types 2017-11-27 20:18:06 +00:00
gingerBill 3e1ff0ec67 Update fmt for runes; Add strings.contains_rune 2017-11-26 23:54:23 +00:00
gingerBill 65945dac09 Fix comparison against nil for slices 2017-11-26 22:49:31 +00:00
gingerBill 1608da2dc8 for key, val in some_map {}; for val, idx in some_array {} 2017-11-26 18:56:47 +00:00
gingerBill c340827381 Remove old slice procedures 2017-11-26 18:38:46 +00:00
gingerBill 74fa7ca25d New slice memory layout (ptr+len); byte 2017-11-26 18:36:46 +00:00
gingerBill 5a9223afda nil_allocator; Fix IR type checking assert; append_string 2017-11-26 15:25:45 +00:00
gingerBill febcd73323 Fix merge from essence cross compile #154 2017-11-26 11:11:29 +00:00
gingerBill df06236076 Merge pull request #154 from nakst/master
essence cross compile
2017-11-26 11:10:13 +00:00
Nakst b0d3fbba47 essence cross compile 2017-11-26 11:03:11 +00:00
gingerBill adb6c7637e Fix 'fallthrough' 2017-11-25 11:16:23 +00:00
gingerBill 425f83b17d Merge pull request #150 from zangent/master
Changed `string_has_extension` to `string_ends_with` and fix macOS target triple
2017-11-21 22:33:39 +00:00
gingerBill 976415ff9d Fix key lookup of pointer to map 2017-11-21 22:32:41 +00:00
Zachary Pierson 4d7fb3e8d6 Changed string_has_extension to string_ends_with.
Fixed macOS target triple.
2017-11-21 16:16:53 -06:00
gingerBill bcca3bf322 Remove target triple from windows 2017-11-19 16:55:24 +00:00
gingerBill 74aaa3408f Fix debug symbol generation 2017-11-19 16:45:12 +00:00
gingerBill 2a5beee88c Remove /SYMBOLS flag 2017-11-19 15:11:07 +00:00
gingerBill cec9f7abfe Add -debug command (still in development) 2017-11-19 15:06:56 +00:00
423 changed files with 142594 additions and 30822 deletions
+1
View File
@@ -0,0 +1 @@
*.odin linguist-language=Odin
+3
View File
@@ -0,0 +1,3 @@
# These are supported funding model platforms
patreon: gingerbill
+39
View File
@@ -0,0 +1,39 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
## Context
Please provide any relevant information about your setup. This is important in case the issue is not reproducible except for under certain conditions.
* Operating System:
* Please paste `odin version` output:
## Expected Behavior
Please describe the behavior you are expecting
## Current Behavior
What is the current behavior?
## Failure Information (for bugs)
Please help provide information about the failure if this is a bug. If it is not a bug, please remove the rest of this template.
### Steps to Reproduce
Please provide detailed steps for reproducing the issue.
1. step 1
2. step 2
3. you get it...
### Failure Logs
Please include any relevant log snippets or files here.
+17
View File
@@ -0,0 +1,17 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Additional context**
Add any other context or screenshots about the feature request here.
+64
View File
@@ -0,0 +1,64 @@
name: CI
on: [push, pull_request]
jobs:
build_linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Download LLVM
run: sudo apt-get install llvm-11 clang-11 llvm
- name: build odin
run: make release
- name: Odin run -llvm-api
run: ./odin run examples/demo/demo.odin -llvm-api
- name: Odin run
run: ./odin run examples/demo/demo.odin
- name: Odin check
run: ./odin check examples/demo/demo.odin -vet
build_macOS:
runs-on: macos-latest
steps:
- uses: actions/checkout@v1
- name: Download LLVM and setup PATH
run: |
brew install llvm@11
echo "/usr/local/opt/llvm/bin" >> $GITHUB_PATH
TMP_PATH=$(xcrun --show-sdk-path)/user/include
echo "CPATH=$TMP_PATH" >> $GITHUB_ENV
- name: build odin
run: make release
- name: Odin run
run: |
./odin run examples/demo/demo.odin
./odin run examples/demo/demo.odin -llvm-api
- name: Odin check
run: ./odin check examples/demo/demo.odin -vet
build_windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v1
- name: Download and unpack LLVM bins
shell: powershell
run: |
cd bin
$ProgressPreference = "SilentlyContinue";
Invoke-WebRequest -Uri https://github.com/odin-lang/Odin/releases/download/llvm-windows/llvm-binaries.zip -OutFile llvm-binaries.zip
7z x llvm-binaries.zip > $null
- name: build Odin
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
./build.bat 1
- name: Odin run
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin run examples/demo/demo.odin
- name: Odin check
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin check examples/demo/demo.odin -vet
+152
View File
@@ -0,0 +1,152 @@
name: Nightly
on:
workflow_dispatch:
schedule:
- cron: 0 20 * * *
jobs:
build_windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v1
- name: Install cURL
run: choco install curl
- name: Download and unpack LLVM bins
shell: cmd
run: |
cd bin
curl -sL https://github.com/odin-lang/Odin/releases/download/llvm-windows/llvm-binaries.zip --output llvm-binaries.zip
7z x llvm-binaries.zip > nul
rm -f llvm-binaries.zip
- name: build Odin
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
./build.bat 1 1
- name: Odin run
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin run examples/demo/demo.odin
- name: Copy artifacts
run: |
rm bin/llvm/windows/LLVM-C.lib
mkdir dist
cp odin.exe dist
cp LLVM-C.dll dist
cp -r shared dist
cp -r core dist
cp -r bin dist
cp -r examples dist
- name: Upload artifact
uses: actions/upload-artifact@v1
with:
name: windows_artifacts
path: dist
build_ubuntu:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: (Linux) Download LLVM
run: sudo apt-get install llvm-11 clang-11 llvm
- name: build odin
run: make nightly
- name: Odin run -llvm-api
run: ./odin run examples/demo/demo.odin -llvm-api
- name: Odin run
run: ./odin run examples/demo/demo.odin
- name: Copy artifacts
run: |
mkdir dist
cp odin dist
cp -r shared dist
cp -r core dist
cp -r examples dist
- name: Upload artifact
uses: actions/upload-artifact@v1
with:
name: ubuntu_artifacts
path: dist
build_macos:
runs-on: macOS-latest
steps:
- uses: actions/checkout@v1
- name: Download LLVM and setup PATH
run: |
brew install llvm
echo "/usr/local/opt/llvm/bin" >> $GITHUB_PATH
TMP_PATH=$(xcrun --show-sdk-path)/user/include
echo "CPATH=$TMP_PATH" >> $GITHUB_ENV
- name: build odin
run: make nightly
- name: Odin run -llvm-api
run: ./odin run examples/demo/demo.odin -llvm-api
- name: Odin run
run: ./odin run examples/demo/demo.odin
- name: Copy artifacts
run: |
mkdir dist
cp odin dist
cp -r shared dist
cp -r core dist
cp -r examples dist
- name: Upload artifact
uses: actions/upload-artifact@v1
with:
name: macos_artifacts
path: dist
upload_b2:
runs-on: [ubuntu-latest]
needs: [build_windows, build_macos, build_ubuntu]
steps:
- uses: actions/checkout@v1
- uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: Install B2 CLI
shell: bash
run: |
python -m pip install --upgrade pip
pip install --upgrade b2
- name: Display Python version
run: python -c "import sys; print(sys.version)"
- name: Download Windows artifacts
uses: actions/download-artifact@v1
with:
name: windows_artifacts
- name: Download Ubuntu artifacts
uses: actions/download-artifact@v1
with:
name: ubuntu_artifacts
- name: Download macOS artifacts
uses: actions/download-artifact@v1
with:
name: macos_artifacts
- name: Create archives and upload
shell: bash
env:
APPID: ${{ secrets.B2_APPID }}
APPKEY: ${{ secrets.B2_APPKEY }}
BUCKET: ${{ secrets.B2_BUCKET }}
DAYS_TO_KEEP: ${{ secrets.B2_DAYS_TO_KEEP }}
run: |
b2 authorize-account "$APPID" "$APPKEY"
chmod +x ./ci/upload_create_nightly.sh
./ci/upload_create_nightly.sh "$BUCKET" windows-amd64 windows_artifacts/
./ci/upload_create_nightly.sh "$BUCKET" ubuntu-amd64 ubuntu_artifacts/
./ci/upload_create_nightly.sh "$BUCKET" macos-amd64 macos_artifacts/
python3 ci/delete_old_binaries.py "$BUCKET" "$DAYS_TO_KEEP"
python3 ci/create_nightly_json.py "$BUCKET" > nightly.json
b2 upload-file "$BUCKET" nightly.json nightly.json
b2 clear-account
+7 -2
View File
@@ -18,11 +18,14 @@ bld/
[Bb]in/
[Oo]bj/
[Ll]og/
![Cc]ore/[Ll]og/
# Visual Studio 2015 cache/options directory
.vs/
# Visual Studio Code options directory
.vscode/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
demo
# MSTest test Results
[Tt]est[Rr]esult*/
@@ -264,10 +267,12 @@ bin/
odin
odin.dSYM
# shared collection
shared/
# temp files
* .ll
*.bc
*.ll
*.sublime-workspace
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2016-2017 Ginger Bill. All rights reserved.
Copyright (c) 2016-2020 Ginger Bill. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
BIN
View File
Binary file not shown.
+17 -7
View File
@@ -1,24 +1,34 @@
DISABLED_WARNINGS=-Wno-switch -Wno-writable-strings -Wno-tautological-compare -Wno-macro-redefined #-Wno-pointer-sign -Wno-tautological-constant-out-of-range-compare
GIT_SHA=$(shell git rev-parse --short HEAD)
DISABLED_WARNINGS=-Wno-switch -Wno-pointer-sign -Wno-tautological-constant-out-of-range-compare -Wno-tautological-compare -Wno-macro-redefined
LDFLAGS=-pthread -ldl -lm -lstdc++
CFLAGS=-std=c++11
CFLAGS=-std=c++14 -DGIT_SHA=\"$(GIT_SHA)\"
CC=clang
OS=$(shell uname)
ifeq ($(OS), DARWIN)
LDFLAGS=$(LDFLAGS) -liconv
ifeq ($(OS), Darwin)
LDFLAGS:=$(LDFLAGS) -liconv
CFLAGS:=$(CFLAGS) $(shell llvm-config --cxxflags --ldflags) -DLLVM_BACKEND_SUPPORT -DUSE_NEW_LLVM_ABI_SYSTEM
LDFLAGS:=$(LDFLAGS) -lLLVM-C
endif
ifeq ($(OS), Linux)
CFLAGS:=$(CFLAGS) $(shell llvm-config-11 --cxxflags --ldflags) -DLLVM_BACKEND_SUPPORT -DUSE_NEW_LLVM_ABI_SYSTEM
LDFLAGS:=$(LDFLAGS) $(shell llvm-config-11 --libs core native --system-libs)
endif
all: debug demo
demo:
./odin run examples/demo.odin
./odin run examples/demo/demo.odin
debug:
$(CC) src/main.cpp $(DISABLED_WARNINGS) $(CFLAGS) -g $(LDFLAGS) -o odin
release:
$(CC) src/main.cpp $(DISABLED_WARNINGS) $(CFLAGS) -O3 -march=native $(LDFLAGS) -o odin
nightly:
$(CC) src/main.cpp $(DISABLED_WARNINGS) $(CFLAGS) -DNIGHTLY -O3 $(LDFLAGS) -o odin
+64
View File
@@ -0,0 +1,64 @@
# The Proposal Process
## Introduction
The Odin project's development process is driven by design and pragmatism. Significant changes to the language, libraries, or tools _must_ be first discussed, and maybe formally documented, before they can be implemented.
This document describes the process for proposing, documenting, and implementing changes to the Odin project.
## The Proposal Process
The proposal process is the process for reviewing a proposal and reaching a decision about whether to accept or decline the proposal.
1. [Ginger Bill](https://github.com/gingerBill) is [BDFL](https://wikipedia.org/wiki/Benevolent_dictator_for_life) and significant changes _must_ be passed by him.
2. The proposal author creates a brief issue describing the proposal.
Note: There is no need for a design document at this point.<br>
Note: A non-proposal issue can be turned into a proposal by simply adding the _proposal_ label.
3. A discussion on the issue tracker will classify the proposal into one of three outcomes:
* Accept proposal
* Decline proposal
* Ask for a design document.
If the proposal is accepted or declined, the process is done. Otherwise the discussion around the process is expected to identify issues that ought to be addressed in a more detailed design.
4. The proposal author writes a design document to work out details of the proposed design and address the concerns raised in the initial discussion.
5. Once comments and revisions on the design document calm, there is a final discussion on the issue, to reach one of two outcomes:
* Accept proposal
* Decline proposal
After the proposal is accepted or declined, implementation of the proposal proceeds in the same way as any other contribution to the project.
## Design Documents
The design document should follow this template:
```
# Proposal: [Title]
Author(s): [Author Name, Co-Author Name]
Last updated: [Date ISO-8601]
Discussion at https://github.com/odin-lang/Odin/issues/######
## Abstract
## Background
## Proposal
## Rationale
## Compatibility
## Implementation
```
## Help
If you need help with this process, please contact an Odin contributor by posting an issue to the [issue tracker](https://github.com/odin-lang/Odin/issues).
+152 -49
View File
@@ -1,15 +1,159 @@
<img src="misc/logo-slim.png" alt="Odin logo" height="74">
<p align="center">
<img src="misc/logo-slim.png" alt="Odin logo" height="120">
<br/>
A fast, concise, readable, pragmatic and open sourced programming language.
<br/>
<br/>
<a href="https://github.com/odin-lang/odin/releases/latest">
<img src="https://img.shields.io/github/release/odin-lang/odin.svg">
</a>
<a href="https://github.com/odin-lang/odin/releases/latest">
<img src="https://img.shields.io/badge/platforms-Windows%20|%20Linux%20|%20macOS-green.svg">
</a>
<br>
<a href="https://discord.gg/hnwN2Rj">
<img src="https://img.shields.io/discord/568138951836172421?logo=discord">
</a>
<a href="https://github.com/odin-lang/odin/actions">
<img src="https://github.com/odin-lang/odin/workflows/CI/badge.svg?branch=master&event=push">
</a>
</p>
# The Odin Programming Language
The Odin programming language is fast, concise, readable, pragmatic and open sourced. It is designed with the intent of replacing C with the following goals:
The Odin programming language is fast, concise, readable, pragmatic and open sourced. It is designed with the intent of creating an alternative to C with the following goals:
* simplicity
* high performance
* built for modern systems
* joy of programming
* metaprogramming
Website: [https://odin.handmade.network/](https://odin.handmade.network/)
Website: [https://odin-lang.org/](https://odin-lang.org/)
```odin
package main
import "core:fmt"
main :: proc() {
program := "+ + * 😃 - /";
accumulator := 0;
for token in program {
switch token {
case '+': accumulator += 1;
case '-': accumulator -= 1;
case '*': accumulator *= 2;
case '/': accumulator /= 2;
case '😃': accumulator *= accumulator;
case: // Ignore everything else
}
}
fmt.printf("The program \"%s\" calculates the value %d\n",
program, accumulator);
}
```
## Documentation
#### [Getting Started](https://odin-lang.org/docs/install)
Instructions for downloading and installing the Odin compiler and libraries.
### Learning Odin
#### [Overview of Odin](https://odin-lang.org/docs/overview)
An overview of the Odin programming language.
#### [Frequently Asked Questions (FAQ)](https://odin-lang.org/docs/faq)
Answers to common questions about Odin.
#### [The Odin Wiki](https://github.com/odin-lang/Odin/wiki)
A wiki maintained by the Odin community.
#### [Odin Discord](https://discord.gg/sVBPHEv)
Get live support and talk with other odiners on the Odin Discord.
### References
#### [Language Specification](https://odin-lang.org/ref/spec)
The official Odin Language specification.
### Articles
#### [The Odin Blog](https://odin-lang.org/blog)
The official blog of the Odin programming language, featuring announcements, news, and in-depth articles by the Odin team and guests.
## Setup
Odin only supports x86-64/amd64 at the moment (64-bit), relies on LLVM for code generation and an external linker.
In addition, the following platform-specific steps are necessary:
- Windows
* Have Visual Studio installed (MSVC 2010 or later, for the linker)
* Have a copy of `opt.exe` and `llc.exe` in `Odin/bin`. Pre-built Windows binaries can be found [here](https://github.com/odin-lang/Odin/releases/tag/llvm-windows) and *must* be explicitly copied
* Open a valid command prompt:
* **Basic:** run the `x64 Native Tools Command Prompt for VS2017` shortcut bundled with VS 2017, or
* **Advanced:** run `vcvarsall.bat x64` from a blank `cmd` session
- MacOS
* Have LLVM explicitly installed (`brew install llvm`)
* Have XCode installed (version X.X or later, for linking)
* Make sure the LLVM binaries and the linker are added to your `$PATH` environmental variable
- GNU/Linux
* Have LLVM installed (opt/llc)
* Have Clang installed (version X.X or later, for linking)
* Make sure the LLVM binaries and the linker are added to your `$PATH` environmental variable
Then build the compiler by calling `build.bat` (Windows) or `make` (Linux/MacOS). This will automatically run the demo program if successful.
**Notes for Linux:**: The compiler currently relies on the `core` and `shared` library collection being relative to the compiler executable. Installing the compiler in the usual sense (to `/usr/local/bin` or similar) is therefore not as straight forward as you need to make sure the mentioned libraries are available. As a result, it is recommended to simply explicitly invoke the compiler with `/path/to/odin` in your preferred build system, or add `/path/to/odin` to `$PATH`.
Please read the [Getting Started Guide](https://github.com/odin-lang/Odin/wiki#getting-started-with-odin) for more information.
## Requirements to build and run
Please read the [Getting Started Guide](https://github.com/odin-lang/Odin/wiki#getting-started-with-odin).
- Windows
* x86-64/amd64
* MSVC 2010 installed (C++11 support)
* [LLVM binaries](https://github.com/odin-lang/Odin/releases/tag/llvm-windows) for `opt.exe`, `llc.exe`, and `lld-link.exe`
* Requires MSVC's link.exe as the linker
* run `vcvarsall.bat` to setup the path
- MacOS
* x86-64/amd64
* LLVM explicitly installed (`brew install llvm`)
* XCode installed (for the linker)
- GNU/Linux
* x86-64/amd64
* Build tools (ld)
* LLVM installed
* Clang installed (temporary - this is Calling the linker for now)
- FreeBSD
* x86-64/amd64
* Build tools (ld)
* LLVM installed
* Clang installed (temporary - this is Calling the linker for now)
Other platforms may be supported but are experimental for the time being.
## Warnings
* The Odin compiler is still in development.
## Demonstrations:
* First Talk & Demo
@@ -22,49 +166,8 @@ Website: [https://odin.handmade.network/](https://odin.handmade.network/)
* [when, for & procedure overloading](https://www.youtube.com/watch?v=OzeOekzyZK8)
* [Context Types, Unexported Entities, Labelled Branches](https://www.youtube.com/watch?v=CkHVwT1Qk-g)
* [Bit Fields, i128 & u128, Syntax Changes](https://www.youtube.com/watch?v=NlTutcLyF64)
* [Default and Named Arguments; Explicit Parametric Polymorphism](https://www.youtube.com/watch?v=-XQZE6S6zUU)
* [Loadsachanges](https://www.youtube.com/watch?v=ar0vFMoMtrI)
* [Packages, Bit Sets, cstring](https://youtu.be/b8bJbjiXZrQ)
- [Q&A](https://youtu.be/5jmxyIfyyTk)
## Requirements to build and run
- Windows
* x86-64
* MSVC 2015 installed (C++11 support)
* [LLVM binaries](https://github.com/gingerBill/Odin/releases/tag/llvm-4.0-windows) for `opt.exe` and `llc.exe`
* Requires MSVC's link.exe as the linker
* run `vcvarsall.bat` to setup the path
- MacOS
* x86-64
* LLVM explicitly installed (`brew install llvm`)
* XCode installed (for the linker)
- GNU/Linux
* x86-64
* Build tools (ld)
* LLVM installed
* Clang installed (temporary - this is Calling the linker for now)
## Warnings
* This is still highly in development and the language's design is quite volatile.
* Syntax is not fixed.
## Roadmap
Not in any particular order and not be implemented
* Compile Time Execution (CTE)
- More metaprogramming madness
- Compiler as a library
- AST inspection and modification
* CTE-based build system
* Replace LLVM backend with my own custom backend
* Improve SSA design to accommodate for lowering to a "bytecode"
* SSA optimizations
* Documentation Generator for "Entities"
* Multiple Architecture support
* Debug Information
- pdb format too
* Command Line Tooling
* Compiler Internals:
- Big numbers library
- Multithreading for performance increase
+30
View File
@@ -0,0 +1,30 @@
# The Odin Programming Language
## Setup
Odin only supports x86-64 at the moment (64-bit), relies on LLVM for code generation and an external linker.
In addition, the following platform-specific steps are necessary:
- Windows
* Have Visual Studio installed (MSVC 2010 or later, for the linker)
* Have a copy of `opt.exe` and `llc.exe` in `Odin/bin`. Pre-built Windows binaries can be found [here](https://github.com/odin-lang/Odin/releases/tag/llvm-windows) and *must* be explicitly copied
* Open a valid command prompt:
* **Basic:** run the `x64 Native Tools Command Prompt for VS2017` shortcut bundled with VS 2017, or
* **Advanced:** run `vcvarsall.bat x64` from a blank `cmd` session
- MacOS
* Have LLVM explicitly installed (`brew install llvm`)
* Have XCode installed (version X.X or later, for linking)
* Make sure the LLVM binaries and the linker are added to your `$PATH` environmental variable
- GNU/Linux
* Have LLVM installed (opt/llc)
* Have Clang installed (version X.X or later, for linking)
* Make sure the LLVM binaries and the linker are added to your `$PATH` environmental variable
Then build the compiler by calling `build.bat` (Windows) or `make` (Linux/MacOS). This will automatically run the demo program if successful.
**Notes for Linux:**: The compiler currently relies on the `core` and `shared` library collection being relative to the compiler executable. Installing the compiler in the usual sense (to `/usr/local/bin` or similar) is therefore not as straight forward as you need to make sure the mentioned libraries are available. As a result, it is recommended to simply explicitly invoke the compiler with `/path/to/odin` in your preferred build system, or add `/path/to/odin` to `$PATH`.
Please read the [Getting Started Guide](https://github.com/odin-lang/Odin/wiki#getting-started-with-odin) for more information.
Binary file not shown.
Executable
+37
View File
@@ -0,0 +1,37 @@
#!/usr/bin/env bash
release_mode=$1
warnings_to_disable="-std=c++11 -Wno-switch"
libraries="-pthread -ldl -lm -lstdc++ -lz -lcurses -lxml2"
other_args="-DLLVM_BACKEND_SUPPORT"
compiler="clang"
if [ -z "$release_mode" ]; then release_mode="0"; fi
if [ "$release_mode" -eq "0" ]; then
other_args="${other_args} -g"
fi
if [ "$release_mode" -eq "1" ]; then
other_args="${other_args} -O3 -march=native"
fi
if [[ "$(uname)" == "Darwin" ]]; then
# Set compiler to clang on MacOS
# MacOS provides a symlink to clang called gcc, but it's nice to be explicit here.
compiler="clang"
llvm_config_flags="--cxxflags --ldflags"
# llvm_config_flags="${llvm_config_flags} --link-static"
llvm_config="llvm-config ${llvm_config_flags}"
other_args="${other_args} -liconv"
other_args="${other_args} `${llvm_config}` -lLLVM-C"
elif [[ "$(uname)" == "FreeBSD" ]]; then
compiler="clang"
fi
${compiler} src/main.cpp ${warnings_to_disable} ${libraries} ${other_args} -o odin
# && ./odin run examples/demo/demo.odin -llvm-api
+31 -14
View File
@@ -4,28 +4,46 @@
set exe_name=odin.exe
:: Debug = 0, Release = 1
set release_mode=0
set compiler_flags= -nologo -Oi -TP -fp:fast -fp:except- -Gm- -MP -FC -GS- -EHsc- -GR-
if "%1" == "1" (
set release_mode=1
) else if "%1" == "release" (
set release_mode=1
) else (
set release_mode=0
)
:: Normal = 0, CI Nightly = 1
if "%2" == "1" (
set nightly=1
) else (
set nightly=0
)
set compiler_flags= -nologo -Oi -TP -fp:precise -Gm- -MP -FC -EHsc- -GR- -GF
set compiler_defines= -DLLVM_BACKEND_SUPPORT -DUSE_NEW_LLVM_ABI_SYSTEM
for /f %%i in ('git rev-parse --short HEAD') do set GIT_SHA=%%i
if %ERRORLEVEL% equ 0 set compiler_defines=%compiler_defines% -DGIT_SHA=\"%GIT_SHA%\"
if %nightly% equ 1 set compiler_defines=%compiler_defines% -DNIGHTLY
if %release_mode% EQU 0 ( rem Debug
set compiler_flags=%compiler_flags% -Od -MDd -Z7
rem -DDISPLAY_TIMING
) else ( rem Release
set compiler_flags=%compiler_flags% -O2 -MT -Z7
set compiler_defines=%compiler_defines% -DNO_ARRAY_BOUNDS_CHECK
)
set compiler_warnings= ^
-W4 -WX ^
-wd4100 -wd4101 -wd4127 -wd4189 ^
-wd4201 -wd4204 -wd4244 ^
-wd4306 ^
-wd4201 -wd4204 ^
-wd4456 -wd4457 -wd4480 ^
-wd4505 -wd4512 -wd4550
-wd4512
set compiler_includes=
set libs= ^
kernel32.lib
rem "src\dyncall\lib\*.lib"
kernel32.lib ^
bin\llvm\windows\LLVM-C.lib
set linker_flags= -incremental:no -opt:ref -subsystem:console
@@ -35,18 +53,17 @@ if %release_mode% EQU 0 ( rem Debug
set linker_flags=%linker_flags% -debug
)
set compiler_settings=%compiler_includes% %compiler_flags% %compiler_warnings%
set compiler_settings=%compiler_includes% %compiler_flags% %compiler_warnings% %compiler_defines%
set linker_settings=%libs% %linker_flags%
del *.pdb > NUL 2> NUL
del *.ilk > NUL 2> NUL
cl %compiler_settings% "src\main.cpp" ^
/link %linker_settings% -OUT:%exe_name% ^
&& odin run examples/demo.odin -opt=0
rem && odin docs core/fmt.odin
cl %compiler_settings% "src\main.cpp" /link %linker_settings% -OUT:%exe_name%
if %errorlevel% neq 0 goto end_of_build
if %release_mode% EQU 0 odin run examples/demo/demo.odin
del *.obj > NUL 2> NUL
:end_of_build
+5 -3
View File
@@ -1,8 +1,8 @@
#!/bin/bash
#!/usr/bin/env bash
release_mode=$1
warnings_to_disable="-std=c++11 -Wno-switch -Wno-pointer-sign -Wno-tautological-constant-out-of-range-compare -Wno-tautological-compare -Wno-macro-redefined -Wno-writable-strings"
warnings_to_disable="-std=c++11 -Wno-switch -Wno-pointer-sign -Wno-tautological-constant-out-of-range-compare -Wno-tautological-compare -Wno-macro-redefined"
libraries="-pthread -ldl -lm -lstdc++"
other_args=""
compiler="clang"
@@ -23,6 +23,8 @@ if [[ "$(uname)" == "Darwin" ]]; then
compiler="clang"
other_args="${other_args} -liconv"
elif [[ "$(uname)" == "FreeBSD" ]]; then
compiler="clang"
fi
${compiler} src/main.cpp ${warnings_to_disable} ${libraries} ${other_args} -o odin && ./odin run examples/demo.odin
${compiler} src/main.cpp ${warnings_to_disable} ${libraries} ${other_args} -o odin && ./odin run examples/demo/demo.odin
+51
View File
@@ -0,0 +1,51 @@
import subprocess
import sys
import json
import datetime
import urllib.parse
import sys
def main():
files_by_date = {}
bucket = sys.argv[1]
files_lines = execute_cli(f"b2 ls --long {bucket} nightly").split("\n")
for x in files_lines:
parts = x.split(" ", 1)
if parts[0]:
json_str = execute_cli(f"b2 get-file-info {parts[0]}")
data = json.loads(json_str)
name = remove_prefix(data['fileName'], "nightly/")
url = f"https://f001.backblazeb2.com/file/{bucket}/nightly/{urllib.parse.quote_plus(name)}"
sha1 = data['contentSha1']
size = int(data['contentLength'])
ts = int(data['fileInfo']['src_last_modified_millis'])
date = datetime.datetime.fromtimestamp(ts/1000).strftime('%Y-%m-%d')
if date not in files_by_date.keys():
files_by_date[date] = []
files_by_date[date].append({
'name': name,
'url': url,
'sha1': sha1,
'sizeInBytes': size,
})
now = datetime.datetime.utcnow().isoformat()
print(json.dumps({
'last_updated' : now,
'files': files_by_date
}, sort_keys=True, indent=4))
def remove_prefix(text, prefix):
return text[text.startswith(prefix) and len(prefix):]
def execute_cli(command):
sb = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
return sb.stdout.read().decode("utf-8");
if __name__ == '__main__':
sys.exit(main())
+34
View File
@@ -0,0 +1,34 @@
import subprocess
import sys
import json
import datetime
import urllib.parse
import sys
def main():
files_by_date = {}
bucket = sys.argv[1]
days_to_keep = int(sys.argv[2])
print(f"Looking for binaries to delete older than {days_to_keep} days")
files_lines = execute_cli(f"b2 ls --long --versions {bucket} nightly").split("\n")
for x in files_lines:
parts = [y for y in x.split(' ') if y]
if parts and parts[0]:
date = datetime.datetime.strptime(parts[2], '%Y-%m-%d').replace(hour=0, minute=0, second=0, microsecond=0)
now = datetime.datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0)
delta = now - date
if delta.days > days_to_keep:
print(f'Deleting {parts[5]}')
execute_cli(f'b2 delete-file-version {parts[0]}')
def execute_cli(command):
sb = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
return sb.stdout.read().decode("utf-8");
if __name__ == '__main__':
sys.exit(main())
+13
View File
@@ -0,0 +1,13 @@
#!/bin/bash
bucket=$1
platform=$2
artifact=$3
now=$(date +'%Y-%m-%d')
filename="odin-$platform-nightly+$now.zip"
echo "Creating archive $filename from $artifact and uploading to $bucket"
7z a -bd "output/$filename" -r "$artifact"
b2 upload-file --noProgress "$bucket" "output/$filename" "nightly/$filename"
-1056
View File
File diff suppressed because it is too large Load Diff
-110
View File
@@ -1,110 +0,0 @@
#shared_global_scope
@(link_name="__multi3")
__multi3 :: proc "c" (a, b: u128) -> u128 {
bits_in_dword_2 :: size_of(i64) * 4;
lower_mask :: u128(~u64(0) >> bits_in_dword_2);
when ODIN_ENDIAN == "big" {
TWords :: struct #raw_union {
all: u128,
using _: struct {lo, hi: u64},
};
} else {
TWords :: struct #raw_union {
all: u128,
using _: struct {hi, lo: u64},
};
}
r: TWords;
t: u64;
r.lo = u64(a & lower_mask) * u64(b & lower_mask);
t = r.lo >> bits_in_dword_2;
r.lo &= u64(lower_mask);
t += u64(a >> bits_in_dword_2) * u64(b & lower_mask);
r.lo += u64(t & u64(lower_mask)) << bits_in_dword_2;
r.hi = t >> bits_in_dword_2;
t = r.lo >> bits_in_dword_2;
r.lo &= u64(lower_mask);
t += u64(b >> bits_in_dword_2) * u64(a & lower_mask);
r.lo += u64(t & u64(lower_mask)) << bits_in_dword_2;
r.hi += t >> bits_in_dword_2;
r.hi += u64(a >> bits_in_dword_2) * u64(b >> bits_in_dword_2);
return r.all;
}
@(link_name="__umodti3")
__u128_mod :: proc "c" (a, b: u128) -> u128 {
r: u128;
__u128_quo_mod(a, b, &r);
return r;
}
@(link_name="__udivti3")
__u128_quo :: proc "c" (a, b: u128) -> u128 {
return __u128_quo_mod(a, b, nil);
}
@(link_name="__modti3")
__i128_mod :: proc "c" (a, b: i128) -> i128 {
r: i128;
__i128_quo_mod(a, b, &r);
return r;
}
@(link_name="__divti3")
__i128_quo :: proc "c" (a, b: i128) -> i128 {
return __i128_quo_mod(a, b, nil);
}
@(link_name="__divmodti4")
__i128_quo_mod :: proc "c" (a, b: i128, rem: ^i128) -> (quo: i128) {
s: i128;
s = b >> 127;
b = (b~s) - s;
s = a >> 127;
b = (a~s) - s;
uquo: u128;
urem := __u128_quo_mod(transmute(u128)a, transmute(u128)b, &uquo);
iquo := transmute(i128)uquo;
irem := transmute(i128)urem;
iquo = (iquo~s) - s;
irem = (irem~s) - s;
if rem != nil do rem^ = irem;
return iquo;
}
@(link_name="__udivmodti4")
__u128_quo_mod :: proc "c" (a, b: u128, rem: ^u128) -> (quo: u128) {
alo := u64(a);
blo := u64(b);
if b == 0 {
if rem != nil do rem^ = 0;
return u128(alo/blo);
}
r, d, x, q: u128 = a, b, 1, 0;
for r >= d && (d>>127)&1 == 0 {
x <<= 1;
d <<= 1;
}
for x != 0 {
if r >= d {
r -= d;
q |= x;
}
x >>= 1;
d >>= 1;
}
if rem != nil do rem^ = r;
return q;
}
-102
View File
@@ -1,102 +0,0 @@
// TODO(bill): Use assembly instead here to implement atomics
// Inline vs external file?
when ODIN_OS == "windows" {
import win32 "core:sys/windows.odin"
}
_ :: compile_assert(ODIN_ARCH == "amd64"); // TODO(bill): x86 version
yield_thread :: proc() { win32.mm_pause(); }
mfence :: proc() { win32.read_write_barrier(); }
sfence :: proc() { win32.write_barrier(); }
lfence :: proc() { win32.read_barrier(); }
load :: proc(a: ^i32) -> i32 {
return a^;
}
store :: proc(a: ^i32, value: i32) {
a^ = value;
}
compare_exchange :: proc(a: ^i32, expected, desired: i32) -> i32 {
return win32.interlocked_compare_exchange(a, desired, expected);
}
exchanged :: proc(a: ^i32, desired: i32) -> i32 {
return win32.interlocked_exchange(a, desired);
}
fetch_add :: proc(a: ^i32, operand: i32) -> i32 {
return win32.interlocked_exchange_add(a, operand);
}
fetch_and :: proc(a: ^i32, operand: i32) -> i32 {
return win32.interlocked_and(a, operand);
}
fetch_or :: proc(a: ^i32, operand: i32) -> i32 {
return win32.interlocked_or(a, operand);
}
spin_lock :: proc(a: ^i32, time_out: int) -> bool { // NOTE(bill) time_out = -1 as default
old_value := compare_exchange(a, 1, 0);
counter := 0;
for old_value != 0 && (time_out < 0 || counter < time_out) {
counter += 1;
yield_thread();
old_value = compare_exchange(a, 1, 0);
mfence();
}
return old_value == 0;
}
spin_unlock :: proc(a: ^i32) {
store(a, 0);
mfence();
}
try_acquire_lock :: proc(a: ^i32) -> bool {
yield_thread();
old_value := compare_exchange(a, 1, 0);
mfence();
return old_value == 0;
}
load :: proc(a: ^i64) -> i64 {
return a^;
}
store :: proc(a: ^i64, value: i64) {
a^ = value;
}
compare_exchange :: proc(a: ^i64, expected, desired: i64) -> i64 {
return win32.interlocked_compare_exchange64(a, desired, expected);
}
exchanged :: proc(a: ^i64, desired: i64) -> i64 {
return win32.interlocked_exchange64(a, desired);
}
fetch_add :: proc(a: ^i64, operand: i64) -> i64 {
return win32.interlocked_exchange_add64(a, operand);
}
fetch_and :: proc(a: ^i64, operand: i64) -> i64 {
return win32.interlocked_and64(a, operand);
}
fetch_or :: proc(a: ^i64, operand: i64) -> i64 {
return win32.interlocked_or64(a, operand);
}
spin_lock :: proc(a: ^i64, time_out: int) -> bool { // NOTE(bill) time_out = -1 as default
old_value := compare_exchange(a, 1, 0);
counter := 0;
for old_value != 0 && (time_out < 0 || counter < time_out) {
counter += 1;
yield_thread();
old_value = compare_exchange(a, 1, 0);
mfence();
}
return old_value == 0;
}
spin_unlock :: proc(a: ^i64) {
store(a, 0);
mfence();
}
try_acquire_lock :: proc(a: ^i64) -> bool {
yield_thread();
old_value := compare_exchange(a, 1, 0);
mfence();
return old_value == 0;
}
-328
View File
@@ -1,328 +0,0 @@
U8_MIN :: u8(0);
U16_MIN :: u16(0);
U32_MIN :: u32(0);
U64_MIN :: u64(0);
U128_MIN :: u128(0);
U8_MAX :: ~u8(0);
U16_MAX :: ~u16(0);
U32_MAX :: ~u32(0);
U64_MAX :: ~u64(0);
U128_MAX :: ~u128(0);
I8_MIN :: i8( ~u8(0) >> 1);
I16_MIN :: i16( ~u16(0) >> 1);
I32_MIN :: i32( ~u32(0) >> 1);
I64_MIN :: i64( ~u64(0) >> 1);
I128_MIN :: i128(~u128(0) >> 1);
I8_MAX :: -I8_MIN - 1;
I16_MAX :: -I16_MIN - 1;
I32_MAX :: -I32_MIN - 1;
I64_MAX :: -I64_MIN - 1;
I128_MAX :: -I128_MIN - 1;
foreign __llvm_core {
@(link_name="llvm.ctpop.i8") __llvm_ctpop :: proc(u8) -> u8 ---;
@(link_name="llvm.ctpop.i8") __llvm_ctpop :: proc(i8) -> i8 ---;
@(link_name="llvm.ctpop.i16") __llvm_ctpop :: proc(u16) -> u16 ---;
@(link_name="llvm.ctpop.i16") __llvm_ctpop :: proc(i16) -> i16 ---;
@(link_name="llvm.ctpop.i32") __llvm_ctpop :: proc(u32) -> u32 ---;
@(link_name="llvm.ctpop.i32") __llvm_ctpop :: proc(i32) -> i32 ---;
@(link_name="llvm.ctpop.i64") __llvm_ctpop :: proc(u64) -> u64 ---;
@(link_name="llvm.ctpop.i64") __llvm_ctpop :: proc(i64) -> i64 ---;
@(link_name="llvm.ctpop.i128") __llvm_ctpop :: proc(u128) -> u128 ---;
@(link_name="llvm.ctpop.i128") __llvm_ctpop :: proc(i128) -> i128 ---;
@(link_name="llvm.ctlz.i8") __llvm_ctlz :: proc(u8, bool) -> u8 ---;
@(link_name="llvm.ctlz.i8") __llvm_ctlz :: proc(i8, bool) -> i8 ---;
@(link_name="llvm.ctlz.i16") __llvm_ctlz :: proc(u16, bool) -> u16 ---;
@(link_name="llvm.ctlz.i16") __llvm_ctlz :: proc(i16, bool) -> i16 ---;
@(link_name="llvm.ctlz.i32") __llvm_ctlz :: proc(u32, bool) -> u32 ---;
@(link_name="llvm.ctlz.i32") __llvm_ctlz :: proc(i32, bool) -> i32 ---;
@(link_name="llvm.ctlz.i64") __llvm_ctlz :: proc(u64, bool) -> u64 ---;
@(link_name="llvm.ctlz.i64") __llvm_ctlz :: proc(i64, bool) -> i64 ---;
@(link_name="llvm.ctlz.i128") __llvm_ctlz :: proc(u128, bool) -> u128 ---;
@(link_name="llvm.ctlz.i128") __llvm_ctlz :: proc(i128, bool) -> i128 ---;
@(link_name="llvm.cttz.i8") __llvm_cttz :: proc(u8, bool) -> u8 ---;
@(link_name="llvm.cttz.i8") __llvm_cttz :: proc(i8, bool) -> i8 ---;
@(link_name="llvm.cttz.i16") __llvm_cttz :: proc(u16, bool) -> u16 ---;
@(link_name="llvm.cttz.i16") __llvm_cttz :: proc(i16, bool) -> i16 ---;
@(link_name="llvm.cttz.i32") __llvm_cttz :: proc(u32, bool) -> u32 ---;
@(link_name="llvm.cttz.i32") __llvm_cttz :: proc(i32, bool) -> i32 ---;
@(link_name="llvm.cttz.i64") __llvm_cttz :: proc(u64, bool) -> u64 ---;
@(link_name="llvm.cttz.i64") __llvm_cttz :: proc(i64, bool) -> i64 ---;
@(link_name="llvm.cttz.i128") __llvm_cttz :: proc(u128, bool) -> u128 ---;
@(link_name="llvm.cttz.i128") __llvm_cttz :: proc(i128, bool) -> i128 ---;
@(link_name="llvm.bitreverse.i8") __llvm_bitreverse :: proc(u8) -> u8 ---;
@(link_name="llvm.bitreverse.i8") __llvm_bitreverse :: proc(i8) -> i8 ---;
@(link_name="llvm.bitreverse.i16") __llvm_bitreverse :: proc(u16) -> u16 ---;
@(link_name="llvm.bitreverse.i16") __llvm_bitreverse :: proc(i16) -> i16 ---;
@(link_name="llvm.bitreverse.i32") __llvm_bitreverse :: proc(u32) -> u32 ---;
@(link_name="llvm.bitreverse.i32") __llvm_bitreverse :: proc(i32) -> i32 ---;
@(link_name="llvm.bitreverse.i64") __llvm_bitreverse :: proc(u64) -> u64 ---;
@(link_name="llvm.bitreverse.i64") __llvm_bitreverse :: proc(i64) -> i64 ---;
@(link_name="llvm.bitreverse.i128") __llvm_bitreverse :: proc(u128) -> u128 ---;
@(link_name="llvm.bitreverse.i128") __llvm_bitreverse :: proc(i128) -> i128 ---;
@(link_name="llvm.bswap.i16") byte_swap :: proc(u16) -> u16 ---;
@(link_name="llvm.bswap.i16") byte_swap :: proc(i16) -> i16 ---;
@(link_name="llvm.bswap.i32") byte_swap :: proc(u32) -> u32 ---;
@(link_name="llvm.bswap.i32") byte_swap :: proc(i32) -> i32 ---;
@(link_name="llvm.bswap.i64") byte_swap :: proc(u64) -> u64 ---;
@(link_name="llvm.bswap.i64") byte_swap :: proc(i64) -> i64 ---;
@(link_name="llvm.bswap.i128") byte_swap :: proc(u128) -> u128 ---;
@(link_name="llvm.bswap.i128") byte_swap :: proc(i128) -> i128 ---;
}
byte_swap :: proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(byte_swap(u32(i))); } else { return uint(byte_swap(u64(i))); } }
byte_swap :: proc(i: int) -> int { when size_of(int) == size_of(i32) { return int(byte_swap(i32(i))); } else { return int(byte_swap(i64(i))); } }
count_ones :: proc(i: u8) -> u8 { return __llvm_ctpop(i); }
count_ones :: proc(i: i8) -> i8 { return __llvm_ctpop(i); }
count_ones :: proc(i: u16) -> u16 { return __llvm_ctpop(i); }
count_ones :: proc(i: i16) -> i16 { return __llvm_ctpop(i); }
count_ones :: proc(i: u32) -> u32 { return __llvm_ctpop(i); }
count_ones :: proc(i: i32) -> i32 { return __llvm_ctpop(i); }
count_ones :: proc(i: u64) -> u64 { return __llvm_ctpop(i); }
count_ones :: proc(i: i64) -> i64 { return __llvm_ctpop(i); }
count_ones :: proc(i: u128) -> u128 { return __llvm_ctpop(i); }
count_ones :: proc(i: i128) -> i128 { return __llvm_ctpop(i); }
count_ones :: proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(count_ones(u32(i))); } else { return uint(count_ones(u64(i))); } }
count_ones :: proc(i: int) -> int { when size_of(int) == size_of(i32) { return int(count_ones(i32(i))); } else { return int(count_ones(i64(i))); } }
count_zeros :: proc(i: u8) -> u8 { return 8 - count_ones(i); }
count_zeros :: proc(i: i8) -> i8 { return 8 - count_ones(i); }
count_zeros :: proc(i: u16) -> u16 { return 16 - count_ones(i); }
count_zeros :: proc(i: i16) -> i16 { return 16 - count_ones(i); }
count_zeros :: proc(i: u32) -> u32 { return 32 - count_ones(i); }
count_zeros :: proc(i: i32) -> i32 { return 32 - count_ones(i); }
count_zeros :: proc(i: u64) -> u64 { return 64 - count_ones(i); }
count_zeros :: proc(i: i64) -> i64 { return 64 - count_ones(i); }
count_zeros :: proc(i: u128) -> u128 { return 128 - count_ones(i); }
count_zeros :: proc(i: i128) -> i128 { return 128 - count_ones(i); }
count_zeros :: proc(i: uint) -> uint { return 8*size_of(uint) - count_ones(i); }
count_zeros :: proc(i: int) -> int { return 8*size_of(int) - count_ones(i); }
rotate_left :: proc(i: u8, s: uint) -> u8 { return (i << s)|(i >> (8*size_of(u8) - s)); }
rotate_left :: proc(i: i8, s: uint) -> i8 { return (i << s)|(i >> (8*size_of(i8) - s)); }
rotate_left :: proc(i: u16, s: uint) -> u16 { return (i << s)|(i >> (8*size_of(u16) - s)); }
rotate_left :: proc(i: i16, s: uint) -> i16 { return (i << s)|(i >> (8*size_of(i16) - s)); }
rotate_left :: proc(i: u32, s: uint) -> u32 { return (i << s)|(i >> (8*size_of(u32) - s)); }
rotate_left :: proc(i: i32, s: uint) -> i32 { return (i << s)|(i >> (8*size_of(i32) - s)); }
rotate_left :: proc(i: u64, s: uint) -> u64 { return (i << s)|(i >> (8*size_of(u64) - s)); }
rotate_left :: proc(i: i64, s: uint) -> i64 { return (i << s)|(i >> (8*size_of(i64) - s)); }
rotate_left :: proc(i: u128, s: uint) -> u128 { return (i << s)|(i >> (8*size_of(u128) - s)); }
rotate_left :: proc(i: i128, s: uint) -> i128 { return (i << s)|(i >> (8*size_of(i128) - s)); }
rotate_left :: proc(i: uint, s: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(rotate_left(u32(i), s)); } else { return uint(rotate_left(u64(i), s)); } }
rotate_left :: proc(i: int, s: uint) -> int { when size_of(int) == size_of(i32) { return int(rotate_left(i32(i), s)); } else { return int(rotate_left(i64(i), s)); } }
rotate_right :: proc(i: u8, s: uint) -> u8 { return (i >> s)|(i << (8*size_of(u8) - s)); }
rotate_right :: proc(i: i8, s: uint) -> i8 { return (i >> s)|(i << (8*size_of(i8) - s)); }
rotate_right :: proc(i: u16, s: uint) -> u16 { return (i >> s)|(i << (8*size_of(u16) - s)); }
rotate_right :: proc(i: i16, s: uint) -> i16 { return (i >> s)|(i << (8*size_of(i16) - s)); }
rotate_right :: proc(i: u32, s: uint) -> u32 { return (i >> s)|(i << (8*size_of(u32) - s)); }
rotate_right :: proc(i: i32, s: uint) -> i32 { return (i >> s)|(i << (8*size_of(i32) - s)); }
rotate_right :: proc(i: u64, s: uint) -> u64 { return (i >> s)|(i << (8*size_of(u64) - s)); }
rotate_right :: proc(i: i64, s: uint) -> i64 { return (i >> s)|(i << (8*size_of(i64) - s)); }
rotate_right :: proc(i: u128, s: uint) -> u128 { return (i >> s)|(i << (8*size_of(u128) - s)); }
rotate_right :: proc(i: i128, s: uint) -> i128 { return (i >> s)|(i << (8*size_of(i128) - s)); }
rotate_right :: proc(i: uint, s: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(rotate_right(u32(i), s)); } else { return uint(rotate_right(u64(i), s)); } }
rotate_right :: proc(i: int, s: uint) -> int { when size_of(int) == size_of(i32) { return int(rotate_right(i32(i), s)); } else { return int(rotate_right(i64(i), s)); } }
leading_zeros :: proc(i: u8) -> u8 { return __llvm_ctlz(i, false); }
leading_zeros :: proc(i: i8) -> i8 { return __llvm_ctlz(i, false); }
leading_zeros :: proc(i: u16) -> u16 { return __llvm_ctlz(i, false); }
leading_zeros :: proc(i: i16) -> i16 { return __llvm_ctlz(i, false); }
leading_zeros :: proc(i: u32) -> u32 { return __llvm_ctlz(i, false); }
leading_zeros :: proc(i: i32) -> i32 { return __llvm_ctlz(i, false); }
leading_zeros :: proc(i: u64) -> u64 { return __llvm_ctlz(i, false); }
leading_zeros :: proc(i: i64) -> i64 { return __llvm_ctlz(i, false); }
leading_zeros :: proc(i: u128) -> u128 { return __llvm_ctlz(i, false); }
leading_zeros :: proc(i: i128) -> i128 { return __llvm_ctlz(i, false); }
leading_zeros :: proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(leading_zeros(u32(i))); } else { return uint(leading_zeros(u64(i))); } }
leading_zeros :: proc(i: int) -> int { when size_of(int) == size_of(i32) { return int(leading_zeros(i32(i))); } else { return int(leading_zeros(i64(i))); } }
trailing_zeros :: proc(i: u8) -> u8 { return __llvm_cttz(i, false); }
trailing_zeros :: proc(i: i8) -> i8 { return __llvm_cttz(i, false); }
trailing_zeros :: proc(i: u16) -> u16 { return __llvm_cttz(i, false); }
trailing_zeros :: proc(i: i16) -> i16 { return __llvm_cttz(i, false); }
trailing_zeros :: proc(i: u32) -> u32 { return __llvm_cttz(i, false); }
trailing_zeros :: proc(i: i32) -> i32 { return __llvm_cttz(i, false); }
trailing_zeros :: proc(i: u64) -> u64 { return __llvm_cttz(i, false); }
trailing_zeros :: proc(i: i64) -> i64 { return __llvm_cttz(i, false); }
trailing_zeros :: proc(i: u128) -> u128 { return __llvm_cttz(i, false); }
trailing_zeros :: proc(i: i128) -> i128 { return __llvm_cttz(i, false); }
trailing_zeros :: proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(trailing_zeros(u32(i))); } else { return uint(trailing_zeros(u64(i))); } }
trailing_zeros :: proc(i: int) -> int { when size_of(int) == size_of(i32) { return int(trailing_zeros(i32(i))); } else { return int(trailing_zeros(i64(i))); } }
reverse_bits :: proc(i: u8) -> u8 { return __llvm_bitreverse(i); }
reverse_bits :: proc(i: i8) -> i8 { return __llvm_bitreverse(i); }
reverse_bits :: proc(i: u16) -> u16 { return __llvm_bitreverse(i); }
reverse_bits :: proc(i: i16) -> i16 { return __llvm_bitreverse(i); }
reverse_bits :: proc(i: u32) -> u32 { return __llvm_bitreverse(i); }
reverse_bits :: proc(i: i32) -> i32 { return __llvm_bitreverse(i); }
reverse_bits :: proc(i: u64) -> u64 { return __llvm_bitreverse(i); }
reverse_bits :: proc(i: i64) -> i64 { return __llvm_bitreverse(i); }
reverse_bits :: proc(i: u128) -> u128 { return __llvm_bitreverse(i); }
reverse_bits :: proc(i: i128) -> i128 { return __llvm_bitreverse(i); }
reverse_bits :: proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(reverse_bits(u32(i))); } else { return uint(reverse_bits(u64(i))); } }
reverse_bits :: proc(i: int) -> int { when size_of(int) == size_of(i32) { return int(reverse_bits(i32(i))); } else { return int(reverse_bits(i64(i))); } }
from_be :: proc(i: u8) -> u8 { return i; }
from_be :: proc(i: i8) -> i8 { return i; }
from_be :: proc(i: u16) -> u16 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
from_be :: proc(i: i16) -> i16 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
from_be :: proc(i: u32) -> u32 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
from_be :: proc(i: i32) -> i32 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
from_be :: proc(i: u64) -> u64 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
from_be :: proc(i: i64) -> i64 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
from_be :: proc(i: u128) -> u128 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
from_be :: proc(i: i128) -> i128 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
from_be :: proc(i: uint) -> uint { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
from_be :: proc(i: int) -> int { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
from_le :: proc(i: u8) -> u8 { return i; }
from_le :: proc(i: i8) -> i8 { return i; }
from_le :: proc(i: u16) -> u16 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
from_le :: proc(i: i16) -> i16 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
from_le :: proc(i: u32) -> u32 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
from_le :: proc(i: i32) -> i32 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
from_le :: proc(i: u64) -> u64 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
from_le :: proc(i: i64) -> i64 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
from_le :: proc(i: u128) -> u128 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
from_le :: proc(i: i128) -> i128 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
from_le :: proc(i: uint) -> uint { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
from_le :: proc(i: int) -> int { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
to_be :: proc(i: u8) -> u8 { return i; }
to_be :: proc(i: i8) -> i8 { return i; }
to_be :: proc(i: u16) -> u16 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
to_be :: proc(i: i16) -> i16 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
to_be :: proc(i: u32) -> u32 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
to_be :: proc(i: i32) -> i32 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
to_be :: proc(i: u64) -> u64 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
to_be :: proc(i: i64) -> i64 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
to_be :: proc(i: u128) -> u128 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
to_be :: proc(i: i128) -> i128 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
to_be :: proc(i: uint) -> uint { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
to_be :: proc(i: int) -> int { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
to_le :: proc(i: u8) -> u8 { return i; }
to_le :: proc(i: i8) -> i8 { return i; }
to_le :: proc(i: u16) -> u16 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
to_le :: proc(i: i16) -> i16 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
to_le :: proc(i: u32) -> u32 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
to_le :: proc(i: i32) -> i32 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
to_le :: proc(i: u64) -> u64 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
to_le :: proc(i: i64) -> i64 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
to_le :: proc(i: u128) -> u128 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
to_le :: proc(i: i128) -> i128 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
to_le :: proc(i: uint) -> uint { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
to_le :: proc(i: int) -> int { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
overflowing_add :: proc(lhs, rhs: u8) -> (u8, bool) { foreign __llvm_core @(link_name="llvm.uadd.with.overflow.i8") op :: proc(u8, u8) -> (u8, bool) ---; return op(lhs, rhs); }
overflowing_add :: proc(lhs, rhs: i8) -> (i8, bool) { foreign __llvm_core @(link_name="llvm.sadd.with.overflow.i8") op :: proc(i8, i8) -> (i8, bool) ---; return op(lhs, rhs); }
overflowing_add :: proc(lhs, rhs: u16) -> (u16, bool) { foreign __llvm_core @(link_name="llvm.uadd.with.overflow.i16") op :: proc(u16, u16) -> (u16, bool) ---; return op(lhs, rhs); }
overflowing_add :: proc(lhs, rhs: i16) -> (i16, bool) { foreign __llvm_core @(link_name="llvm.sadd.with.overflow.i16") op :: proc(i16, i16) -> (i16, bool) ---; return op(lhs, rhs); }
overflowing_add :: proc(lhs, rhs: u32) -> (u32, bool) { foreign __llvm_core @(link_name="llvm.uadd.with.overflow.i32") op :: proc(u32, u32) -> (u32, bool) ---; return op(lhs, rhs); }
overflowing_add :: proc(lhs, rhs: i32) -> (i32, bool) { foreign __llvm_core @(link_name="llvm.sadd.with.overflow.i32") op :: proc(i32, i32) -> (i32, bool) ---; return op(lhs, rhs); }
overflowing_add :: proc(lhs, rhs: u64) -> (u64, bool) { foreign __llvm_core @(link_name="llvm.uadd.with.overflow.i64") op :: proc(u64, u64) -> (u64, bool) ---; return op(lhs, rhs); }
overflowing_add :: proc(lhs, rhs: i64) -> (i64, bool) { foreign __llvm_core @(link_name="llvm.sadd.with.overflow.i64") op :: proc(i64, i64) -> (i64, bool) ---; return op(lhs, rhs); }
overflowing_add :: proc(lhs, rhs: u128) -> (u128, bool) { foreign __llvm_core @(link_name="llvm.uadd.with.overflow.i128") op :: proc(u128, u128) -> (u128, bool) ---; return op(lhs, rhs); }
overflowing_add :: proc(lhs, rhs: i128) -> (i128, bool) { foreign __llvm_core @(link_name="llvm.sadd.with.overflow.i128") op :: proc(i128, i128) -> (i128, bool) ---; return op(lhs, rhs); }
overflowing_add :: proc(lhs, rhs: uint) -> (uint, bool) {
when size_of(uint) == size_of(u32) {
x, ok := overflowing_add(u32(lhs), u32(rhs));
return uint(x), ok;
} else {
x, ok := overflowing_add(u64(lhs), u64(rhs));
return uint(x), ok;
}
}
overflowing_add :: proc(lhs, rhs: int) -> (int, bool) {
when size_of(int) == size_of(i32) {
x, ok := overflowing_add(i32(lhs), i32(rhs));
return int(x), ok;
} else {
x, ok := overflowing_add(i64(lhs), i64(rhs));
return int(x), ok;
}
}
overflowing_sub :: proc(lhs, rhs: u8) -> (u8, bool) { foreign __llvm_core @(link_name="llvm.usub.with.overflow.i8") op :: proc(u8, u8) -> (u8, bool) ---; return op(lhs, rhs); }
overflowing_sub :: proc(lhs, rhs: i8) -> (i8, bool) { foreign __llvm_core @(link_name="llvm.ssub.with.overflow.i8") op :: proc(i8, i8) -> (i8, bool) ---; return op(lhs, rhs); }
overflowing_sub :: proc(lhs, rhs: u16) -> (u16, bool) { foreign __llvm_core @(link_name="llvm.usub.with.overflow.i16") op :: proc(u16, u16) -> (u16, bool) ---; return op(lhs, rhs); }
overflowing_sub :: proc(lhs, rhs: i16) -> (i16, bool) { foreign __llvm_core @(link_name="llvm.ssub.with.overflow.i16") op :: proc(i16, i16) -> (i16, bool) ---; return op(lhs, rhs); }
overflowing_sub :: proc(lhs, rhs: u32) -> (u32, bool) { foreign __llvm_core @(link_name="llvm.usub.with.overflow.i32") op :: proc(u32, u32) -> (u32, bool) ---; return op(lhs, rhs); }
overflowing_sub :: proc(lhs, rhs: i32) -> (i32, bool) { foreign __llvm_core @(link_name="llvm.ssub.with.overflow.i32") op :: proc(i32, i32) -> (i32, bool) ---; return op(lhs, rhs); }
overflowing_sub :: proc(lhs, rhs: u64) -> (u64, bool) { foreign __llvm_core @(link_name="llvm.usub.with.overflow.i64") op :: proc(u64, u64) -> (u64, bool) ---; return op(lhs, rhs); }
overflowing_sub :: proc(lhs, rhs: i64) -> (i64, bool) { foreign __llvm_core @(link_name="llvm.ssub.with.overflow.i64") op :: proc(i64, i64) -> (i64, bool) ---; return op(lhs, rhs); }
overflowing_sub :: proc(lhs, rhs: u128) -> (u128, bool) { foreign __llvm_core @(link_name="llvm.usub.with.overflow.i128") op :: proc(u128, u128) -> (u128, bool) ---; return op(lhs, rhs); }
overflowing_sub :: proc(lhs, rhs: i128) -> (i128, bool) { foreign __llvm_core @(link_name="llvm.ssub.with.overflow.i128") op :: proc(i128, i128) -> (i128, bool) ---; return op(lhs, rhs); }
overflowing_sub :: proc(lhs, rhs: uint) -> (uint, bool) {
when size_of(uint) == size_of(u32) {
x, ok := overflowing_sub(u32(lhs), u32(rhs));
return uint(x), ok;
} else {
x, ok := overflowing_sub(u64(lhs), u64(rhs));
return uint(x), ok;
}
}
overflowing_sub :: proc(lhs, rhs: int) -> (int, bool) {
when size_of(int) == size_of(i32) {
x, ok := overflowing_sub(i32(lhs), i32(rhs));
return int(x), ok;
} else {
x, ok := overflowing_sub(i64(lhs), i64(rhs));
return int(x), ok;
}
}
overflowing_mul :: proc(lhs, rhs: u8) -> (u8, bool) { foreign __llvm_core @(link_name="llvm.umul.with.overflow.i8") op :: proc(u8, u8) -> (u8, bool) ---; return op(lhs, rhs); }
overflowing_mul :: proc(lhs, rhs: i8) -> (i8, bool) { foreign __llvm_core @(link_name="llvm.smul.with.overflow.i8") op :: proc(i8, i8) -> (i8, bool) ---; return op(lhs, rhs); }
overflowing_mul :: proc(lhs, rhs: u16) -> (u16, bool) { foreign __llvm_core @(link_name="llvm.umul.with.overflow.i16") op :: proc(u16, u16) -> (u16, bool) ---; return op(lhs, rhs); }
overflowing_mul :: proc(lhs, rhs: i16) -> (i16, bool) { foreign __llvm_core @(link_name="llvm.smul.with.overflow.i16") op :: proc(i16, i16) -> (i16, bool) ---; return op(lhs, rhs); }
overflowing_mul :: proc(lhs, rhs: u32) -> (u32, bool) { foreign __llvm_core @(link_name="llvm.umul.with.overflow.i32") op :: proc(u32, u32) -> (u32, bool) ---; return op(lhs, rhs); }
overflowing_mul :: proc(lhs, rhs: i32) -> (i32, bool) { foreign __llvm_core @(link_name="llvm.smul.with.overflow.i32") op :: proc(i32, i32) -> (i32, bool) ---; return op(lhs, rhs); }
overflowing_mul :: proc(lhs, rhs: u64) -> (u64, bool) { foreign __llvm_core @(link_name="llvm.umul.with.overflow.i64") op :: proc(u64, u64) -> (u64, bool) ---; return op(lhs, rhs); }
overflowing_mul :: proc(lhs, rhs: i64) -> (i64, bool) { foreign __llvm_core @(link_name="llvm.smul.with.overflow.i64") op :: proc(i64, i64) -> (i64, bool) ---; return op(lhs, rhs); }
overflowing_mul :: proc(lhs, rhs: u128) -> (u128, bool) { foreign __llvm_core @(link_name="llvm.umul.with.overflow.i128") op :: proc(u128, u128) -> (u128, bool) ---; return op(lhs, rhs); }
overflowing_mul :: proc(lhs, rhs: i128) -> (i128, bool) { foreign __llvm_core @(link_name="llvm.smul.with.overflow.i128") op :: proc(i128, i128) -> (i128, bool) ---; return op(lhs, rhs); }
overflowing_mul :: proc(lhs, rhs: uint) -> (uint, bool) {
when size_of(uint) == size_of(u32) {
x, ok := overflowing_mul(u32(lhs), u32(rhs));
return uint(x), ok;
} else {
x, ok := overflowing_mul(u64(lhs), u64(rhs));
return uint(x), ok;
}
}
overflowing_mul :: proc(lhs, rhs: int) -> (int, bool) {
when size_of(int) == size_of(i32) {
x, ok := overflowing_mul(i32(lhs), i32(rhs));
return int(x), ok;
} else {
x, ok := overflowing_mul(i64(lhs), i64(rhs));
return int(x), ok;
}
}
is_power_of_two :: proc(i: u8) -> bool { return i > 0 && (i & (i-1)) == 0; }
is_power_of_two :: proc(i: i8) -> bool { return i > 0 && (i & (i-1)) == 0; }
is_power_of_two :: proc(i: u16) -> bool { return i > 0 && (i & (i-1)) == 0; }
is_power_of_two :: proc(i: i16) -> bool { return i > 0 && (i & (i-1)) == 0; }
is_power_of_two :: proc(i: u32) -> bool { return i > 0 && (i & (i-1)) == 0; }
is_power_of_two :: proc(i: i32) -> bool { return i > 0 && (i & (i-1)) == 0; }
is_power_of_two :: proc(i: u64) -> bool { return i > 0 && (i & (i-1)) == 0; }
is_power_of_two :: proc(i: i64) -> bool { return i > 0 && (i & (i-1)) == 0; }
is_power_of_two :: proc(i: u128) -> bool { return i > 0 && (i & (i-1)) == 0; }
is_power_of_two :: proc(i: i128) -> bool { return i > 0 && (i & (i-1)) == 0; }
is_power_of_two :: proc(i: uint) -> bool { return i > 0 && (i & (i-1)) == 0; }
is_power_of_two :: proc(i: int) -> bool { return i > 0 && (i & (i-1)) == 0; }
+68
View File
@@ -0,0 +1,68 @@
package bufio
import "core:io"
// Read_Writer stores pointers to a Reader and a Writer
Read_Writer :: struct {
r: ^Reader,
w: ^Writer,
}
read_writer_init :: proc(rw: ^Read_Writer, r: ^Reader, w: ^Writer) {
rw.r, rw.w = r, w;
}
read_writer_to_stream :: proc(rw: ^Read_Writer) -> (s: io.Stream) {
s.stream_data = rw;
s.stream_vtable = _read_writer_vtable;
return;
}
@(private)
_read_writer_vtable := &io.Stream_VTable{
impl_read = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
b := (^Read_Writer)(s.stream_data).r;
return reader_read(b, p);
},
impl_read_byte = proc(s: io.Stream) -> (c: byte, err: io.Error) {
b := (^Read_Writer)(s.stream_data).r;
return reader_read_byte(b);
},
impl_unread_byte = proc(s: io.Stream) -> io.Error {
b := (^Read_Writer)(s.stream_data).r;
return reader_unread_byte(b);
},
impl_read_rune = proc(s: io.Stream) -> (r: rune, size: int, err: io.Error) {
b := (^Read_Writer)(s.stream_data).r;
return reader_read_rune(b);
},
impl_unread_rune = proc(s: io.Stream) -> io.Error {
b := (^Read_Writer)(s.stream_data).r;
return reader_unread_rune(b);
},
impl_write_to = proc(s: io.Stream, w: io.Writer) -> (n: i64, err: io.Error) {
b := (^Read_Writer)(s.stream_data).r;
return reader_write_to(b, w);
},
impl_flush = proc(s: io.Stream) -> io.Error {
b := (^Read_Writer)(s.stream_data).w;
return writer_flush(b);
},
impl_write = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
b := (^Read_Writer)(s.stream_data).w;
return writer_write(b, p);
},
impl_write_byte = proc(s: io.Stream, c: byte) -> io.Error {
b := (^Read_Writer)(s.stream_data).w;
return writer_write_byte(b, c);
},
impl_write_rune = proc(s: io.Stream, r: rune) -> (int, io.Error) {
b := (^Read_Writer)(s.stream_data).w;
return writer_write_rune(b, r);
},
impl_read_from = proc(s: io.Stream, r: io.Reader) -> (n: i64, err: io.Error) {
b := (^Read_Writer)(s.stream_data).w;
return writer_read_from(b, r);
},
};
+474
View File
@@ -0,0 +1,474 @@
package bufio
import "core:io"
import "core:mem"
import "core:unicode/utf8"
import "core:bytes"
// Reader is a buffered wrapper for an io.Reader
Reader :: struct {
buf: []byte,
buf_allocator: mem.Allocator,
rd: io.Reader, // reader
r, w: int, // read and write positions for buf
err: io.Error,
last_byte: int, // last byte read, invalid is -1
last_rune_size: int, // size of last rune read, invalid is -1
}
DEFAULT_BUF_SIZE :: 4096;
@(private)
MIN_READ_BUFFER_SIZE :: 16;
@(private)
MAX_CONSECUTIVE_EMPTY_READS :: 128;
reader_init :: proc(b: ^Reader, rd: io.Reader, size: int = DEFAULT_BUF_SIZE, allocator := context.allocator) {
size := size;
size = max(size, MIN_READ_BUFFER_SIZE);
reader_reset(b, rd);
b.buf_allocator = allocator;
b.buf = make([]byte, size, allocator);
}
reader_init_with_buf :: proc(b: ^Reader, rd: io.Reader, buf: []byte) {
reader_reset(b, rd);
b.buf_allocator = {};
b.buf = buf;
}
// reader_destroy destroys the underlying buffer with its associated allocator IFF that allocator has been set
reader_destroy :: proc(b: ^Reader) {
delete(b.buf, b.buf_allocator);
b^ = {};
}
reader_size :: proc(b: ^Reader) -> int {
return len(b.buf);
}
reader_reset :: proc(b: ^Reader, r: io.Reader) {
b.rd = r;
b.r, b.w = 0, 0;
b.err = nil;
b.last_byte = -1;
b.last_rune_size = -1;
}
@(private)
_reader_read_new_chunk :: proc(b: ^Reader) -> io.Error {
if b.r > 0 {
copy(b.buf, b.buf[b.r:b.w]);
b.w -= b.r;
b.r = 0;
}
if b.w >= len(b.buf) {
return .Buffer_Full;
}
// read new data, and try a limited number of times
for i := MAX_CONSECUTIVE_EMPTY_READS; i > 0; i -= 1 {
n, err := io.read(b.rd, b.buf[b.w:]);
if n < 0 {
return .Negative_Read;
}
b.w += n;
if err != nil {
b.err = err;
return nil;
}
if n > 0 {
return nil;
}
}
b.err = .No_Progress;
return nil;
}
@(private)
_reader_consume_err :: proc(b: ^Reader) -> io.Error {
err := b.err;
b.err = nil;
return err;
}
// reader_peek returns the next n bytes without advancing the reader
// The bytes stop being valid on the next read call
// If reader_peek returns fewer than n bytes, it also return an error
// explaining why the read is short
// The error will be .Buffer_Full if n is larger than the internal buffer size
reader_peek :: proc(b: ^Reader, n: int) -> (data: []byte, err: io.Error) {
n := n;
if n < 0 {
return nil, .Negative_Count;
}
b.last_byte = -1;
b.last_rune_size = -1;
for b.w-b.r < n && b.w-b.r < len(b.buf) && b.err == nil {
if fill_err := _reader_read_new_chunk(b); fill_err != nil {
return nil, fill_err;
}
}
if n > len(b.buf) {
return b.buf[b.r : b.w], .Buffer_Full;
}
if available := b.w - b.r; available < n {
n = available;
err = _reader_consume_err(b);
if err == nil {
err = .Buffer_Full;
}
}
return b.buf[b.r : b.r+n], err;
}
// reader_buffered returns the number of bytes that can be read from the current buffer
reader_buffered :: proc(b: ^Reader) -> int {
return b.w - b.r;
}
// reader_discard skips the next n bytes, and returns the number of bytes that were discarded
reader_discard :: proc(b: ^Reader, n: int) -> (discarded: int, err: io.Error) {
if n < 0 {
return 0, .Negative_Count;
}
if n == 0 {
return;
}
remaining := n;
for {
skip := reader_buffered(b);
if skip == 0 {
if fill_err := _reader_read_new_chunk(b); fill_err != nil {
return 0, fill_err;
}
skip = reader_buffered(b);
}
skip = min(skip, remaining);
b.r += skip;
remaining -= skip;
if remaining == 0 {
return n, nil;
}
if b.err != nil {
return n - remaining, _reader_consume_err(b);
}
}
return;
}
// reader_read reads data into p
// The bytes are taken from at most one read on the underlying Reader, which means n may be less than len(p)
reader_read :: proc(b: ^Reader, p: []byte) -> (n: int, err: io.Error) {
n = len(p);
if n == 0 {
if reader_buffered(b) > 0 {
return 0, nil;
}
return 0, _reader_consume_err(b);
}
if b.r == b.w {
if b.err != nil {
return 0, _reader_consume_err(b);
}
if len(p) >= len(b.buf) {
n, b.err = io.read(b.rd, p);
if n < 0 {
return 0, .Negative_Read;
}
if n > 0 {
b.last_byte = int(p[n-1]);
b.last_rune_size = -1;
}
return n, _reader_consume_err(b);
}
b.r, b.w = 0, 0;
n, b.err = io.read(b.rd, b.buf);
if n < 0 {
return 0, .Negative_Read;
}
if n == 0 {
return 0, _reader_consume_err(b);
}
b.w += n;
}
n = copy(p, b.buf[b.r:b.w]);
b.r += n;
b.last_byte = int(b.buf[b.r-1]);
b.last_rune_size = -1;
return n, nil;
}
// reader_read_byte reads and returns a single byte
// If no byte is available, it return an error
reader_read_byte :: proc(b: ^Reader) -> (byte, io.Error) {
b.last_rune_size = -1;
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;
}
}
c := b.buf[b.r];
b.r += 1;
b.last_byte = int(c);
return c, nil;
}
// reader_unread_byte unreads the last byte. Only the most recently read byte can be unread
reader_unread_byte :: proc(b: ^Reader) -> io.Error {
if b.last_byte < 0 || b.r == 0 && b.w > 0 {
return .Invalid_Unread;
}
if b.r > 0 {
b.r -= 1;
} else {
// b.r == 0 && b.w == 0
b.w = 1;
}
b.buf[b.r] = byte(b.last_byte);
b.last_byte = -1;
b.last_rune_size = -1;
return nil;
}
// reader_read_rune reads a single UTF-8 encoded unicode character
// and returns the rune and its size in bytes
// If the encoded rune is invalid, it consumes one byte and returns utf8.RUNE_ERROR (U+FFFD) with a size of 1
reader_read_rune :: proc(b: ^Reader) -> (r: rune, size: int, err: io.Error) {
for b.r+utf8.UTF_MAX > b.w &&
!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;
}
}
b.last_rune_size = -1;
if b.r == b.w {
err = _reader_consume_err(b);
return;
}
r, size = rune(b.buf[b.r]), 1;
if r >= utf8.RUNE_SELF {
r, size = utf8.decode_rune(b.buf[b.r : b.w]);
}
b.r += size;
b.last_byte = int(b.buf[b.r-1]);
b.last_rune_size = size;
return;
}
// reader_unread_rune unreads the last rune. Only the most recently read rune can be unread
reader_unread_rune :: proc(b: ^Reader) -> io.Error {
if b.last_rune_size < 0 || b.r < b.last_rune_size {
return .Invalid_Unread;
}
b.r -= b.last_rune_size;
b.last_byte = -1;
b.last_rune_size = -1;
return nil;
}
reader_write_to :: proc(b: ^Reader, w: io.Writer) -> (n: i64, err: io.Error) {
write_buf :: proc(b: ^Reader, w: io.Writer) -> (i64, io.Error) {
n, err := io.write(w, b.buf[b.r:b.w]);
if n < 0 {
return 0, .Negative_Write;
}
b.r += n;
return i64(n), err;
}
n, err = write_buf(b, w);
if err != nil {
return;
}
m: i64;
if nr, ok := io.to_writer_to(b.rd); ok {
m, err = io.write_to(nr, w);
n += m;
return n, err;
}
if nw, ok := io.to_reader_from(w); ok {
m, err = io.read_from(nw, b.rd);
n += m;
return n, err;
}
if b.w-b.r < len(b.buf) {
if err = _reader_read_new_chunk(b); err != nil {
return;
}
}
for b.r < b.w {
m, err = write_buf(b, w);
n += m;
if err != nil {
return;
}
if err = _reader_read_new_chunk(b); err != nil {
return;
}
}
if b.err == .EOF {
b.err = nil;
}
err = _reader_consume_err(b);
return;
}
// reader_to_stream converts a Reader into an io.Stream
reader_to_stream :: proc(b: ^Reader) -> (s: io.Stream) {
s.stream_data = b;
s.stream_vtable = _reader_vtable;
return;
}
@(private)
_reader_vtable := &io.Stream_VTable{
impl_destroy = proc(s: io.Stream) -> io.Error {
b := (^Reader)(s.stream_data);
reader_destroy(b);
return nil;
},
impl_read = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
b := (^Reader)(s.stream_data);
return reader_read(b, p);
},
impl_read_byte = proc(s: io.Stream) -> (c: byte, err: io.Error) {
b := (^Reader)(s.stream_data);
return reader_read_byte(b);
},
impl_unread_byte = proc(s: io.Stream) -> io.Error {
b := (^Reader)(s.stream_data);
return reader_unread_byte(b);
},
impl_read_rune = proc(s: io.Stream) -> (r: rune, size: int, err: io.Error) {
b := (^Reader)(s.stream_data);
return reader_read_rune(b);
},
impl_unread_rune = proc(s: io.Stream) -> io.Error {
b := (^Reader)(s.stream_data);
return reader_unread_rune(b);
},
impl_write_to = proc(s: io.Stream, w: io.Writer) -> (n: i64, err: io.Error) {
b := (^Reader)(s.stream_data);
return reader_write_to(b, w);
},
};
//
// Utility procedures
//
// reader_read_slice reads until the first occurrence of delim from the reader
// It returns a slice pointing at the bytes in the buffer
// The bytes stop being valid at the next read
// If reader_read_slice encounters an error before finding a delimiter
// reader_read_slice fails with error .Buffer_Full if the buffer fills without a delim
// Because the data returned from reader_read_slice will be overwritten on the
// next IO operation, reader_read_bytes or reader_read_string is usually preferred
//
// reader_read_slice returns err != nil if and only if line does not end in delim
//
reader_read_slice :: proc(b: ^Reader, delim: byte) -> (line: []byte, err: io.Error) {
s := 0;
for {
if i := bytes.index_byte(b.buf[b.r+s : b.w], delim); i >= 0 {
i += s;
line = b.buf[b.r:][:i+1];
b.r += i + 1;
break;
}
if b.err != nil {
line = b.buf[b.r : b.w];
b.r = b.w;
err = _reader_consume_err(b);
break;
}
if reader_buffered(b) >= len(b.buf) {
b.r = b.w;
line = b.buf;
err = .Buffer_Full;
break;
}
s = b.w - b.r;
if err = _reader_read_new_chunk(b); err != nil {
break;
}
}
if i := len(line)-1; i >= 0 {
b.last_byte = int(line[i]);
b.last_rune_size = -1;
}
return;
}
// reader_read_bytes reads until the first occurrence of delim from the Reader
// It returns an allocated slice containing the data up to and including the delimiter
reader_read_bytes :: proc(b: ^Reader, delim: byte, allocator := context.allocator) -> (buf: []byte, err: io.Error) {
full: [dynamic]byte;
full.allocator = allocator;
frag: []byte;
for {
e: io.Error;
frag, e = reader_read_slice(b, delim);
if e == nil {
break;
}
if e != .Buffer_Full {
err = e;
break;
}
append(&full, ..frag);
}
append(&full, ..frag);
return full[:], err;
}
// reader_read_string reads until the first occurrence of delim from the Reader
// It returns an allocated string containing the data up to and including the delimiter
reader_read_string :: proc(b: ^Reader, delim: byte, allocator := context.allocator) -> (string, io.Error) {
buf, err := reader_read_bytes(b, delim, allocator);
return string(buf), err;
}
+255
View File
@@ -0,0 +1,255 @@
package bufio
import "core:io"
import "core:mem"
import "core:unicode/utf8"
// import "core:bytes"
// Writer is a buffered wrapper for an io.Writer
Writer :: struct {
buf: []byte,
buf_allocator: mem.Allocator,
wr: io.Writer,
n: int,
err: io.Error,
}
writer_init :: proc(b: ^Writer, wr: io.Writer, size: int = DEFAULT_BUF_SIZE, allocator := context.allocator) {
size := size;
size = max(size, MIN_READ_BUFFER_SIZE);
writer_reset(b, wr);
b.buf_allocator = allocator;
b.buf = make([]byte, size, allocator);
}
writer_init_with_buf :: proc(b: ^Writer, wr: io.Writer, buf: []byte) {
writer_reset(b, wr);
b.buf_allocator = {};
b.buf = buf;
}
// writer_destroy destroys the underlying buffer with its associated allocator IFF that allocator has been set
writer_destroy :: proc(b: ^Writer) {
delete(b.buf, b.buf_allocator);
b^ = {};
}
// writer_size returns the size of underlying buffer in bytes
writer_size :: proc(b: ^Writer) -> int {
return len(b.buf);
}
writer_reset :: proc(b: ^Writer, w: io.Writer) {
b.wr = w;
b.n = 0;
b.err = nil;
}
// writer_flush writes any buffered data into the underlying io.Writer
writer_flush :: proc(b: ^Writer) -> io.Error {
if b.err != nil {
return b.err;
}
if b.n == 0 {
return nil;
}
n, err := io.write(b.wr, b.buf[0:b.n]);
if n < b.n && err == nil {
err = .Short_Write;
}
if err != nil {
if n > 0 && n < b.n {
copy(b.buf[:b.n-n], b.buf[n : b.n]);
}
b.n -= n;
b.err = err;
return err;
}
b.n = 0;
return nil;
}
// writer_available returns how many bytes are unused in the buffer
writer_available :: proc(b: ^Writer) -> int {
return len(b.buf) - b.n;
}
// writer_buffered returns the number of bytes that have been writted into the current buffer
writer_buffered :: proc(b: ^Writer) -> int {
return b.n;
}
// writer_write writes the contents of p into the buffer
// It returns the number of bytes written
// If n < len(p), it will return an error explaining why the write is short
writer_write :: proc(b: ^Writer, p: []byte) -> (n: int, err: io.Error) {
p := p;
for len(p) > writer_available(b) && b.err == nil {
m: int;
if writer_buffered(b) == 0 {
m, b.err = io.write(b.wr, p);
} else {
m = copy(b.buf[b.n:], p);
b.n += m;
writer_flush(b);
}
n += m;
p = p[m:];
}
if b.err != nil {
return n, b.err;
}
m := copy(b.buf[b.n:], p);
b.n += m;
m += n;
return m, nil;
}
// writer_write_byte writes a single byte
writer_write_byte :: proc(b: ^Writer, c: byte) -> io.Error {
if b.err != nil {
return b.err;
}
if writer_available(b) <= 0 && writer_flush(b) != nil {
return b.err;
}
b.buf[b.n] = c;
b.n += 1;
return nil;
}
// writer_write_rune writes a single unicode code point, and returns the number of bytes written with any error
writer_write_rune :: proc(b: ^Writer, r: rune) -> (size: int, err: io.Error) {
if r < utf8.RUNE_SELF {
err = writer_write_byte(b, byte(r));
size = 0 if err != nil else 1;
return;
}
if b.err != nil {
return 0, b.err;
}
buf: [4]u8;
n := writer_available(b);
if n < utf8.UTF_MAX {
writer_flush(b);
if b.err != nil {
return 0, b.err;
}
n = writer_available(b);
if n < utf8.UTF_MAX {
// this only happens if the buffer is very small
w: int;
buf, w = utf8.encode_rune(r);
return writer_write(b, buf[:w]);
}
}
buf, size = utf8.encode_rune(r);
copy(b.buf[b.n:], buf[:size]);
b.n += size;
return;
}
// writer_write writes a string into the buffer
// It returns the number of bytes written
// If n < len(p), it will return an error explaining why the write is short
writer_write_string :: proc(b: ^Writer, s: string) -> (int, io.Error) {
return writer_write(b, transmute([]byte)s);
}
// writer_read_from is to support io.Reader_From types
// If the underlying writer supports the io,read_from, and b has no buffered data yet,
// this procedure calls the underlying read_from implementation without buffering
writer_read_from :: proc(b: ^Writer, r: io.Reader) -> (n: i64, err: io.Error) {
if b.err != nil {
return 0, b.err;
}
if writer_buffered(b) == 0 {
if w, ok := io.to_reader_from(b.wr); !ok {
n, err = io.read_from(w, r);
b.err = err;
return;
}
}
for {
if writer_available(b) == 0 {
if ferr := writer_flush(b); ferr != nil {
return n, ferr;
}
}
m: int;
nr := 0;
for nr < MAX_CONSECUTIVE_EMPTY_READS {
m, err = io.read(r, b.buf[b.n:]);
if m != 0 || err != nil {
break;
}
nr += 1;
}
if nr == MAX_CONSECUTIVE_EMPTY_READS {
return n, .No_Progress;
}
b.n += m;
n += i64(m);
if err != nil {
break;
}
}
if err == .EOF {
if writer_available(b) == 0 {
err = writer_flush(b);
} else {
err = nil;
}
}
return;
}
// writer_to_stream converts a Writer into an io.Stream
writer_to_stream :: proc(b: ^Writer) -> (s: io.Stream) {
s.stream_data = b;
s.stream_vtable = _writer_vtable;
return;
}
@(private)
_writer_vtable := &io.Stream_VTable{
impl_destroy = proc(s: io.Stream) -> io.Error {
b := (^Writer)(s.stream_data);
writer_destroy(b);
return nil;
},
impl_flush = proc(s: io.Stream) -> io.Error {
b := (^Writer)(s.stream_data);
return writer_flush(b);
},
impl_write = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
b := (^Writer)(s.stream_data);
return writer_write(b, p);
},
impl_write_byte = proc(s: io.Stream, c: byte) -> io.Error {
b := (^Writer)(s.stream_data);
return writer_write_byte(b, c);
},
impl_write_rune = proc(s: io.Stream, r: rune) -> (int, io.Error) {
b := (^Writer)(s.stream_data);
return writer_write_rune(b, r);
},
impl_read_from = proc(s: io.Stream, r: io.Reader) -> (n: i64, err: io.Error) {
b := (^Writer)(s.stream_data);
return writer_read_from(b, r);
},
};
+120
View File
@@ -0,0 +1,120 @@
// This is purely for documentation
package builtin
nil :: nil;
false :: 0!==0;
true :: 0==0;
ODIN_OS :: ODIN_OS;
ODIN_ARCH :: ODIN_ARCH;
ODIN_ENDIAN :: ODIN_ENDIAN;
ODIN_VENDOR :: ODIN_VENDOR;
ODIN_VERSION :: ODIN_VERSION;
ODIN_ROOT :: ODIN_ROOT;
ODIN_DEBUG :: ODIN_DEBUG;
byte :: u8; // alias
bool :: bool;
b8 :: b8;
b16 :: b16;
b32 :: b32;
b64 :: b64;
i8 :: i8;
u8 :: u8;
i16 :: i16;
u16 :: u16;
i32 :: i32;
u32 :: u32;
i64 :: i64;
u64 :: u64;
i128 :: i128;
u128 :: u128;
rune :: rune;
f16 :: f16;
f32 :: f32;
f64 :: f64;
complex32 :: complex32;
complex64 :: complex64;
complex128 :: complex128;
quaternion64 :: quaternion64;
quaternion128 :: quaternion128;
quaternion256 :: quaternion256;
int :: int;
uint :: uint;
uintptr :: uintptr;
rawptr :: rawptr;
string :: string;
cstring :: cstring;
any :: any;
typeid :: typeid;
// Endian Specific Types
i16le :: i16le;
u16le :: u16le;
i32le :: i32le;
u32le :: u32le;
i64le :: i64le;
u64le :: u64le;
i128le :: i128le;
u128le :: u128le;
i16be :: i16be;
u16be :: u16be;
i32be :: i32be;
u32be :: u32be;
i64be :: i64be;
u64be :: u64be;
i128be :: i128be;
u128be :: u128be;
f16le :: f16le;
f32le :: f32le;
f64le :: f64le;
f16be :: f16be;
f32be :: f32be;
f64be :: f64be;
// Procedures
len :: proc(array: Array_Type) -> int ---
cap :: proc(array: Array_Type) -> int ---
size_of :: proc($T: typeid) -> int ---
align_of :: proc($T: typeid) -> int ---
offset_of :: proc($T: typeid) -> uintptr ---
type_of :: proc(x: expr) -> type ---
type_info_of :: proc($T: typeid) -> ^runtime.Type_Info ---
typeid_of :: proc($T: typeid) -> typeid ---
swizzle :: proc(x: [N]T, indices: ..int) -> [len(indices)]T ---
complex :: proc(real, imag: Float) -> Complex_Type ---
quaternion :: proc(real, imag, jmag, kmag: Float) -> Quaternion_Type ---
real :: proc(value: Complex_Or_Quaternion) -> Float ---
imag :: proc(value: Complex_Or_Quaternion) -> Float ---
jmag :: proc(value: Quaternion) -> Float ---
kmag :: proc(value: Quaternion) -> Float ---
conj :: proc(value: Complex_Or_Quaternion) -> Complex_Or_Quaternion ---
expand_to_tuple :: proc(value: Struct_Or_Array) -> (A, B, C, ...) ---
min :: proc(values: ..T) -> T ---
max :: proc(values: ..T) -> T ---
abs :: proc(value: T) -> T ---
clamp :: proc(value, minimum, maximum: T) -> T ---
soa_zip :: proc(slices: ...) -> #soa[]Struct ---
soa_unzip :: proc(value: $S/#soa[]$E) -> (slices: ...) ---
+433
View File
@@ -0,0 +1,433 @@
package bytes
import "core:io"
import "core:unicode/utf8"
MIN_READ :: 512;
@(private)
SMALL_BUFFER_SIZE :: 64;
// A Buffer is a variable-sized buffer of bytes with a io.Stream interface
// The zero value for Buffer is an empty buffer ready to use.
Buffer :: struct {
buf: [dynamic]byte,
off: int,
last_read: Read_Op,
}
@(private)
Read_Op :: enum i8 {
Read = -1,
Invalid = 0,
Read_Rune1 = 1,
Read_Rune2 = 2,
Read_Rune3 = 3,
Read_Rune4 = 4,
}
buffer_init :: proc(b: ^Buffer, buf: []byte) {
resize(&b.buf, len(buf));
copy(b.buf[:], buf);
}
buffer_init_string :: proc(b: ^Buffer, s: string) {
resize(&b.buf, len(s));
copy(b.buf[:], s);
}
buffer_init_allocator :: proc(b: ^Buffer, len, cap: int, allocator := context.allocator) {
b.buf.allocator = allocator;
reserve(&b.buf, cap);
resize(&b.buf, len);
}
buffer_destroy :: proc(b: ^Buffer) {
delete(b.buf);
buffer_reset(b);
}
buffer_to_bytes :: proc(b: ^Buffer) -> []byte {
return b.buf[b.off:];
}
buffer_to_string :: proc(b: ^Buffer) -> string {
if b == nil {
return "<nil>";
}
return string(b.buf[b.off:]);
}
buffer_is_empty :: proc(b: ^Buffer) -> bool {
return len(b.buf) <= b.off;
}
buffer_length :: proc(b: ^Buffer) -> int {
return len(b.buf) - b.off;
}
buffer_capacity :: proc(b: ^Buffer) -> int {
return cap(b.buf);
}
buffer_reset :: proc(b: ^Buffer) {
clear(&b.buf);
b.off = 0;
b.last_read = .Invalid;
}
buffer_truncate :: proc(b: ^Buffer, n: int) {
if n == 0 {
buffer_reset(b);
return;
}
b.last_read = .Invalid;
if n < 0 || n > buffer_length(b) {
panic("bytes.truncate: truncation out of range");
}
resize(&b.buf, b.off+n);
}
@(private)
_buffer_try_grow :: proc(b: ^Buffer, n: int) -> (int, bool) {
if l := len(b.buf); n <= cap(b.buf)-l {
resize(&b.buf, l+n);
return l, true;
}
return 0, false;
}
@(private)
_buffer_grow :: proc(b: ^Buffer, n: int) -> int {
m := buffer_length(b);
if m == 0 && b.off != 0 {
buffer_reset(b);
}
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);
return 0;
}
c := cap(b.buf);
if n <= c/2 - m {
copy(b.buf[:], b.buf[b.off:]);
} else if c > max(int) - c - n {
panic("bytes.Buffer: too large");
} else {
resize(&b.buf, 2*c + n);
copy(b.buf[:], b.buf[b.off:]);
}
b.off = 0;
resize(&b.buf, m+n);
return m;
}
buffer_grow :: proc(b: ^Buffer, n: int) {
if n < 0 {
panic("bytes.buffer_grow: negative count");
}
m := _buffer_grow(b, n);
resize(&b.buf, m);
}
buffer_write_at :: proc(b: ^Buffer, p: []byte, offset: int) -> (n: int, err: io.Error) {
b.last_read = .Invalid;
if offset < 0 {
err = .Invalid_Offset;
return;
}
_, ok := _buffer_try_grow(b, offset+len(p));
if !ok {
_ = _buffer_grow(b, offset+len(p));
}
if len(b.buf) <= offset {
return 0, .Short_Write;
}
return copy(b.buf[offset:], p), nil;
}
buffer_write :: proc(b: ^Buffer, p: []byte) -> (n: int, err: io.Error) {
b.last_read = .Invalid;
m, ok := _buffer_try_grow(b, len(p));
if !ok {
m = _buffer_grow(b, len(p));
}
return copy(b.buf[m:], p), nil;
}
buffer_write_string :: proc(b: ^Buffer, s: string) -> (n: int, err: io.Error) {
b.last_read = .Invalid;
m, ok := _buffer_try_grow(b, len(s));
if !ok {
m = _buffer_grow(b, len(s));
}
return copy(b.buf[m:], s), nil;
}
buffer_write_byte :: proc(b: ^Buffer, c: byte) -> io.Error {
b.last_read = .Invalid;
m, ok := _buffer_try_grow(b, 1);
if !ok {
m = _buffer_grow(b, 1);
}
b.buf[m] = c;
return nil;
}
buffer_write_rune :: proc(b: ^Buffer, r: rune) -> (n: int, err: io.Error) {
if r < utf8.RUNE_SELF {
buffer_write_byte(b, byte(r));
return 1, nil;
}
b.last_read = .Invalid;
m, ok := _buffer_try_grow(b, utf8.UTF_MAX);
if !ok {
m = _buffer_grow(b, utf8.UTF_MAX);
}
res: [4]byte;
res, n = utf8.encode_rune(r);
copy(b.buf[m:][:utf8.UTF_MAX], res[:n]);
resize(&b.buf, m+n);
return;
}
buffer_next :: proc(b: ^Buffer, n: int) -> []byte {
n := n;
b.last_read = .Invalid;
m := buffer_length(b);
if n > m {
n = m;
}
data := b.buf[b.off : b.off + n];
b.off += n;
if n > 0 {
b.last_read = .Read;
}
return data;
}
buffer_read :: proc(b: ^Buffer, p: []byte) -> (n: int, err: io.Error) {
b.last_read = .Invalid;
if buffer_is_empty(b) {
buffer_reset(b);
if len(p) == 0 {
return 0, nil;
}
return 0, .EOF;
}
n = copy(p, b.buf[b.off:]);
b.off += n;
if n > 0 {
b.last_read = .Read;
}
return;
}
buffer_read_at :: proc(b: ^Buffer, p: []byte, offset: int) -> (n: int, err: io.Error) {
b.last_read = .Invalid;
if offset < 0 || offset >= len(b.buf) {
err = .Invalid_Offset;
return;
}
if 0 <= offset && offset < len(b.buf) {
n = copy(p, b.buf[offset:]);
}
if n > 0 {
b.last_read = .Read;
}
return;
}
buffer_read_byte :: proc(b: ^Buffer) -> (byte, io.Error) {
if buffer_is_empty(b) {
buffer_reset(b);
return 0, .EOF;
}
c := b.buf[b.off];
b.off += 1;
b.last_read = .Read;
return c, nil;
}
buffer_read_rune :: proc(b: ^Buffer) -> (r: rune, size: int, err: io.Error) {
if buffer_is_empty(b) {
buffer_reset(b);
return 0, 0, .EOF;
}
c := b.buf[b.off];
if c < utf8.RUNE_SELF {
b.off += 1;
b.last_read = .Read_Rune1;
return rune(c), 1, nil;
}
r, size = utf8.decode_rune(b.buf[b.off:]);
b.off += size;
b.last_read = Read_Op(i8(size));
return;
}
buffer_unread_byte :: proc(b: ^Buffer) -> io.Error {
if b.last_read == .Invalid {
return .Invalid_Unread;
}
b.last_read = .Invalid;
if b.off > 0 {
b.off -= 1;
}
return nil;
}
buffer_unread_rune :: proc(b: ^Buffer) -> io.Error {
if b.last_read <= .Invalid {
return .Invalid_Unread;
}
if b.off >= int(b.last_read) {
b.off -= int(i8(b.last_read));
}
b.last_read = .Invalid;
return nil;
}
buffer_read_bytes :: proc(b: ^Buffer, delim: byte) -> (line: []byte, err: io.Error) {
i := index_byte(b.buf[b.off:], delim);
end := b.off + i + 1;
if i < 0 {
end = len(b.buf);
err = .EOF;
}
line = b.buf[b.off:end];
b.off = end;
b.last_read = .Read;
return;
}
buffer_read_string :: proc(b: ^Buffer, delim: byte) -> (line: string, err: io.Error) {
slice: []byte;
slice, err = buffer_read_bytes(b, delim);
return string(slice), err;
}
buffer_write_to :: proc(b: ^Buffer, w: io.Writer) -> (n: i64, err: io.Error) {
b.last_read = .Invalid;
if byte_count := buffer_length(b); byte_count > 0 {
m, e := io.write(w, b.buf[b.off:]);
if m > byte_count {
panic("bytes.buffer_write_to: invalid io.write count");
}
b.off += m;
n = i64(m);
if e != nil {
err = e;
return;
}
if m != byte_count {
err = .Short_Write;
return;
}
}
buffer_reset(b);
return;
}
buffer_read_from :: proc(b: ^Buffer, r: io.Reader) -> (n: i64, err: io.Error) #no_bounds_check {
b.last_read = .Invalid;
for {
i := _buffer_grow(b, MIN_READ);
resize(&b.buf, i);
m, e := io.read(r, b.buf[i:cap(b.buf)]);
if m < 0 {
err = .Negative_Read;
return;
}
resize(&b.buf, i+m);
n += i64(m);
if e == .EOF {
return;
}
if e != nil {
err = e;
return;
}
}
return;
}
buffer_to_stream :: proc(b: ^Buffer) -> (s: io.Stream) {
s.stream_data = b;
s.stream_vtable = _buffer_vtable;
return;
}
@(private)
_buffer_vtable := &io.Stream_VTable{
impl_size = proc(s: io.Stream) -> i64 {
b := (^Buffer)(s.stream_data);
return i64(buffer_capacity(b));
},
impl_read = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
b := (^Buffer)(s.stream_data);
return buffer_read(b, p);
},
impl_read_at = proc(s: io.Stream, p: []byte, offset: i64) -> (n: int, err: io.Error) {
b := (^Buffer)(s.stream_data);
return buffer_read_at(b, p, int(offset));
},
impl_read_byte = proc(s: io.Stream) -> (byte, io.Error) {
b := (^Buffer)(s.stream_data);
return buffer_read_byte(b);
},
impl_read_rune = proc(s: io.Stream) -> (r: rune, size: int, err: io.Error) {
b := (^Buffer)(s.stream_data);
return buffer_read_rune(b);
},
impl_write = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
b := (^Buffer)(s.stream_data);
return buffer_write(b, p);
},
impl_write_at = proc(s: io.Stream, p: []byte, offset: i64) -> (n: int, err: io.Error) {
b := (^Buffer)(s.stream_data);
return buffer_write_at(b, p, int(offset));
},
impl_write_byte = proc(s: io.Stream, c: byte) -> io.Error {
b := (^Buffer)(s.stream_data);
return buffer_write_byte(b, c);
},
impl_write_rune = proc(s: io.Stream, r: rune) -> (int, io.Error) {
b := (^Buffer)(s.stream_data);
return buffer_write_rune(b, r);
},
impl_unread_byte = proc(s: io.Stream) -> io.Error {
b := (^Buffer)(s.stream_data);
return buffer_unread_byte(b);
},
impl_unread_rune = proc(s: io.Stream) -> io.Error {
b := (^Buffer)(s.stream_data);
return buffer_unread_rune(b);
},
impl_destroy = proc(s: io.Stream) -> io.Error {
b := (^Buffer)(s.stream_data);
buffer_destroy(b);
return nil;
},
impl_write_to = proc(s: io.Stream, w: io.Writer) -> (n: i64, err: io.Error) {
b := (^Buffer)(s.stream_data);
return buffer_write_to(b, w);
},
impl_read_from = proc(s: io.Stream, r: io.Reader) -> (n: i64, err: io.Error) {
b := (^Buffer)(s.stream_data);
return buffer_read_from(b, r);
},
};
File diff suppressed because it is too large Load Diff
+177
View File
@@ -0,0 +1,177 @@
package bytes
import "core:io"
import "core:unicode/utf8"
Reader :: struct {
s: []byte, // read-only buffer
i: i64, // current reading index
prev_rune: int, // previous reading index of rune or < 0
}
reader_init :: proc(r: ^Reader, s: []byte) {
r.s = s;
r.i = 0;
r.prev_rune = -1;
}
reader_to_stream :: proc(r: ^Reader) -> (s: io.Stream) {
s.stream_data = r;
s.stream_vtable = _reader_vtable;
return;
}
reader_length :: proc(r: ^Reader) -> int {
if r.i >= i64(len(r.s)) {
return 0;
}
return int(i64(len(r.s)) - r.i);
}
reader_size :: proc(r: ^Reader) -> i64 {
return i64(len(r.s));
}
reader_read :: proc(r: ^Reader, p: []byte) -> (n: int, err: io.Error) {
if r.i >= i64(len(r.s)) {
return 0, .EOF;
}
r.prev_rune = -1;
n = copy(p, r.s[r.i:]);
r.i += i64(n);
return;
}
reader_read_at :: proc(r: ^Reader, p: []byte, off: i64) -> (n: int, err: io.Error) {
if off < 0 {
return 0, .Invalid_Offset;
}
if off >= i64(len(r.s)) {
return 0, .EOF;
}
n = copy(p, r.s[off:]);
if n < len(p) {
err = .EOF;
}
return;
}
reader_read_byte :: proc(r: ^Reader) -> (byte, io.Error) {
r.prev_rune = -1;
if r.i >= i64(len(r.s)) {
return 0, .EOF;
}
b := r.s[r.i];
r.i += 1;
return b, nil;
}
reader_unread_byte :: proc(r: ^Reader) -> io.Error {
if r.i <= 0 {
return .Invalid_Unread;
}
r.prev_rune = -1;
r.i -= 1;
return nil;
}
reader_read_rune :: proc(r: ^Reader) -> (ch: rune, size: int, err: io.Error) {
if r.i >= i64(len(r.s)) {
r.prev_rune = -1;
return 0, 0, .EOF;
}
r.prev_rune = int(r.i);
if c := r.s[r.i]; c < utf8.RUNE_SELF {
r.i += 1;
return rune(c), 1, nil;
}
ch, size = utf8.decode_rune(r.s[r.i:]);
r.i += i64(size);
return;
}
reader_unread_rune :: proc(r: ^Reader) -> io.Error {
if r.i <= 0 {
return .Invalid_Unread;
}
if r.prev_rune < 0 {
return .Invalid_Unread;
}
r.i = i64(r.prev_rune);
r.prev_rune = -1;
return nil;
}
reader_seek :: proc(r: ^Reader, offset: i64, whence: io.Seek_From) -> (i64, io.Error) {
r.prev_rune = -1;
abs: i64;
switch whence {
case .Start:
abs = offset;
case .Current:
abs = r.i + offset;
case .End:
abs = i64(len(r.s)) + offset;
case:
return 0, .Invalid_Whence;
}
if abs < 0 {
return 0, .Invalid_Offset;
}
r.i = abs;
return abs, nil;
}
reader_write_to :: proc(r: ^Reader, w: io.Writer) -> (n: i64, err: io.Error) {
r.prev_rune = -1;
if r.i >= i64(len(r.s)) {
return 0, nil;
}
s := r.s[r.i:];
m: int;
m, err = io.write(w, s);
if m > len(s) {
panic("bytes.Reader.write_to: invalid io.write_string count");
}
r.i += i64(m);
n = i64(m);
if m != len(s) && err == nil {
err = .Short_Write;
}
return;
}
@(private)
_reader_vtable := &io.Stream_VTable{
impl_size = proc(s: io.Stream) -> i64 {
r := (^Reader)(s.stream_data);
return reader_size(r);
},
impl_read = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
r := (^Reader)(s.stream_data);
return reader_read(r, p);
},
impl_read_at = proc(s: io.Stream, p: []byte, off: i64) -> (n: int, err: io.Error) {
r := (^Reader)(s.stream_data);
return reader_read_at(r, p, off);
},
impl_read_byte = proc(s: io.Stream) -> (byte, io.Error) {
r := (^Reader)(s.stream_data);
return reader_read_byte(r);
},
impl_unread_byte = proc(s: io.Stream) -> io.Error {
r := (^Reader)(s.stream_data);
return reader_unread_byte(r);
},
impl_read_rune = proc(s: io.Stream) -> (ch: rune, size: int, err: io.Error) {
r := (^Reader)(s.stream_data);
return reader_read_rune(r);
},
impl_unread_rune = proc(s: io.Stream) -> io.Error {
r := (^Reader)(s.stream_data);
return reader_unread_rune(r);
},
impl_seek = proc(s: io.Stream, offset: i64, whence: io.Seek_From) -> (i64, io.Error) {
r := (^Reader)(s.stream_data);
return reader_seek(r, offset, whence);
},
impl_write_to = proc(s: io.Stream, w: io.Writer) -> (n: i64, err: io.Error) {
r := (^Reader)(s.stream_data);
return reader_write_to(r, w);
},
};
-38
View File
@@ -1,38 +0,0 @@
CHAR_BIT :: 8;
c_bool :: #alias bool;
c_char :: #alias u8;
c_byte :: #alias u8;
c_schar :: #alias i8;
c_uchar :: #alias u8;
c_short :: #alias i16;
c_ushort :: #alias u16;
c_int :: #alias i32;
c_uint :: #alias u32;
when ODIN_OS == "windows" || size_of(rawptr) == 4 {
c_long :: #alias i32;
} else {
c_long :: #alias i64;
}
when ODIN_OS == "windows" || size_of(rawptr) == 4 {
c_ulong :: #alias u32;
} else {
c_ulong :: #alias u64;
}
c_longlong :: #alias i64;
c_ulonglong :: #alias u64;
c_float :: #alias f32;
c_double :: #alias f64;
c_complex_float :: #alias complex64;
c_complex_double :: #alias complex128;
_ :: compile_assert(size_of(uintptr) == size_of(int));
c_size_t :: #alias uint;
c_ssize_t :: #alias int;
c_ptrdiff_t :: #alias int;
c_uintptr_t :: #alias uintptr;
c_intptr_t :: #alias int;
+35
View File
@@ -0,0 +1,35 @@
package c
import b "core:builtin"
CHAR_BIT :: 8;
bool :: b.bool;
char :: b.u8;
byte :: b.byte;
schar :: b.i8;
uchar :: b.u8;
short :: b.i16;
ushort :: b.u16;
int :: b.i32;
uint :: b.u32;
long :: b.i32 when (ODIN_OS == "windows" || size_of(b.rawptr) == 4) else b.i64;
ulong :: b.u32 when (ODIN_OS == "windows" || size_of(b.rawptr) == 4) else b.u64;
longlong :: b.i64;
ulonglong :: b.u64;
float :: b.f32;
double :: b.f64;
complex_float :: b.complex64;
complex_double :: b.complex128;
#assert(size_of(b.uintptr) == size_of(b.int));
size_t :: b.uint;
ssize_t :: b.int;
ptrdiff_t :: b.int;
uintptr_t :: b.uintptr;
intptr_t :: b.int;
wchar_t :: b.u16 when (ODIN_OS == "windows") else b.u32;
@@ -0,0 +1,25 @@
package c_frontend_preprocess
import "core:c/frontend/tokenizer"
const_expr :: proc(rest: ^^Token, tok: ^Token) -> i64 {
// TODO(bill): Handle const_expr correctly
// This is effectively a mini-parser
assert(rest != nil);
assert(tok != nil);
rest^ = tokenizer.new_eof(tok);
switch v in tok.val {
case i64:
return v;
case f64:
return i64(v);
case string:
return 0;
case []u16:
// TODO
case []u32:
// TODO
}
return 0;
}
File diff suppressed because it is too large Load Diff
+154
View File
@@ -0,0 +1,154 @@
package c_frontend_preprocess
import "core:unicode/utf8"
unquote_char :: proc(str: string, quote: byte) -> (r: rune, multiple_bytes: bool, tail_string: string, success: bool) {
hex_to_int :: proc(c: byte) -> int {
switch c {
case '0'..'9': return int(c-'0');
case 'a'..'f': return int(c-'a')+10;
case 'A'..'F': return int(c-'A')+10;
}
return -1;
}
w: int;
if str[0] == quote && quote == '"' {
return;
} else if str[0] >= 0x80 {
r, w = utf8.decode_rune_in_string(str);
return r, true, str[w:], true;
} else if str[0] != '\\' {
return rune(str[0]), false, str[1:], true;
}
if len(str) <= 1 {
return;
}
s := str;
c := s[1];
s = s[2:];
switch c {
case: r = rune(c);
case 'a': r = '\a';
case 'b': r = '\b';
case 'e': r = '\e';
case 'f': r = '\f';
case 'n': r = '\n';
case 'r': r = '\r';
case 't': r = '\t';
case 'v': r = '\v';
case '\\': r = '\\';
case '"': r = '"';
case '\'': r = '\'';
case '0'..'7':
v := int(c-'0');
if len(s) < 2 {
return;
}
for i in 0..<len(s) {
d := int(s[i]-'0');
if d < 0 || d > 7 {
return;
}
v = (v<<3) | d;
}
s = s[2:];
if v > 0xff {
return;
}
r = rune(v);
case 'x', 'u', 'U':
count: int;
switch c {
case 'x': count = 2;
case 'u': count = 4;
case 'U': count = 8;
}
if len(s) < count {
return;
}
for i in 0..<count {
d := hex_to_int(s[i]);
if d < 0 {
return;
}
r = (r<<4) | rune(d);
}
s = s[count:];
if c == 'x' {
break;
}
if r > utf8.MAX_RUNE {
return;
}
multiple_bytes = true;
}
success = true;
tail_string = s;
return;
}
unquote_string :: proc(lit: string, allocator := context.allocator) -> (res: string, allocated, success: bool) {
contains_rune :: proc(s: string, r: rune) -> int {
for c, offset in s {
if c == r {
return offset;
}
}
return -1;
}
assert(len(lit) >= 2);
s := lit;
quote := '"';
if s == `""` {
return "", false, true;
}
if contains_rune(s, '\n') >= 0 {
return s, false, false;
}
if contains_rune(s, '\\') < 0 && contains_rune(s, quote) < 0 {
if quote == '"' {
return s, false, true;
}
}
s = s[1:len(s)-1];
buf_len := 3*len(s) / 2;
buf := make([]byte, buf_len, allocator);
offset := 0;
for len(s) > 0 {
r, multiple_bytes, tail_string, ok := unquote_char(s, byte(quote));
if !ok {
delete(buf);
return s, false, false;
}
s = tail_string;
if r < 0x80 || !multiple_bytes {
buf[offset] = byte(r);
offset += 1;
} else {
b, w := utf8.encode_rune(r);
copy(buf[offset:], b[:w]);
offset += w;
}
}
new_string := string(buf[:offset]);
return new_string, true, true;
}
+34
View File
@@ -0,0 +1,34 @@
/*
package demo
import tokenizer "core:c/frontend/tokenizer"
import preprocessor "core:c/frontend/preprocessor"
import "core:fmt"
main :: proc() {
t := &tokenizer.Tokenizer{};
tokenizer.init_defaults(t);
cpp := &preprocessor.Preprocessor{};
cpp.warn, cpp.err = t.warn, t.err;
preprocessor.init_lookup_tables(cpp);
preprocessor.init_default_macros(cpp);
cpp.include_paths = {"my/path/to/include"};
tok := tokenizer.tokenize_file(t, "the/source/file.c", 1);
tok = preprocessor.preprocess(cpp, tok);
if tok != nil {
for t := tok; t.kind != .EOF; t = t.next {
fmt.println(t.lit);
}
}
fmt.println("[Done]");
}
*/
package c_frontend_tokenizer
+68
View File
@@ -0,0 +1,68 @@
package c_frontend_tokenizer
// NOTE(bill): This is a really dumb approach for a hide set,
// but it's really simple and probably fast enough in practice
Hide_Set :: struct {
next: ^Hide_Set,
name: string,
}
new_hide_set :: proc(name: string) -> ^Hide_Set {
hs := new(Hide_Set);
hs.name = name;
return hs;
}
hide_set_contains :: proc(hs: ^Hide_Set, name: string) -> bool {
for h := hs; h != nil; h = h.next {
if h.name == name {
return true;
}
}
return false;
}
hide_set_union :: proc(a, b: ^Hide_Set) -> ^Hide_Set {
head: Hide_Set;
curr := &head;
for h := a; h != nil; h = h.next {
curr.next = new_hide_set(h.name);
curr = curr.next;
}
curr.next = b;
return head.next;
}
hide_set_intersection :: proc(a, b: ^Hide_Set) -> ^Hide_Set {
head: Hide_Set;
curr := &head;
for h := a; h != nil; h = h.next {
if hide_set_contains(b, h.name) {
curr.next = new_hide_set(h.name);
curr = curr.next;
}
}
return head.next;
}
add_hide_set :: proc(tok: ^Token, hs: ^Hide_Set) -> ^Token {
head: Token;
curr := &head;
tok := tok;
for ; tok != nil; tok = tok.next {
t := copy_token(tok);
t.hide_set = hide_set_union(t.hide_set, hs);
curr.next = t;
curr = curr.next;
}
return head.next;
}
+169
View File
@@ -0,0 +1,169 @@
package c_frontend_tokenizer
Pos :: struct {
file: string,
line: int,
column: int,
offset: int,
}
Token_Kind :: enum {
Invalid,
Ident,
Punct,
Keyword,
Char,
String,
Number,
PP_Number,
Comment,
EOF,
}
File :: struct {
name: string,
id: int,
src: []byte,
display_name: string,
line_delta: int,
}
Token_Type_Hint :: enum u8 {
None,
Int,
Long,
Long_Long,
Unsigned_Int,
Unsigned_Long,
Unsigned_Long_Long,
Float,
Double,
Long_Double,
UTF_8,
UTF_16,
UTF_32,
UTF_Wide,
}
Token_Value :: union {
i64,
f64,
string,
[]u16,
[]u32,
}
Token :: struct {
kind: Token_Kind,
next: ^Token,
lit: string,
pos: Pos,
file: ^File,
line_delta: int,
at_bol: bool,
has_space: bool,
type_hint: Token_Type_Hint,
val: Token_Value,
prefix: string,
// Preprocessor values
hide_set: ^Hide_Set,
origin: ^Token,
}
Is_Keyword_Proc :: #type proc(tok: ^Token) -> bool;
copy_token :: proc(tok: ^Token) -> ^Token {
t := new_clone(tok^);
t.next = nil;
return t;
}
new_eof :: proc(tok: ^Token) -> ^Token {
t := new_clone(tok^);
t.kind = .EOF;
t.lit = "";
return t;
}
default_is_keyword :: proc(tok: ^Token) -> bool {
if tok.kind == .Keyword {
return true;
}
if len(tok.lit) > 0 {
return default_keyword_set[tok.lit];
}
return false;
}
token_name := [Token_Kind]string {
.Invalid = "invalid",
.Ident = "ident",
.Punct = "punct",
.Keyword = "keyword",
.Char = "char",
.String = "string",
.Number = "number",
.PP_Number = "preprocessor number",
.Comment = "comment",
.EOF = "eof",
};
default_keyword_set := map[string]bool{
"auto" = true,
"break" = true,
"case" = true,
"char" = true,
"const" = true,
"continue" = true,
"default" = true,
"do" = true,
"double" = true,
"else" = true,
"enum" = true,
"extern" = true,
"float" = true,
"for" = true,
"goto" = true,
"if" = true,
"int" = true,
"long" = true,
"register" = true,
"restrict" = true,
"return" = true,
"short" = true,
"signed" = true,
"sizeof" = true,
"static" = true,
"struct" = true,
"switch" = true,
"typedef" = true,
"union" = true,
"unsigned" = true,
"void" = true,
"volatile" = true,
"while" = true,
"_Alignas" = true,
"_Alignof" = true,
"_Atomic" = true,
"_Bool" = true,
"_Generic" = true,
"_Noreturn" = true,
"_Thread_local" = true,
"__restrict" = true,
"typeof" = true,
"asm" = true,
"__restrict__" = true,
"__thread" = true,
"__attribute__" = true,
};
+667
View File
@@ -0,0 +1,667 @@
package c_frontend_tokenizer
import "core:fmt"
import "core:os"
import "core:strings"
import "core:unicode/utf8"
Error_Handler :: #type proc(pos: Pos, fmt: string, args: ..any);
Tokenizer :: struct {
// Immutable data
path: string,
src: []byte,
// Tokenizing state
ch: rune,
offset: int,
read_offset: int,
line_offset: int,
line_count: int,
// Extra information for tokens
at_bol: bool,
has_space: bool,
// Mutable data
err: Error_Handler,
warn: Error_Handler,
error_count: int,
warning_count: int,
}
init_defaults :: proc(t: ^Tokenizer, err: Error_Handler = default_error_handler, warn: Error_Handler = default_warn_handler) {
t.err = err;
t.warn = warn;
}
@(private)
offset_to_pos :: proc(t: ^Tokenizer, offset: int) -> (pos: Pos) {
pos.file = t.path;
pos.offset = offset;
pos.line = t.line_count;
pos.column = offset - t.line_offset + 1;
return;
}
default_error_handler :: proc(pos: Pos, msg: string, args: ..any) {
fmt.eprintf("%s(%d:%d) ", pos.file, pos.line, pos.column);
fmt.eprintf(msg, ..args);
fmt.eprintf("\n");
}
default_warn_handler :: proc(pos: Pos, msg: string, args: ..any) {
fmt.eprintf("%s(%d:%d) warning: ", pos.file, pos.line, pos.column);
fmt.eprintf(msg, ..args);
fmt.eprintf("\n");
}
error_offset :: proc(t: ^Tokenizer, offset: int, msg: string, args: ..any) {
pos := offset_to_pos(t, offset);
if t.err != nil {
t.err(pos, msg, ..args);
}
t.error_count += 1;
}
warn_offset :: proc(t: ^Tokenizer, offset: int, msg: string, args: ..any) {
pos := offset_to_pos(t, offset);
if t.warn != nil {
t.warn(pos, msg, ..args);
}
t.warning_count += 1;
}
error :: proc(t: ^Tokenizer, tok: ^Token, msg: string, args: ..any) {
pos := tok.pos;
if t.err != nil {
t.err(pos, msg, ..args);
}
t.error_count += 1;
}
warn :: proc(t: ^Tokenizer, tok: ^Token, msg: string, args: ..any) {
pos := tok.pos;
if t.warn != nil {
t.warn(pos, msg, ..args);
}
t.warning_count += 1;
}
advance_rune :: proc(t: ^Tokenizer) {
if t.read_offset < len(t.src) {
t.offset = t.read_offset;
if t.ch == '\n' {
t.at_bol = true;
t.line_offset = t.offset;
t.line_count += 1;
}
r, w := rune(t.src[t.read_offset]), 1;
switch {
case r == 0:
error_offset(t, t.offset, "illegal character NUL");
case r >= utf8.RUNE_SELF:
r, w = utf8.decode_rune(t.src[t.read_offset:]);
if r == utf8.RUNE_ERROR && w == 1 {
error_offset(t, t.offset, "illegal UTF-8 encoding");
} else if r == utf8.RUNE_BOM && t.offset > 0 {
error_offset(t, t.offset, "illegal byte order mark");
}
}
t.read_offset += w;
t.ch = r;
} else {
t.offset = len(t.src);
if t.ch == '\n' {
t.at_bol = true;
t.line_offset = t.offset;
t.line_count += 1;
}
t.ch = -1;
}
}
advance_rune_n :: proc(t: ^Tokenizer, n: int) {
for in 0..<n {
advance_rune(t);
}
}
is_digit :: proc(r: rune) -> bool {
return '0' <= r && r <= '9';
}
skip_whitespace :: proc(t: ^Tokenizer) {
for {
switch t.ch {
case ' ', '\t', '\r', '\v', '\f', '\n':
t.has_space = true;
advance_rune(t);
case:
return;
}
}
}
scan_comment :: proc(t: ^Tokenizer) -> string {
offset := t.offset-1;
next := -1;
general: {
if t.ch == '/'{ // line comments
advance_rune(t);
for t.ch != '\n' && t.ch >= 0 {
advance_rune(t);
}
next = t.offset;
if t.ch == '\n' {
next += 1;
}
break general;
}
/* style comment */
advance_rune(t);
for t.ch >= 0 {
ch := t.ch;
advance_rune(t);
if ch == '*' && t.ch == '/' {
advance_rune(t);
next = t.offset;
break general;
}
}
error_offset(t, offset, "comment not terminated");
}
lit := t.src[offset : t.offset];
// NOTE(bill): Strip CR for line comments
for len(lit) > 2 && lit[1] == '/' && lit[len(lit)-1] == '\r' {
lit = lit[:len(lit)-1];
}
return string(lit);
}
scan_identifier :: proc(t: ^Tokenizer) -> string {
offset := t.offset;
for is_ident1(t.ch) {
advance_rune(t);
}
return string(t.src[offset : t.offset]);
}
scan_string :: proc(t: ^Tokenizer) -> string {
offset := t.offset-1;
for {
ch := t.ch;
if ch == '\n' || ch < 0 {
error_offset(t, offset, "string literal was not terminated");
break;
}
advance_rune(t);
if ch == '"' {
break;
}
if ch == '\\' {
scan_escape(t);
}
}
return string(t.src[offset : t.offset]);
}
digit_val :: proc(r: rune) -> int {
switch r {
case '0'..'9':
return int(r-'0');
case 'A'..'F':
return int(r-'A' + 10);
case 'a'..'f':
return int(r-'a' + 10);
}
return 16;
}
scan_escape :: proc(t: ^Tokenizer) -> bool {
offset := t.offset;
esc := t.ch;
n: int;
base, max: u32;
switch esc {
case 'a', 'b', 'e', 'f', 'n', 't', 'v', 'r', '\\', '\'', '"':
advance_rune(t);
return true;
case '0'..'7':
for digit_val(t.ch) < 8 {
advance_rune(t);
}
return true;
case 'x':
advance_rune(t);
for digit_val(t.ch) < 16 {
advance_rune(t);
}
return true;
case 'u':
advance_rune(t);
n, base, max = 4, 16, utf8.MAX_RUNE;
case 'U':
advance_rune(t);
n, base, max = 8, 16, utf8.MAX_RUNE;
case:
if t.ch < 0 {
error_offset(t, offset, "escape sequence was not terminated");
} else {
break;
}
return false;
}
x: u32;
main_loop: for n > 0 {
d := u32(digit_val(t.ch));
if d >= base {
if t.ch == '"' || t.ch == '\'' {
break main_loop;
}
if t.ch < 0 {
error_offset(t, t.offset, "escape sequence was not terminated");
} else {
error_offset(t, t.offset, "illegal character '%r' : %d in escape sequence", t.ch, t.ch);
}
return false;
}
x = x*base + d;
advance_rune(t);
n -= 1;
}
if x > max || 0xd800 <= x && x <= 0xe000 {
error_offset(t, offset, "escape sequence is an invalid Unicode code point");
return false;
}
return true;
}
scan_rune :: proc(t: ^Tokenizer) -> string {
offset := t.offset-1;
valid := true;
n := 0;
for {
ch := t.ch;
if ch == '\n' || ch < 0 {
if valid {
error_offset(t, offset, "rune literal not terminated");
valid = false;
}
break;
}
advance_rune(t);
if ch == '\'' {
break;
}
n += 1;
if ch == '\\' {
if !scan_escape(t) {
valid = false;
}
}
}
if valid && n != 1 {
error_offset(t, offset, "illegal rune literal");
}
return string(t.src[offset : t.offset]);
}
scan_number :: proc(t: ^Tokenizer, seen_decimal_point: bool) -> (Token_Kind, string) {
scan_mantissa :: proc(t: ^Tokenizer, base: int) {
for digit_val(t.ch) < base {
advance_rune(t);
}
}
scan_exponent :: proc(t: ^Tokenizer) {
if t.ch == 'e' || t.ch == 'E' || t.ch == 'p' || t.ch == 'P' {
advance_rune(t);
if t.ch == '-' || t.ch == '+' {
advance_rune(t);
}
if digit_val(t.ch) < 10 {
scan_mantissa(t, 10);
} else {
error_offset(t, t.offset, "illegal floating-point exponent");
}
}
}
scan_fraction :: proc(t: ^Tokenizer) -> (early_exit: bool) {
if t.ch == '.' && peek(t) == '.' {
return true;
}
if t.ch == '.' {
advance_rune(t);
scan_mantissa(t, 10);
}
return false;
}
check_end := true;
offset := t.offset;
seen_point := seen_decimal_point;
if seen_point {
offset -= 1;
scan_mantissa(t, 10);
scan_exponent(t);
} else {
if t.ch == '0' {
int_base :: proc(t: ^Tokenizer, base: int, msg: string) {
prev := t.offset;
advance_rune(t);
scan_mantissa(t, base);
if t.offset - prev <= 1 {
error_offset(t, t.offset, msg);
}
}
advance_rune(t);
switch t.ch {
case 'b', 'B':
int_base(t, 2, "illegal binary integer");
case 'x', 'X':
int_base(t, 16, "illegal hexadecimal integer");
case:
seen_point = false;
scan_mantissa(t, 10);
if t.ch == '.' {
seen_point = true;
if scan_fraction(t) {
check_end = false;
}
}
if check_end {
scan_exponent(t);
check_end = false;
}
}
}
}
if check_end {
scan_mantissa(t, 10);
if !scan_fraction(t) {
scan_exponent(t);
}
}
return .Number, string(t.src[offset : t.offset]);
}
scan_punct :: proc(t: ^Tokenizer, ch: rune) -> (kind: Token_Kind) {
kind = .Punct;
switch ch {
case:
kind = .Invalid;
case '<', '>':
if t.ch == ch {
advance_rune(t);
}
if t.ch == '=' {
advance_rune(t);
}
case '!', '+', '-', '*', '/', '%', '^', '=':
if t.ch == '=' {
advance_rune(t);
}
case '#':
if t.ch == '#' {
advance_rune(t);
}
case '&':
if t.ch == '=' || t.ch == '&' {
advance_rune(t);
}
case '|':
if t.ch == '=' || t.ch == '|' {
advance_rune(t);
}
case '(', ')', '[', ']', '{', '}':
// okay
case '~', ',', ':', ';', '?':
// okay
case '`':
// okay
case '.':
if t.ch == '.' && peek(t) == '.' {
advance_rune(t);
advance_rune(t); // consume last '.'
}
}
return;
}
peek :: proc(t: ^Tokenizer) -> byte {
if t.read_offset < len(t.src) {
return t.src[t.read_offset];
}
return 0;
}
peek_str :: proc(t: ^Tokenizer, str: string) -> bool {
if t.read_offset < len(t.src) {
return strings.has_prefix(string(t.src[t.offset:]), str);
}
return false;
}
scan_literal_prefix :: proc(t: ^Tokenizer, str: string, prefix: ^string) -> bool {
if peek_str(t, str) {
offset := t.offset;
for _ in str {
advance_rune(t);
}
prefix^ = string(t.src[offset:][:len(str)-1]);
return true;
}
return false;
}
allow_next_to_be_newline :: proc(t: ^Tokenizer) -> bool {
if t.ch == '\n' {
advance_rune(t);
return true;
} else if t.ch == '\r' && peek(t) == '\n' { // allow for MS-DOS style line endings
advance_rune(t); // \r
advance_rune(t); // \n
return true;
}
return false;
}
scan :: proc(t: ^Tokenizer, f: ^File) -> ^Token {
skip_whitespace(t);
offset := t.offset;
kind: Token_Kind;
lit: string;
prefix: string;
switch ch := t.ch; {
case scan_literal_prefix(t, `u8"`, &prefix):
kind = .String;
lit = scan_string(t);
case scan_literal_prefix(t, `u"`, &prefix):
kind = .String;
lit = scan_string(t);
case scan_literal_prefix(t, `L"`, &prefix):
kind = .String;
lit = scan_string(t);
case scan_literal_prefix(t, `U"`, &prefix):
kind = .String;
lit = scan_string(t);
case scan_literal_prefix(t, `u'`, &prefix):
kind = .Char;
lit = scan_rune(t);
case scan_literal_prefix(t, `L'`, &prefix):
kind = .Char;
lit = scan_rune(t);
case scan_literal_prefix(t, `U'`, &prefix):
kind = .Char;
lit = scan_rune(t);
case is_ident0(ch):
lit = scan_identifier(t);
kind = .Ident;
case '0' <= ch && ch <= '9':
kind, lit = scan_number(t, false);
case:
advance_rune(t);
switch ch {
case -1:
kind = .EOF;
case '\\':
kind = .Punct;
if allow_next_to_be_newline(t) {
t.at_bol = true;
t.has_space = false;
return scan(t, f);
}
case '.':
if is_digit(t.ch) {
kind, lit = scan_number(t, true);
} else {
kind = scan_punct(t, ch);
}
case '"':
kind = .String;
lit = scan_string(t);
case '\'':
kind = .Char;
lit = scan_rune(t);
case '/':
if t.ch == '/' || t.ch == '*' {
kind = .Comment;
lit = scan_comment(t);
t.has_space = true;
break;
}
fallthrough;
case:
kind = scan_punct(t, ch);
if kind == .Invalid && ch != utf8.RUNE_BOM {
error_offset(t, t.offset, "illegal character '%r': %d", ch, ch);
}
}
}
if lit == "" {
lit = string(t.src[offset : t.offset]);
}
if kind == .Comment {
return scan(t, f);
}
tok := new(Token);
tok.kind = kind;
tok.lit = lit;
tok.pos = offset_to_pos(t, offset);
tok.file = f;
tok.prefix = prefix;
tok.at_bol = t.at_bol;
tok.has_space = t.has_space;
t.at_bol, t.has_space = false, false;
return tok;
}
tokenize :: proc(t: ^Tokenizer, f: ^File) -> ^Token {
setup_tokenizer: {
t.src = f.src;
t.ch = ' ';
t.offset = 0;
t.read_offset = 0;
t.line_offset = 0;
t.line_count = len(t.src) > 0 ? 1 : 0;
t.error_count = 0;
t.path = f.name;
advance_rune(t);
if t.ch == utf8.RUNE_BOM {
advance_rune(t);
}
}
t.at_bol = true;
t.has_space = false;
head: Token;
curr := &head;
for {
tok := scan(t, f);
if tok == nil {
break;
}
curr.next = tok;
curr = curr.next;
if tok.kind == .EOF {
break;
}
}
return head.next;
}
add_new_file :: proc(t: ^Tokenizer, name: string, src: []byte, id: int) -> ^File {
file := new(File);
file.id = id;
file.src = src;
file.name = name;
file.display_name = name;
return file;
}
tokenize_file :: proc(t: ^Tokenizer, path: string, id: int, loc := #caller_location) -> ^Token {
src, ok := os.read_entire_file(path);
if !ok {
return nil;
}
return tokenize(t, add_new_file(t, path, src, id));
}
inline_tokenize :: proc(t: ^Tokenizer, tok: ^Token, src: []byte) -> ^Token {
file := new(File);
file.src = src;
if tok.file != nil {
file.id = tok.file.id;
file.name = tok.file.name;
file.display_name = tok.file.name;
}
return tokenize(t, file);
}
+116
View File
@@ -0,0 +1,116 @@
package c_frontend_tokenizer
in_range :: proc(range: []rune, c: rune) -> bool #no_bounds_check {
for i := 0; range[i] != -1; i += 2 {
if range[i] <= c && c <= range[i+1] {
return true;
}
}
return false;
}
// [https://www.sigbus.info/n1570#D] C11 allows ASCII and some multibyte characters in certan Unicode ranges to be used in an identifier.
//
// is_ident0 returns true if a given character is acceptable as the first character of an identifier.
is_ident0 :: proc(c: rune) -> bool {
return in_range(_range_ident0, c);
}
// is_ident0 returns true if a given character is acceptable as a non-first character of an identifier.
is_ident1 :: proc(c: rune) -> bool {
return is_ident0(c) || in_range(_range_ident1, c);
}
// Returns the number of columns needed to display a given character in a fixed-width font.
// Based on https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
char_width :: proc(c: rune) -> int {
switch {
case in_range(_range_width0, c):
return 0;
case in_range(_range_width2, c):
return 2;
}
return 1;
}
display_width :: proc(str: string) -> (w: int) {
for c in str {
w += char_width(c);
}
return;
}
_range_ident0 := []rune{
'_', '_', 'a', 'z', 'A', 'Z', '$', '$',
0x00A8, 0x00A8, 0x00AA, 0x00AA, 0x00AD, 0x00AD, 0x00AF, 0x00AF,
0x00B2, 0x00B5, 0x00B7, 0x00BA, 0x00BC, 0x00BE, 0x00C0, 0x00D6,
0x00D8, 0x00F6, 0x00F8, 0x00FF, 0x0100, 0x02FF, 0x0370, 0x167F,
0x1681, 0x180D, 0x180F, 0x1DBF, 0x1E00, 0x1FFF, 0x200B, 0x200D,
0x202A, 0x202E, 0x203F, 0x2040, 0x2054, 0x2054, 0x2060, 0x206F,
0x2070, 0x20CF, 0x2100, 0x218F, 0x2460, 0x24FF, 0x2776, 0x2793,
0x2C00, 0x2DFF, 0x2E80, 0x2FFF, 0x3004, 0x3007, 0x3021, 0x302F,
0x3031, 0x303F, 0x3040, 0xD7FF, 0xF900, 0xFD3D, 0xFD40, 0xFDCF,
0xFDF0, 0xFE1F, 0xFE30, 0xFE44, 0xFE47, 0xFFFD,
0x10000, 0x1FFFD, 0x20000, 0x2FFFD, 0x30000, 0x3FFFD, 0x40000, 0x4FFFD,
0x50000, 0x5FFFD, 0x60000, 0x6FFFD, 0x70000, 0x7FFFD, 0x80000, 0x8FFFD,
0x90000, 0x9FFFD, 0xA0000, 0xAFFFD, 0xB0000, 0xBFFFD, 0xC0000, 0xCFFFD,
0xD0000, 0xDFFFD, 0xE0000, 0xEFFFD,
-1,
};
_range_ident1 := []rune{
'0', '9', '$', '$', 0x0300, 0x036F, 0x1DC0, 0x1DFF, 0x20D0, 0x20FF, 0xFE20, 0xFE2F,
-1,
};
_range_width0 := []rune{
0x0000, 0x001F, 0x007f, 0x00a0, 0x0300, 0x036F, 0x0483, 0x0486,
0x0488, 0x0489, 0x0591, 0x05BD, 0x05BF, 0x05BF, 0x05C1, 0x05C2,
0x05C4, 0x05C5, 0x05C7, 0x05C7, 0x0600, 0x0603, 0x0610, 0x0615,
0x064B, 0x065E, 0x0670, 0x0670, 0x06D6, 0x06E4, 0x06E7, 0x06E8,
0x06EA, 0x06ED, 0x070F, 0x070F, 0x0711, 0x0711, 0x0730, 0x074A,
0x07A6, 0x07B0, 0x07EB, 0x07F3, 0x0901, 0x0902, 0x093C, 0x093C,
0x0941, 0x0948, 0x094D, 0x094D, 0x0951, 0x0954, 0x0962, 0x0963,
0x0981, 0x0981, 0x09BC, 0x09BC, 0x09C1, 0x09C4, 0x09CD, 0x09CD,
0x09E2, 0x09E3, 0x0A01, 0x0A02, 0x0A3C, 0x0A3C, 0x0A41, 0x0A42,
0x0A47, 0x0A48, 0x0A4B, 0x0A4D, 0x0A70, 0x0A71, 0x0A81, 0x0A82,
0x0ABC, 0x0ABC, 0x0AC1, 0x0AC5, 0x0AC7, 0x0AC8, 0x0ACD, 0x0ACD,
0x0AE2, 0x0AE3, 0x0B01, 0x0B01, 0x0B3C, 0x0B3C, 0x0B3F, 0x0B3F,
0x0B41, 0x0B43, 0x0B4D, 0x0B4D, 0x0B56, 0x0B56, 0x0B82, 0x0B82,
0x0BC0, 0x0BC0, 0x0BCD, 0x0BCD, 0x0C3E, 0x0C40, 0x0C46, 0x0C48,
0x0C4A, 0x0C4D, 0x0C55, 0x0C56, 0x0CBC, 0x0CBC, 0x0CBF, 0x0CBF,
0x0CC6, 0x0CC6, 0x0CCC, 0x0CCD, 0x0CE2, 0x0CE3, 0x0D41, 0x0D43,
0x0D4D, 0x0D4D, 0x0DCA, 0x0DCA, 0x0DD2, 0x0DD4, 0x0DD6, 0x0DD6,
0x0E31, 0x0E31, 0x0E34, 0x0E3A, 0x0E47, 0x0E4E, 0x0EB1, 0x0EB1,
0x0EB4, 0x0EB9, 0x0EBB, 0x0EBC, 0x0EC8, 0x0ECD, 0x0F18, 0x0F19,
0x0F35, 0x0F35, 0x0F37, 0x0F37, 0x0F39, 0x0F39, 0x0F71, 0x0F7E,
0x0F80, 0x0F84, 0x0F86, 0x0F87, 0x0F90, 0x0F97, 0x0F99, 0x0FBC,
0x0FC6, 0x0FC6, 0x102D, 0x1030, 0x1032, 0x1032, 0x1036, 0x1037,
0x1039, 0x1039, 0x1058, 0x1059, 0x1160, 0x11FF, 0x135F, 0x135F,
0x1712, 0x1714, 0x1732, 0x1734, 0x1752, 0x1753, 0x1772, 0x1773,
0x17B4, 0x17B5, 0x17B7, 0x17BD, 0x17C6, 0x17C6, 0x17C9, 0x17D3,
0x17DD, 0x17DD, 0x180B, 0x180D, 0x18A9, 0x18A9, 0x1920, 0x1922,
0x1927, 0x1928, 0x1932, 0x1932, 0x1939, 0x193B, 0x1A17, 0x1A18,
0x1B00, 0x1B03, 0x1B34, 0x1B34, 0x1B36, 0x1B3A, 0x1B3C, 0x1B3C,
0x1B42, 0x1B42, 0x1B6B, 0x1B73, 0x1DC0, 0x1DCA, 0x1DFE, 0x1DFF,
0x200B, 0x200F, 0x202A, 0x202E, 0x2060, 0x2063, 0x206A, 0x206F,
0x20D0, 0x20EF, 0x302A, 0x302F, 0x3099, 0x309A, 0xA806, 0xA806,
0xA80B, 0xA80B, 0xA825, 0xA826, 0xFB1E, 0xFB1E, 0xFE00, 0xFE0F,
0xFE20, 0xFE23, 0xFEFF, 0xFEFF, 0xFFF9, 0xFFFB, 0x10A01, 0x10A03,
0x10A05, 0x10A06, 0x10A0C, 0x10A0F, 0x10A38, 0x10A3A, 0x10A3F, 0x10A3F,
0x1D167, 0x1D169, 0x1D173, 0x1D182, 0x1D185, 0x1D18B, 0x1D1AA, 0x1D1AD,
0x1D242, 0x1D244, 0xE0001, 0xE0001, 0xE0020, 0xE007F, 0xE0100, 0xE01EF,
-1,
};
_range_width2 := []rune{
0x1100, 0x115F, 0x2329, 0x2329, 0x232A, 0x232A, 0x2E80, 0x303E,
0x3040, 0xA4CF, 0xAC00, 0xD7A3, 0xF900, 0xFAFF, 0xFE10, 0xFE19,
0xFE30, 0xFE6F, 0xFF00, 0xFF60, 0xFFE0, 0xFFE6, 0x1F000, 0x1F644,
0x20000, 0x2FFFD, 0x30000, 0x3FFFD,
-1,
};
+216
View File
@@ -0,0 +1,216 @@
package container
import "core:mem"
import "core:runtime"
Array :: struct(T: typeid) {
data: ^T,
len: int,
cap: int,
allocator: mem.Allocator,
}
ARRAY_DEFAULT_CAPACITY :: 16;
/*
array_init :: proc {
array_init_none,
array_init_len,
array_init_len_cap,
}
array_init
array_delete
array_len
array_cap
array_space
array_slice
array_get
array_get_ptr
array_set
array_reserve
array_resize
array_push = array_append :: proc{
array_push_back,
array_push_back_elems,
}
array_push_front
array_pop_back
array_pop_front
array_consume
array_trim
array_clear
array_clone
array_set_capacity
array_grow
*/
array_init_none :: proc(a: ^$A/Array, allocator := context.allocator) {
array_init_len_cap(a, 0, ARRAY_DEFAULT_CAPACITY, allocator);
}
array_init_len :: proc(a: ^$A/Array, len: int, allocator := context.allocator) {
array_init_len_cap(a, len, len, allocator);
}
array_init_len_cap :: proc(a: ^$A/Array($T), len: int, cap: int, allocator := context.allocator) {
a.allocator = allocator;
a.data = (^T)(mem.alloc(size_of(T)*cap, align_of(T), a.allocator));
a.len = len;
a.cap = cap;
}
array_init :: proc{array_init_none, array_init_len, array_init_len_cap};
array_delete :: proc(a: $A/Array) {
mem.free(a.data, a.allocator);
}
array_len :: proc(a: $A/Array) -> int {
return a.len;
}
array_cap :: proc(a: $A/Array) -> int {
return a.cap;
}
array_space :: proc(a: $A/Array) -> int {
return a.cap - a.len;
}
array_slice :: proc(a: $A/Array($T)) -> []T {
s := mem.Raw_Slice{a.data, a.len};
return transmute([]T)s;
}
array_cap_slice :: proc(a: $A/Array($T)) -> []T {
s := mem.Raw_Slice{a.data, a.cap};
return transmute([]T)s;
}
array_get :: proc(a: $A/Array($T), index: int, loc := #caller_location) -> T {
runtime.bounds_check_error_loc(loc, index, array_len(a));
return (^T)(uintptr(a.data) + size_of(T)*uintptr(index))^;
}
array_get_ptr :: proc(a: $A/Array($T), index: int, loc := #caller_location) -> ^T {
runtime.bounds_check_error_loc(loc, index, array_len(a));
return (^T)(uintptr(a.data) + size_of(T)*uintptr(index));
}
array_set :: proc(a: ^$A/Array($T), index: int, item: T, loc := #caller_location) {
runtime.bounds_check_error_loc(loc, index, array_len(a^));
(^T)(uintptr(a.data) + size_of(T)*uintptr(index))^ = item;
}
array_reserve :: proc(a: ^$A/Array, capacity: int) {
if capacity > a.len {
array_set_capacity(a, capacity);
}
}
array_resize :: proc(a: ^$A/Array, length: int) {
if length > a.len {
array_set_capacity(a, length);
}
a.len = length;
}
array_push_back :: proc(a: ^$A/Array($T), item: T) {
if array_space(a^) == 0 {
array_grow(a);
}
a.len += 1;
array_set(a, a.len-1, item);
}
array_push_front :: proc(a: ^$A/Array($T), item: T) {
if array_space(a^) == 0 {
array_grow(a);
}
a.len += 1;
data := array_slice(a^);
copy(data[1:], data[:]);
data[0] = item;
}
array_pop_back :: proc(a: ^$A/Array($T), loc := #caller_location) -> T {
assert(condition=a.len > 0, loc=loc);
item := array_get(a^, a.len-1);
a.len -= 1;
return item;
}
array_pop_front :: proc(a: ^$A/Array($T), loc := #caller_location) -> T {
assert(condition=a.len > 0, loc=loc);
item := array_get(a^, 0);
s := array_slice(a^);
copy(s[:], s[1:]);
a.len -= 1;
return item;
}
array_consume :: proc(a: ^$A/Array($T), count: int, loc := #caller_location) {
assert(condition=a.len >= count, loc=loc);
a.len -= count;
}
array_trim :: proc(a: ^$A/Array($T)) {
array_set_capacity(a, a.len);
}
array_clear :: proc(a: ^$A/Array($T)) {
array_resize(a, 0);
}
array_clone :: proc(a: $A/Array($T), allocator := context.allocator) -> A {
res: A;
array_init(&res, array_len(a), array_len(a), allocator);
copy(array_slice(res), array_slice(a));
return res;
}
array_push_back_elems :: proc(a: ^$A/Array($T), items: ..T) {
if array_space(a^) < len(items) {
array_grow(a, a.len + len(items));
}
offset := a.len;
data := array_cap_slice(a^);
n := copy(data[a.len:], items);
a.len += n;
}
array_push :: proc{array_push_back, array_push_back_elems};
array_append :: proc{array_push_back, array_push_back_elems};
array_set_capacity :: proc(a: ^$A/Array($T), new_capacity: int) {
if new_capacity == a.cap {
return;
}
if new_capacity < a.len {
array_resize(a, new_capacity);
}
new_data: ^T;
if new_capacity > 0 {
if a.allocator.procedure == nil {
a.allocator = context.allocator;
}
new_data = (^T)(mem.alloc(size_of(T)*new_capacity, align_of(T), a.allocator));
if new_data != nil {
mem.copy(new_data, a.data, size_of(T)*a.len);
}
}
mem.free(a.data, a.allocator);
a.data = new_data;
a.cap = new_capacity;
}
array_grow :: proc(a: ^$A/Array, min_capacity: int = 0) {
new_capacity := max(array_len(a^)*2 + 8, min_capacity);
array_set_capacity(a, new_capacity);
}
+80
View File
@@ -0,0 +1,80 @@
package container
import "core:mem"
Bloom_Hash_Proc :: #type proc(data: []byte) -> u32;
Bloom_Hash :: struct {
hash_proc: Bloom_Hash_Proc,
next: ^Bloom_Hash,
}
Bloom_Filter :: struct {
allocator: mem.Allocator,
hash: ^Bloom_Hash,
bits: []byte,
}
bloom_filter_init :: proc(b: ^Bloom_Filter, size: int, allocator := context.allocator) {
b.allocator = allocator;
b.bits = make([]byte, size, allocator);
}
bloom_filter_destroy :: proc(b: ^Bloom_Filter) {
context.allocator = b.allocator;
delete(b.bits);
for b.hash != nil {
hash := b.hash;
b.hash = b.hash.next;
free(hash);
}
}
bloom_filter_add_hash_proc :: proc(b: ^Bloom_Filter, hash_proc: Bloom_Hash_Proc) {
context.allocator = b.allocator;
h := new(Bloom_Hash);
h.hash_proc = hash_proc;
head := &b.hash;
for head^ != nil {
head = &(head^.next);
}
head^ = h;
}
bloom_filter_add :: proc(b: ^Bloom_Filter, item: []byte) {
#no_bounds_check for h := b.hash; h != nil; h = h.next {
hash := h.hash_proc(item);
hash %= u32(len(b.bits) * 8);
b.bits[hash >> 3] |= 1 << (hash & 3);
}
}
bloom_filter_add_string :: proc(b: ^Bloom_Filter, item: string) {
bloom_filter_add(b, transmute([]byte)item);
}
bloom_filter_add_raw :: proc(b: ^Bloom_Filter, data: rawptr, size: int) {
item := mem.slice_ptr((^byte)(data), size);
bloom_filter_add(b, item);
}
bloom_filter_test :: proc(b: ^Bloom_Filter, item: []byte) -> bool {
#no_bounds_check for h := b.hash; h != nil; h = h.next {
hash := h.hash_proc(item);
hash %= u32(len(b.bits) * 8);
if (b.bits[hash >> 3] & (1 << (hash & 3)) == 0) {
return false;
}
}
return true;
}
bloom_filter_test_string :: proc(b: ^Bloom_Filter, item: string) -> bool {
return bloom_filter_test(b, transmute([]byte)item);
}
bloom_filter_test_raw :: proc(b: ^Bloom_Filter, data: rawptr, size: int) -> bool {
item := mem.slice_ptr((^byte)(data), size);
return bloom_filter_test(b, item);
}
+377
View File
@@ -0,0 +1,377 @@
package container
import "intrinsics"
_ :: intrinsics;
Map :: struct(Key, Value: typeid) where intrinsics.type_is_valid_map_key(Key) {
hash: Array(int),
entries: Array(Map_Entry(Key, Value)),
}
Map_Entry :: struct(Key, Value: typeid) where intrinsics.type_is_valid_map_key(Key) {
hash: uintptr,
next: int,
key: Key,
value: Value,
}
/*
map_init :: proc{
map_init_none,
map_init_cap,
}
map_delete
map_has
map_get
map_get_default
map_get_ptr
map_set
map_remove
map_reserve
map_clear
// Multi Map
multi_map_find_first
multi_map_find_next
multi_map_count
multi_map_get :: proc{
multi_map_get_array,
multi_map_get_slice,
};
multi_map_get_as_slice
multi_map_insert
multi_map_remove
multi_map_remove_all
*/
map_init :: proc{map_init_none, map_init_cap};
map_init_none :: proc(m: ^$M/Map($Key, $Value), allocator := context.allocator) {
m.hash.allocator = allocator;
m.entries.allocator = allocator;
}
map_init_cap :: proc(m: ^$M/Map($Key, $Value), cap: int, allocator := context.allocator) {
m.hash.allocator = allocator;
m.entries.allocator = allocator;
map_reserve(m, cap);
}
map_delete :: proc(m: $M/Map($Key, $Value)) {
array_delete(m.hash);
array_delete(m.entries);
}
map_has :: proc(m: $M/Map($Key, $Value), key: Key) -> bool {
return _map_find_or_fail(m, key) >= 0;
}
map_get :: proc(m: $M/Map($Key, $Value), key: Key) -> (res: Value, ok: bool) #optional_ok {
i := _map_find_or_fail(m, key);
if i < 0 {
return {}, false;
}
return array_get(m.entries, i).value, true;
}
map_get_default :: proc(m: $M/Map($Key, $Value), key: Key, default: Value) -> (res: Value, ok: bool) #optional_ok {
i := _map_find_or_fail(m, key);
if i < 0 {
return default, false;
}
return array_get(m.entries, i).value, true;
}
map_get_ptr :: proc(m: $M/Map($Key, $Value), key: Key) -> ^Value {
i := _map_find_or_fail(m, key);
if i < 0 {
return nil;
}
return array_get_ptr(m.entries, i).value;
}
map_set :: proc(m: ^$M/Map($Key, $Value), key: Key, value: Value) {
if array_len(m.hash) == 0 {
_map_grow(m);
}
i := _map_find_or_make(m, key);
array_get_ptr(m.entries, i).value = value;
if _map_full(m^) {
_map_grow(m);
}
}
map_remove :: proc(m: ^$M/Map($Key, $Value), key: Key) {
fr := _map_find_key(m^, key);
if fr.entry_index >= 0 {
_map_erase(m, fr);
}
}
map_reserve :: proc(m: ^$M/Map($Key, $Value), new_size: int) {
nm: M;
map_init(&nm, m.hash.allocator);
array_resize(&nm.hash, new_size);
array_reserve(&nm.entries, array_len(m.entries));
for i in 0..<new_size {
array_set(&nm.hash, i, -1);
}
for i in 0..<array_len(m.entries) {
e := array_get(m.entries, i);
multi_map_insert(&nm, e.key, e.value);
}
map_delete(m^);
m^ = nm;
}
map_clear :: proc(m: ^$M/Map($Key, $Value)) {
array_clear(&m.hash);
array_clear(&m.entries);
}
multi_map_find_first :: proc(m: $M/Map($Key, $Value), key: Key) -> ^Map_Entry(Value) {
i := _map_find_or_fail(m, key);
if i < 0 {
return nil;
}
return array_get_ptr(m.entries, i);
}
multi_map_find_next :: proc(m: $M/Map($Key, $Value), e: ^Map_Entry(Value)) -> ^Map_Entry(Value) {
i := e.next;
for i >= 0 {
it := array_get_ptr(m.entries, i);
if it.hash == e.hash && it.key == e.key {
return it;
}
i = it.next;
}
return nil;
}
multi_map_count :: proc(m: $M/Map($Key, $Value), key: Key) -> int {
n := 0;
e := multi_map_find_first(m, key);
for e != nil {
n += 1;
e = multi_map_find_next(m, e);
}
return n;
}
multi_map_get :: proc{multi_map_get_array, multi_map_get_slice};
multi_map_get_array :: proc(m: $M/Map($Key, $Value), key: Key, items: ^Array(Value)) {
if items == nil {
return;
}
e := multi_map_find_first(m, key);
for e != nil {
array_append(items, e.value);
e = multi_map_find_next(m, e);
}
}
multi_map_get_slice :: proc(m: $M/Map($Key, $Value), key: Key, items: []Value) {
e := multi_map_find_first(m, key);
i := 0;
for e != nil && i < len(items) {
items[i] = e.value;
i += 1;
e = multi_map_find_next(m, e);
}
}
multi_map_get_as_slice :: proc(m: $M/Map($Key, $Value), key: Key) -> []Value {
items: Array(Value);
array_init(&items, 0);
e := multi_map_find_first(m, key);
for e != nil {
array_append(&items, e.value);
e = multi_map_find_next(m, e);
}
return array_slice(items);
}
multi_map_insert :: proc(m: ^$M/Map($Key, $Value), key: Key, value: Value) {
if array_len(m.hash) == 0 {
_map_grow(m);
}
i := _map_make(m, key);
array_get_ptr(m.entries, i).value = value;
if _map_full(m^) {
_map_grow(m);
}
}
multi_map_remove :: proc(m: ^$M/Map($Key, $Value), e: ^Map_Entry(Value)) {
fr := _map_find_entry(m, e);
if fr.entry_index >= 0 {
_map_erase(m, fr);
}
}
multi_map_remove_all :: proc(m: ^$M/Map($Key, $Value), key: Key) {
for map_exist(m^, key) {
map_remove(m, key);
}
}
/// Internal
Map_Find_Result :: struct {
hash_index: int,
entry_prev: int,
entry_index: int,
}
_map_add_entry :: proc(m: ^$M/Map($Key, $Value), key: Key) -> int where intrinsics.type_is_valid_map_key(Key) {
hasher := intrinsics.type_hasher_proc(Key);
e: Map_Entry(Key, Value);
e.key = key;
e.hash = hasher(&e.key, 0);
e.next = -1;
idx := array_len(m.entries);
array_push(&m.entries, e);
return idx;
}
_map_erase :: proc(m: ^$M/Map, fr: Map_Find_Result) {
if fr.entry_prev < 0 {
array_set(&m.hash, fr.hash_index, array_get(m.entries, fr.entry_index).next);
} else {
array_get_ptr(m.entries, fr.entry_prev).next = array_get(m.entries, fr.entry_index).next;
}
if fr.entry_index == array_len(m.entries)-1 {
array_pop_back(&m.entries);
return;
}
array_set(&m.entries, fr.entry_index, array_get(m.entries, array_len(m.entries)-1));
last := _map_find_key(m^, array_get(m.entries, fr.entry_index).key);
if last.entry_prev < 0 {
array_get_ptr(m.entries, last.entry_prev).next = fr.entry_index;
} else {
array_set(&m.hash, last.hash_index, fr.entry_index);
}
}
_map_find_key :: proc(m: $M/Map($Key, $Value), key: Key) -> Map_Find_Result where intrinsics.type_is_valid_map_key(Key) {
fr: Map_Find_Result;
fr.hash_index = -1;
fr.entry_prev = -1;
fr.entry_index = -1;
if array_len(m.hash) == 0 {
return fr;
}
hasher := intrinsics.type_hasher_proc(Key);
key := key;
hash := hasher(&key, 0);
fr.hash_index = int(hash % uintptr(array_len(m.hash)));
fr.entry_index = array_get(m.hash, fr.hash_index);
for fr.entry_index >= 0 {
it := array_get_ptr(m.entries, fr.entry_index);
if it.hash == hash && it.key == key {
return fr;
}
fr.entry_prev = fr.entry_index;
fr.entry_index = it.next;
}
return fr;
}
_map_find_entry :: proc(m: ^$M/Map($Key, $Value), e: ^Map_Entry(Value)) -> Map_Find_Result {
fr: Map_Find_Result;
fr.hash_index = -1;
fr.entry_prev = -1;
fr.entry_index = -1;
if array_len(m.hash) == 0 {
return fr;
}
fr.hash_index = int(e.hash % uintptr(array_len(m.hash)));
fr.entry_index = array_get(m.hash, fr.hash_index);
for fr.entry_index >= 0 {
it := array_get_ptr(m.entries, fr.entry_index);
if it == e {
return fr;
}
fr.entry_prev = fr.entry_index;
fr.entry_index = it.next;
}
return fr;
}
_map_find_or_fail :: proc(m: $M/Map($Key, $Value), key: Key) -> int {
return _map_find_key(m, key).entry_index;
}
_map_find_or_make :: proc(m: ^$M/Map($Key, $Value), key: Key) -> int {
fr := _map_find_key(m^, key);
if fr.entry_index >= 0 {
return fr.entry_index;
}
i := _map_add_entry(m, key);
if fr.entry_prev < 0 {
array_set(&m.hash, fr.hash_index, i);
} else {
array_get_ptr(m.entries, fr.entry_prev).next = i;
}
return i;
}
_map_make :: proc(m: ^$M/Map($Key, $Value), key: Key) -> int {
fr := _map_find_key(m^, key);
i := _map_add_entry(m, key);
if fr.entry_prev < 0 {
array_set(&m.hash, fr.hash_index, i);
} else {
array_get_ptr(m.entries, fr.entry_prev).next = i;
}
array_get_ptr(m.entries, i).next = fr.entry_index;
return i;
}
_map_full :: proc(m: $M/Map($Key, $Value)) -> bool {
// TODO(bill): Determine good max load factor
return array_len(m.entries) >= (array_len(m.hash) / 4)*3;
}
_map_grow :: proc(m: ^$M/Map($Key, $Value)) {
new_size := array_len(m.entries) * 4 + 7; // TODO(bill): Determine good grow rate
map_reserve(m, new_size);
}
+113
View File
@@ -0,0 +1,113 @@
package container
Priority_Queue :: struct(T: typeid) {
data: Array(T),
len: int,
priority: proc(item: T) -> int,
}
priority_queue_init_none :: proc(q: ^$Q/Priority_Queue($T), f: proc(item: T) -> int, allocator := context.allocator) {
queue_init_len(q, f, 0, allocator);
}
priority_queue_init_len :: proc(q: ^$Q/Priority_Queue($T), f: proc(item: T) -> int, len: int, allocator := context.allocator) {
queue_init_len_cap(q, f, 0, 16, allocator);
}
priority_queue_init_len_cap :: proc(q: ^$Q/Priority_Queue($T), f: proc(item: T) -> int, len: int, cap: int, allocator := context.allocator) {
array_init(&q.data, len, cap, allocator);
q.len = len;
q.priority = f;
}
priority_queue_init :: proc{priority_queue_init_none, priority_queue_init_len, priority_queue_init_len_cap};
priority_queue_delete :: proc(q: $Q/Priority_Queue($T)) {
array_delete(q.data);
}
priority_queue_clear :: proc(q: ^$Q/Priority_Queue($T)) {
q.len = 0;
}
priority_queue_len :: proc(q: $Q/Priority_Queue($T)) -> int {
return q.len;
}
priority_queue_cap :: proc(q: $Q/Priority_Queue($T)) -> int {
return array_cap(q.data);
}
priority_queue_space :: proc(q: $Q/Priority_Queue($T)) -> int {
return array_len(q.data) - q.len;
}
priority_queue_reserve :: proc(q: ^$Q/Priority_Queue($T), capacity: int) {
if capacity > q.len {
array_resize(&q.data, new_capacity);
}
}
priority_queue_resize :: proc(q: ^$Q/Priority_Queue($T), length: int) {
if length > q.len {
array_resize(&q.data, new_capacity);
}
q.len = length;
}
_priority_queue_grow :: proc(q: ^$Q/Priority_Queue($T), min_capacity: int = 0) {
new_capacity := max(array_len(q.data)*2 + 8, min_capacity);
array_resize(&q.data, new_capacity);
}
priority_queue_push :: proc(q: ^$Q/Priority_Queue($T), item: T) {
if array_len(q.data) - q.len == 0 {
_priority_queue_grow(q);
}
s := array_slice(q.data);
s[q.len] = item;
i := q.len;
for i > 0 {
p := (i - 1) / 2;
if q.priority(s[p]) <= q.priority(item) do break;
s[i] = s[p];
i = p;
}
q.len += 1;
if q.len > 0 do s[i] = item;
}
priority_queue_pop :: proc(q: ^$Q/Priority_Queue($T)) -> T {
assert(q.len > 0);
s := array_slice(q.data);
min := s[0];
root := s[q.len-1];
q.len -= 1;
i := 0;
for i * 2 + 1 < q.len {
a := i * 2 + 1;
b := i * 2 + 2;
c := b < q.len && q.priority(s[b]) < q.priority(s[a]) ? b : a;
if q.priority(s[c]) >= q.priority(root) do break;
s[i] = s[c];
i = c;
}
if q.len > 0 do s[i] = root;
return min;
}
priority_queue_peek :: proc(q: ^$Q/Priority_Queue($T)) -> T {
assert(q.len > 0);
s := array_slice(q.data);
return s[0];
}
+175
View File
@@ -0,0 +1,175 @@
package container
Queue :: struct(T: typeid) {
data: Array(T),
len: int,
offset: int,
}
/*
queue_init :: proc{
queue_init_none,
queue_init_len,
queue_init_len_cap,
}
queue_delete
queue_clear
queue_len
queue_cap
queue_space
queue_get
queue_set
queue_reserve
queue_resize
queue_push :: proc{
queue_push_back,
queue_push_elems,
};
queue_push_front
queue_pop_front
queue_pop_back
queue_consume
*/
queue_init_none :: proc(q: ^$Q/Queue($T), allocator := context.allocator) {
queue_init_len(q, 0, allocator);
}
queue_init_len :: proc(q: ^$Q/Queue($T), len: int, allocator := context.allocator) {
queue_init_len_cap(q, 0, 16, allocator);
}
queue_init_len_cap :: proc(q: ^$Q/Queue($T), len: int, cap: int, allocator := context.allocator) {
array_init(&q.data, len, cap, allocator);
q.len = len;
q.offset = 0;
}
queue_init :: proc{queue_init_none, queue_init_len, queue_init_len_cap};
queue_delete :: proc(q: $Q/Queue($T)) {
array_delete(q.data);
}
queue_clear :: proc(q: ^$Q/Queue($T)) {
q.len = 0;
}
queue_len :: proc(q: $Q/Queue($T)) -> int {
return q.len;
}
queue_cap :: proc(q: $Q/Queue($T)) -> int {
return array_cap(q.data);
}
queue_space :: proc(q: $Q/Queue($T)) -> int {
return array_len(q.data) - q.len;
}
queue_get :: proc(q: $Q/Queue($T), index: int) -> T {
i := (index + q.offset) % array_len(q.data);
data := array_slice(q.data);
return data[i];
}
queue_set :: proc(q: ^$Q/Queue($T), index: int, item: T) {
i := (index + q.offset) % array_len(q.data);
data := array_slice(q.data);
data[i] = item;
}
queue_reserve :: proc(q: ^$Q/Queue($T), capacity: int) {
if capacity > q.len {
_queue_increase_capacity(q, capacity);
}
}
queue_resize :: proc(q: ^$Q/Queue($T), length: int) {
if length > q.len {
_queue_increase_capacity(q, length);
}
q.len = length;
}
queue_push_back :: proc(q: ^$Q/Queue($T), item: T) {
if queue_space(q^) == 0 {
_queue_grow(q);
}
queue_set(q, q.len, item);
q.len += 1;
}
queue_push_front :: proc(q: ^$Q/Queue($T), item: T) {
if queue_space(q^) == 0 {
_queue_grow(q);
}
q.offset = (q.offset - 1 + array_len(q.data)) % array_len(q.data);
q.len += 1;
queue_set(q, 0, item);
}
queue_pop_front :: proc(q: ^$Q/Queue($T)) -> T {
assert(q.len > 0);
item := queue_get(q^, 0);
q.offset = (q.offset + 1) % array_len(q.data);
q.len -= 1;
if q.len == 0 {
q.offset = 0;
}
return item;
}
queue_pop_back :: proc(q: ^$Q/Queue($T)) -> T {
assert(q.len > 0);
item := queue_get(q^, q.len-1);
q.len -= 1;
return item;
}
queue_consume :: proc(q: ^$Q/Queue($T), count: int) {
q.offset = (q.offset + count) & array_len(q.data);
q.len -= count;
}
queue_push_elems :: proc(q: ^$Q/Queue($T), items: ..T) {
if queue_space(q^) < len(items) {
_queue_grow(q, q.len + len(items));
}
size := array_len(q.data);
insert := (q.offset + q.len) % size;
to_insert := len(items);
if insert + to_insert > size {
to_insert = size - insert;
}
the_items := items[:];
data := array_slice(q.data);
q.len += copy(data[insert:][:to_insert], the_items);
the_items = the_items[to_insert:];
q.len += copy(data[:], the_items);
}
queue_push :: proc{queue_push_back, queue_push_elems};
_queue_increase_capacity :: proc(q: ^$Q/Queue($T), new_capacity: int) {
end := array_len(q.data);
array_resize(&q.data, new_capacity);
if q.offset + q.len > end {
end_items := q.len + end;
data := array_slice(q.data);
copy(data[new_capacity-end_items:][:end_items], data[q.offset:][:end_items]);
q.offset += new_capacity - end;
}
}
_queue_grow :: proc(q: ^$Q/Queue($T), min_capacity: int = 0) {
new_capacity := max(array_len(q.data)*2 + 8, min_capacity);
_queue_increase_capacity(q, new_capacity);
}
+73
View File
@@ -0,0 +1,73 @@
package container
Ring :: struct(T: typeid) {
next, prev: ^Ring(T),
value: T,
}
ring_init :: proc(r: ^$R/Ring) -> ^R {
r.prev, r.next = r, r;
return r;
}
ring_next :: proc(r: ^$R/Ring) -> ^R {
if r.next == nil {
return ring_init(r);
}
return r.next;
}
ring_prev :: proc(r: ^$R/Ring) -> ^R {
if r.prev == nil {
return ring_init(r);
}
return r.prev;
}
ring_move :: proc(r: ^$R/Ring, n: int) -> ^R {
if r.next == nil {
return ring_init(r);
}
switch {
case n < 0:
for _ in n..<0 {
r = r.prev;
}
case n > 0:
for _ in 0..<n {
r = r.next;
}
}
return r;
}
ring_link :: proc(r, s: ^$R/Ring) -> ^R {
n := ring_next(r);
if s != nil {
p := ring_prev(s);
r.next = s;
s.prev = r;
n.prev = p;
p.next = n;
}
return n;
}
ring_unlink :: proc(r: ^$R/Ring, n: int) -> ^R {
if n <= 0 {
return nil;
}
return ring_link(r, ring_move(r, n+1));
}
ring_len :: proc(r: ^$R/Ring) -> int {
n := 0;
if r != nil {
n = 1;
for p := ring_next(&p); p != r; p = p.next {
n += 1;
}
}
return n;
}
+240
View File
@@ -0,0 +1,240 @@
package container
Set :: struct {
hash: Array(int),
entries: Array(Set_Entry),
}
Set_Entry :: struct {
key: u64,
next: int,
}
/*
set_init :: proc{
set_init_none,
set_init_cap,
}
set_delete
set_in
set_not_in
set_add
set_remove
set_reserve
set_clear
*/
set_init :: proc{set_init_none, set_init_cap};
set_init_none :: proc(m: ^Set, allocator := context.allocator) {
m.hash.allocator = allocator;
m.entries.allocator = allocator;
}
set_init_cap :: proc(m: ^Set, cap: int, allocator := context.allocator) {
m.hash.allocator = allocator;
m.entries.allocator = allocator;
set_reserve(m, cap);
}
set_delete :: proc(m: Set) {
array_delete(m.hash);
array_delete(m.entries);
}
set_in :: proc(m: Set, key: u64) -> bool {
return _set_find_or_fail(m, key) >= 0;
}
set_not_in :: proc(m: Set, key: u64) -> bool {
return _set_find_or_fail(m, key) < 0;
}
set_add :: proc(m: ^Set, key: u64) {
if array_len(m.hash) == 0 {
_set_grow(m);
}
_ = _set_find_or_make(m, key);
if _set_full(m^) {
_set_grow(m);
}
}
set_remove :: proc(m: ^Set, key: u64) {
fr := _set_find_key(m^, key);
if fr.entry_index >= 0 {
_set_erase(m, fr);
}
}
set_reserve :: proc(m: ^Set, new_size: int) {
nm: Set;
set_init(&nm, m.hash.allocator);
array_resize(&nm.hash, new_size);
array_reserve(&nm.entries, array_len(m.entries));
for i in 0..<new_size {
array_set(&nm.hash, i, -1);
}
for i in 0..<array_len(m.entries) {
e := array_get(m.entries, i);
set_add(&nm, e.key);
}
set_delete(m^);
m^ = nm;
}
set_clear :: proc(m: ^Set) {
array_clear(&m.hash);
array_clear(&m.entries);
}
set_equal :: proc(a, b: Set) -> bool {
a_entries := array_slice(a.entries);
b_entries := array_slice(b.entries);
if len(a_entries) != len(b_entries) {
return false;
}
for e in a_entries {
if set_not_in(b, e.key) {
return false;
}
}
return true;
}
/// Internal
_set_add_entry :: proc(m: ^Set, key: u64) -> int {
e: Set_Entry;
e.key = key;
e.next = -1;
idx := array_len(m.entries);
array_push(&m.entries, e);
return idx;
}
_set_erase :: proc(m: ^Set, fr: Map_Find_Result) {
if fr.entry_prev < 0 {
array_set(&m.hash, fr.hash_index, array_get(m.entries, fr.entry_index).next);
} else {
array_get_ptr(m.entries, fr.entry_prev).next = array_get(m.entries, fr.entry_index).next;
}
if fr.entry_index == array_len(m.entries)-1 {
array_pop_back(&m.entries);
return;
}
array_set(&m.entries, fr.entry_index, array_get(m.entries, array_len(m.entries)-1));
last := _set_find_key(m^, array_get(m.entries, fr.entry_index).key);
if last.entry_prev < 0 {
array_get_ptr(m.entries, last.entry_prev).next = fr.entry_index;
} else {
array_set(&m.hash, last.hash_index, fr.entry_index);
}
}
_set_find_key :: proc(m: Set, key: u64) -> Map_Find_Result {
fr: Map_Find_Result;
fr.hash_index = -1;
fr.entry_prev = -1;
fr.entry_index = -1;
if array_len(m.hash) == 0 {
return fr;
}
fr.hash_index = int(key % u64(array_len(m.hash)));
fr.entry_index = array_get(m.hash, fr.hash_index);
for fr.entry_index >= 0 {
it := array_get_ptr(m.entries, fr.entry_index);
if it.key == key {
return fr;
}
fr.entry_prev = fr.entry_index;
fr.entry_index = it.next;
}
return fr;
}
_set_find_entry :: proc(m: ^Set, e: ^Set_Entry) -> Map_Find_Result {
fr: Map_Find_Result;
fr.hash_index = -1;
fr.entry_prev = -1;
fr.entry_index = -1;
if array_len(m.hash) == 0 {
return fr;
}
fr.hash_index = int(e.key % u64(array_len(m.hash)));
fr.entry_index = array_get(m.hash, fr.hash_index);
for fr.entry_index >= 0 {
it := array_get_ptr(m.entries, fr.entry_index);
if it == e {
return fr;
}
fr.entry_prev = fr.entry_index;
fr.entry_index = it.next;
}
return fr;
}
_set_find_or_fail :: proc(m: Set, key: u64) -> int {
return _set_find_key(m, key).entry_index;
}
_set_find_or_make :: proc(m: ^Set, key: u64) -> int {
fr := _set_find_key(m^, key);
if fr.entry_index >= 0 {
return fr.entry_index;
}
i := _set_add_entry(m, key);
if fr.entry_prev < 0 {
array_set(&m.hash, fr.hash_index, i);
} else {
array_get_ptr(m.entries, fr.entry_prev).next = i;
}
return i;
}
_set_make :: proc(m: ^Set, key: u64) -> int {
fr := _set_find_key(m^, key);
i := _set_add_entry(m, key);
if fr.entry_prev < 0 {
array_set(&m.hash, fr.hash_index, i);
} else {
array_get_ptr(m.entries, fr.entry_prev).next = i;
}
array_get_ptr(m.entries, i).next = fr.entry_index;
return i;
}
_set_full :: proc(m: Set) -> bool {
// TODO(bill): Determine good max load factor
return array_len(m.entries) >= (array_len(m.hash) / 4)*3;
}
_set_grow :: proc(m: ^Set) {
new_size := array_len(m.entries) * 4 + 7; // TODO(bill): Determine good grow rate
set_reserve(m, new_size);
}
+95
View File
@@ -0,0 +1,95 @@
package container
Small_Array :: struct(N: int, T: typeid) where N >= 0 {
data: [N]T,
len: int,
}
small_array_len :: proc(a: $A/Small_Array) -> int {
return a.len;
}
small_array_cap :: proc(a: $A/Small_Array) -> int {
return len(a.data);
}
small_array_space :: proc(a: $A/Small_Array) -> int {
return len(a.data) - a.len;
}
small_array_slice :: proc(a: ^$A/Small_Array($N, $T)) -> []T {
return a.data[:a.len];
}
small_array_get :: proc(a: $A/Small_Array($N, $T), index: int, loc := #caller_location) -> T {
return a.data[index];
}
small_array_get_ptr :: proc(a: $A/Small_Array($N, $T), index: int, loc := #caller_location) -> ^T {
return &a.data[index];
}
small_array_set :: proc(a: ^$A/Small_Array($N, $T), index: int, item: T, loc := #caller_location) {
a.data[index] = item;
}
small_array_resize :: proc(a: ^$A/Small_Array, length: int) {
a.len = min(length, len(a.data));
}
small_array_push_back :: proc(a: ^$A/Small_Array($N, $T), item: T) -> bool {
if a.len < len(a.data) {
a.len += 1;
a.data[a.len-1] = item;
return true;
}
return false;
}
small_array_push_front :: proc(a: ^$A/Small_Array($N, $T), item: T) -> bool {
if a.len < len(a.data) {
a.len += 1;
data := small_array_slice(a);
copy(data[1:], data[:]);
data[0] = item;
return true;
}
return false;
}
small_array_pop_back :: proc(a: ^$A/Small_Array($N, $T), loc := #caller_location) -> T {
assert(condition=a.len > 0, loc=loc);
item := a.data[a.len-1];
a.len -= 1;
return item;
}
small_array_pop_front :: proc(a: ^$A/Small_Array($N, $T), loc := #caller_location) -> T {
assert(condition=a.len > 0, loc=loc);
item := a.data[0];
s := small_array_slice(a);
copy(s[:], s[1:]);
a.len -= 1;
return item;
}
small_array_consume :: proc(a: ^$A/Small_Array($N, $T), count: int, loc := #caller_location) {
assert(condition=a.len >= count, loc=loc);
a.len -= count;
}
small_array_clear :: proc(a: ^$A/Small_Array($N, $T)) {
small_array_resize(a, 0);
}
small_array_push_back_elems :: proc(a: ^$A/Small_Array($N, $T), items: ..T) {
n := copy(a.data[a.len:], items[:]);
a.len += n;
}
small_array_push :: proc{small_array_push_back, small_array_push_back_elems};
small_array_append :: proc{small_array_push_back, small_array_push_back_elems};
+3
View File
@@ -0,0 +1,3 @@
package dynlib
Library :: distinct rawptr;
+23
View File
@@ -0,0 +1,23 @@
// +build linux, darwin, freebsd
package dynlib
import "core:os"
load_library :: proc(path: string, global_symbols := false) -> (Library, bool) {
flags := os.RTLD_NOW;
if global_symbols {
flags |= os.RTLD_GLOBAL;
}
lib := os.dlopen(path, flags);
return Library(lib), lib != nil;
}
unload_library :: proc(library: Library) {
os.dlclose(rawptr(library));
}
symbol_address :: proc(library: Library, symbol: string) -> (ptr: rawptr, found: bool) {
ptr = os.dlsym(rawptr(library), symbol);
found = ptr != nil;
return;
}
+25
View File
@@ -0,0 +1,25 @@
// +build windows
package dynlib
import win32 "core:sys/windows"
import "core:strings"
load_library :: proc(path: string, global_symbols := false) -> (Library, bool) {
// NOTE(bill): 'global_symbols' is here only for consistency with POSIX which has RTLD_GLOBAL
wide_path := win32.utf8_to_wstring(path, context.temp_allocator);
handle := cast(Library)win32.LoadLibraryW(wide_path);
return handle, handle != nil;
}
unload_library :: proc(library: Library) -> bool {
ok := win32.FreeLibrary(cast(win32.HMODULE)library);
return bool(ok);
}
symbol_address :: proc(library: Library, symbol: string) -> (ptr: rawptr, found: bool) {
c_str := strings.clone_to_cstring(symbol, context.temp_allocator);
ptr = win32.GetProcAddress(cast(win32.HMODULE)library, c_str);
found = ptr != nil;
return;
}
+148
View File
@@ -0,0 +1,148 @@
package base32
// @note(zh): Encoding utility for Base32
// A secondary param can be used to supply a custom alphabet to
// @link(encode) and a matching decoding table to @link(decode).
// If none is supplied it just uses the standard Base32 alphabet.
// Incase your specific version does not use padding, you may
// truncate it from the encoded output.
ENC_TABLE := [32]byte {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', '2', '3', '4', '5', '6', '7',
};
PADDING :: '=';
DEC_TABLE := [?]u8 {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 26, 27, 28, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
encode :: proc(data: []byte, ENC_TBL := ENC_TABLE, allocator := context.allocator) -> string {
out_length := (len(data) + 4) / 5 * 8;
out := make([]byte, out_length);
_encode(out, data);
return string(out);
}
@private
_encode :: proc(out, data: []byte, ENC_TBL := ENC_TABLE, allocator := context.allocator) {
out := out;
data := data;
for len(data) > 0 {
carry: byte;
switch len(data) {
case:
out[7] = ENC_TABLE[data[4] & 0x1f];
carry = data[4] >> 5;
fallthrough;
case 4:
out[6] = ENC_TABLE[carry | (data[3] << 3) & 0x1f];
out[5] = ENC_TABLE[(data[3] >> 2) & 0x1f];
carry = data[3] >> 7;
fallthrough;
case 3:
out[4] = ENC_TABLE[carry | (data[2] << 1) & 0x1f];
carry = (data[2] >> 4) & 0x1f;
fallthrough;
case 2:
out[3] = ENC_TABLE[carry | (data[1] << 4) & 0x1f];
out[2] = ENC_TABLE[(data[1] >> 1) & 0x1f];
carry = (data[1] >> 6) & 0x1f;
fallthrough;
case 1:
out[1] = ENC_TABLE[carry | (data[0] << 2) & 0x1f];
out[0] = ENC_TABLE[data[0] >> 3];
}
if len(data) < 5 {
out[7] = byte(PADDING);
if len(data) < 4 {
out[6] = byte(PADDING);
out[5] = byte(PADDING);
if len(data) < 3 {
out[4] = byte(PADDING);
if len(data) < 2 {
out[3] = byte(PADDING);
out[2] = byte(PADDING);
}
}
}
break;
}
data = data[5:];
out = out[8:];
}
}
decode :: proc(data: string, DEC_TBL := DEC_TABLE, allocator := context.allocator) -> []byte #no_bounds_check{
if len(data) == 0 {
return nil;
}
outi := 0;
data := data;
out := make([]byte, len(data) / 8 * 5, allocator);
end := false;
for len(data) > 0 && !end {
dbuf : [8]byte;
dlen := 8;
for j := 0; j < 8; {
if len(data) == 0 {
dlen, end = j, true;
break;
}
input := data[0];
data = data[1:];
if input == byte(PADDING) && j >= 2 && len(data) < 8 {
assert(!(len(data) + j < 8 - 1), "Corrupted input");
for k := 0; k < 8-1-j; k +=1 {
assert(len(data) < k || data[k] == byte(PADDING), "Corrupted input");
}
dlen, end = j, true;
assert(dlen != 1 && dlen != 3 && dlen != 6, "Corrupted input");
break;
}
dbuf[j] = DEC_TABLE[input];
assert(dbuf[j] != 0xff, "Corrupted input");
j += 1;
}
switch dlen {
case 8:
out[outi + 4] = dbuf[6] << 5 | dbuf[7];
fallthrough;
case 7:
out[outi + 3] = dbuf[4] << 7 | dbuf[5] << 2 | dbuf[6] >> 3;
fallthrough;
case 5:
out[outi + 2] = dbuf[3] << 4 | dbuf[4] >> 1;
fallthrough;
case 4:
out[outi + 1] = dbuf[1] << 6 | dbuf[2] << 1 | dbuf[3] >> 4;
fallthrough;
case 2:
out[outi + 0] = dbuf[0] << 3 | dbuf[1] >> 2;
}
outi += 5;
}
return out;
}
+97
View File
@@ -0,0 +1,97 @@
package base64
// @note(zh): Encoding utility for Base64
// A secondary param can be used to supply a custom alphabet to
// @link(encode) and a matching decoding table to @link(decode).
// If none is supplied it just uses the standard Base64 alphabet.
// Incase your specific version does not use padding, you may
// truncate it from the encoded output.
ENC_TABLE := [64]byte {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/',
};
PADDING :: '=';
DEC_TABLE := [128]int {
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, 62, -1, -1, -1, 63,
52, 53, 54, 55, 56, 57, 58, 59,
60, 61, -1, -1, -1, -1, -1, -1,
-1, 0, 1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, -1, -1, -1, -1, -1,
-1, 26, 27, 28, 29, 30, 31, 32,
33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, -1, -1, -1, -1, -1,
};
encode :: proc(data: []byte, ENC_TBL := ENC_TABLE, allocator := context.allocator) -> string #no_bounds_check {
length := len(data);
if length == 0 {
return "";
}
out_length := ((4 * length / 3) + 3) &~ 3;
out := make([]byte, out_length, allocator);
c0, c1, c2, block: int;
for i, d := 0, 0; i < length; i, d = i + 3, d + 4 {
c0, c1, c2 = int(data[i]), -1, -1;
if i + 1 < length { c1 = int(data[i + 1]); }
if i + 2 < length { c2 = int(data[i + 2]); }
block = (c0 << 16) | (max(c1, 0) << 8) | max(c2, 0);
out[d] = ENC_TBL[block >> 18 & 63];
out[d + 1] = ENC_TBL[block >> 12 & 63];
out[d + 2] = c1 == -1 ? PADDING : ENC_TBL[block >> 6 & 63];
out[d + 3] = c2 == -1 ? PADDING : ENC_TBL[block & 63];
}
return string(out);
}
decode :: proc(data: string, DEC_TBL := DEC_TABLE, allocator := context.allocator) -> []byte #no_bounds_check {
length := len(data);
if length == 0 {
return nil;
}
pad_count := data[length - 1] == PADDING ? (data[length - 2] == PADDING ? 2 : 1) : 0;
out_length := ((length * 6) >> 3) - pad_count;
out := make([]byte, out_length, allocator);
c0, c1, c2, c3: int;
b0, b1, b2: int;
for i, j := 0, 0; i < length; i, j = i + 4, j + 3 {
c0 = DEC_TBL[data[i]];
c1 = DEC_TBL[data[i + 1]];
c2 = DEC_TBL[data[i + 2]];
c3 = DEC_TBL[data[i + 3]];
b0 = (c0 << 2) | (c1 >> 4);
b1 = (c1 << 4) | (c2 >> 2);
b2 = (c2 << 6) | c3;
out[j] = byte(b0);
out[j + 1] = byte(b1);
out[j + 2] = byte(b2);
}
return out;
}
+852
View File
@@ -0,0 +1,852 @@
package cel;
import "core:fmt"
import "core:strconv"
import "core:unicode/utf8"
import "core:strings"
Array :: []Value;
Dict :: map[string]Value;
Nil_Value :: struct{};
Value :: union {
Nil_Value,
bool, i64, f64, string,
Array, Dict,
}
Parser :: struct {
tokens: [dynamic]Token,
prev_token: Token,
curr_token: Token,
curr_token_index: int,
allocated_strings: [dynamic]string,
error_count: int,
root: Dict,
dict_stack: [dynamic]^Dict, // NOTE: Pointers may be stored on the stack
}
print_value :: proc(value: Value, pretty := true, indent := 0) {
print_indent :: proc(indent: int) {
for _ in 0..<indent {
fmt.print("\t");
}
}
switch v in value {
case bool: fmt.print(v);
case i64: fmt.print(v);
case f64: fmt.print(v);
case string: fmt.print(v);
case Array:
fmt.print("[");
if pretty { fmt.println(); }
for e, i in v {
if pretty {
print_indent(indent+1);
print_value(e, pretty, indent+1);
fmt.println(",");
} else {
if i > 0 { fmt.print(", "); }
print_value(e);
}
}
if pretty { print_indent(indent); }
fmt.print("]");
case Dict:
fmt.print("{");
if pretty { fmt.println(); }
i := 0;
for name, val in v {
if pretty {
print_indent(indent+1);
fmt.printf("%s = ", name);
print_value(val, pretty, indent+1);
fmt.println(",");
} else {
if i > 0 { fmt.print(", "); }
fmt.printf("%s = ", name);
print_value(val, pretty, indent+1);
i += 1;
}
}
if pretty { print_indent(indent); }
fmt.print("}");
case:
fmt.print("nil");
case Nil_Value:
fmt.print("nil");
}
}
print :: proc(p: ^Parser, pretty := false) {
for name, val in p.root {
fmt.printf("%s = ", name);
print_value(val, pretty);
fmt.println(";");
}
}
create_from_string :: proc(src: string) -> (^Parser, bool) {
return init(transmute([]byte)src);
}
init :: proc(src: []byte) -> (^Parser, bool) {
t: Tokenizer;
tokenizer_init(&t, src);
return create_from_tokenizer(&t);
}
create_from_tokenizer :: proc(t: ^Tokenizer) -> (^Parser, bool) {
p := new(Parser);
for {
tok := scan(t);
if tok.kind == .Illegal {
return p, false;
}
append(&p.tokens, tok);
if tok.kind == .EOF {
break;
}
}
if t.error_count > 0 {
return p, false;
}
if len(p.tokens) == 0 {
tok := Token{kind = .EOF};
tok.line, tok.column = 1, 1;
append(&p.tokens, tok);
return p, true;
}
p.curr_token_index = 0;
p.prev_token = p.tokens[p.curr_token_index];
p.curr_token = p.tokens[p.curr_token_index];
p.root = Dict{};
p.dict_stack = make([dynamic]^Dict, 0, 4);
append(&p.dict_stack, &p.root);
for p.curr_token.kind != .EOF &&
p.curr_token.kind != .Illegal &&
p.curr_token_index < len(p.tokens) {
if !parse_assignment(p) {
break;
}
}
return p, true;
}
destroy :: proc(p: ^Parser) {
destroy_value :: proc(value: Value) {
#partial switch v in value {
case Array:
for elem in v {
destroy_value(elem);
}
delete(v);
case Dict:
for _, dv in v {
destroy_value(dv);
}
delete(v);
}
}
delete(p.tokens);
for s in p.allocated_strings {
delete(s);
}
delete(p.allocated_strings);
delete(p.dict_stack);
destroy_value(p.root);
free(p);
}
error :: proc(p: ^Parser, pos: Pos, msg: string, args: ..any) {
fmt.eprintf("%s(%d:%d) Error: ", pos.file, pos.line, pos.column);
fmt.eprintf(msg, ..args);
fmt.eprintln();
p.error_count += 1;
}
next_token :: proc(p: ^Parser) -> Token {
p.prev_token = p.curr_token;
prev := p.prev_token;
if p.curr_token_index+1 < len(p.tokens) {
p.curr_token_index += 1;
p.curr_token = p.tokens[p.curr_token_index];
return prev;
}
p.curr_token_index = len(p.tokens);
p.curr_token = p.tokens[p.curr_token_index-1];
error(p, prev.pos, "Token is EOF");
return prev;
}
unquote_char :: proc(str: string, quote: byte) -> (r: rune, multiple_bytes: bool, tail_string: string, success: bool) {
hex_to_int :: proc(c: byte) -> int {
switch c {
case '0'..'9': return int(c-'0');
case 'a'..'f': return int(c-'a')+10;
case 'A'..'F': return int(c-'A')+10;
}
return -1;
}
w: int;
if str[0] == quote && quote == '"' {
return;
} else if str[0] >= 0x80 {
r, w = utf8.decode_rune_in_string(str);
return r, true, str[w:], true;
} else if str[0] != '\\' {
return rune(str[0]), false, str[1:], true;
}
if len(str) <= 1 {
return;
}
s := str;
c := s[1];
s = s[2:];
switch c {
case:
return;
case 'a': r = '\a';
case 'b': r = '\b';
case 'f': r = '\f';
case 'n': r = '\n';
case 'r': r = '\r';
case 't': r = '\t';
case 'v': r = '\v';
case '\\': r = '\\';
case '"': r = '"';
case '\'': r = '\'';
case '0'..'7':
v := int(c-'0');
if len(s) < 2 {
return;
}
for i in 0..<len(s) {
d := int(s[i]-'0');
if d < 0 || d > 7 {
return;
}
v = (v<<3) | d;
}
s = s[2:];
if v > 0xff {
return;
}
r = rune(v);
case 'x', 'u', 'U':
count: int;
switch c {
case 'x': count = 2;
case 'u': count = 4;
case 'U': count = 8;
}
if len(s) < count {
return;
}
for i in 0..<count {
d := hex_to_int(s[i]);
if d < 0 {
return;
}
r = (r<<4) | rune(d);
}
s = s[count:];
if c == 'x' {
break;
}
if r > utf8.MAX_RUNE {
return;
}
multiple_bytes = true;
}
success = true;
tail_string = s;
return;
}
unquote_string :: proc(p: ^Parser, t: Token) -> (string, bool) {
if t.kind != .String {
return t.lit, true;
}
s := t.lit;
quote := '"';
if s == `""` {
return "", true;
}
if strings.contains_rune(s, '\n') >= 0 {
return s, false;
}
if strings.contains_rune(s, '\\') < 0 && strings.contains_rune(s, quote) < 0 {
if quote == '"' {
return s, true;
}
}
buf_len := 3*len(s) / 2;
buf := make([]byte, buf_len);
offset := 0;
for len(s) > 0 {
r, multiple_bytes, tail_string, ok := unquote_char(s, byte(quote));
if !ok {
delete(buf);
return s, false;
}
s = tail_string;
if r < 0x80 || !multiple_bytes {
buf[offset] = byte(r);
offset += 1;
} else {
b, w := utf8.encode_rune(r);
copy(buf[offset:], b[:w]);
offset += w;
}
}
new_string := string(buf[:offset]);
append(&p.allocated_strings, new_string);
return new_string, true;
}
allow_token :: proc(p: ^Parser, kind: Kind) -> bool {
if p.curr_token.kind == kind {
next_token(p);
return true;
}
return false;
}
expect_token :: proc(p: ^Parser, kind: Kind) -> Token {
prev := p.curr_token;
if prev.kind != kind {
got := prev.lit;
if got == "\n" {
got = ";";
}
error(p, prev.pos, "Expected %s, got %s", kind_to_string[kind], got);
}
next_token(p);
return prev;
}
expect_operator :: proc(p: ^Parser) -> Token {
prev := p.curr_token;
if !is_operator(prev.kind) {
error(p, prev.pos, "Expected an operator, got %s", prev.lit);
}
next_token(p);
return prev;
}
fix_advance :: proc(p: ^Parser) {
for {
#partial switch t := p.curr_token; t.kind {
case .EOF, .Semicolon:
return;
}
next_token(p);
}
}
copy_value :: proc(value: Value) -> Value {
#partial switch v in value {
case Array:
a := make(Array, len(v));
for elem, idx in v {
a[idx] = copy_value(elem);
}
return a;
case Dict:
d := make(Dict, cap(v));
for key, val in v {
d[key] = copy_value(val);
}
return d;
}
return value;
}
lookup_value :: proc(p: ^Parser, name: string) -> (Value, bool) {
for i := len(p.dict_stack)-1; i >= 0; i -= 1 {
d := p.dict_stack[i];
if val, ok := d[name]; ok {
return copy_value(val), true;
}
}
return nil, false;
}
parse_operand :: proc(p: ^Parser) -> (Value, Pos) {
tok := p.curr_token;
#partial switch p.curr_token.kind {
case .Ident:
next_token(p);
v, ok := lookup_value(p, tok.lit);
if !ok { error(p, tok.pos, "Undeclared identifier %s", tok.lit); }
return v, tok.pos;
case .True:
next_token(p);
return true, tok.pos;
case .False:
next_token(p);
return false, tok.pos;
case .Nil:
next_token(p);
return Nil_Value{}, tok.pos;
case .Integer:
next_token(p);
i, _ := strconv.parse_i64(tok.lit);
return i, tok.pos;
case .Float:
next_token(p);
f, _ := strconv.parse_f64(tok.lit);
return f, tok.pos;
case .String:
next_token(p);
str, ok := unquote_string(p, tok);
if !ok { error(p, tok.pos, "Unable to unquote string"); }
return string(str), tok.pos;
case .Open_Paren:
expect_token(p, .Open_Paren);
expr, _ := parse_expr(p);
expect_token(p, .Close_Paren);
return expr, tok.pos;
case .Open_Bracket:
expect_token(p, .Open_Bracket);
elems := make([dynamic]Value, 0, 4);
for p.curr_token.kind != .Close_Bracket &&
p.curr_token.kind != .EOF {
elem, _ := parse_expr(p);
append(&elems, elem);
if p.curr_token.kind == .Semicolon && p.curr_token.lit == "\n" {
next_token(p);
} else if !allow_token(p, .Comma) {
break;
}
}
expect_token(p, .Close_Bracket);
return Array(elems[:]), tok.pos;
case .Open_Brace:
expect_token(p, .Open_Brace);
dict := Dict{};
append(&p.dict_stack, &dict);
defer pop(&p.dict_stack);
for p.curr_token.kind != .Close_Brace &&
p.curr_token.kind != .EOF {
name_tok := p.curr_token;
if !allow_token(p, .Ident) && !allow_token(p, .String) {
name_tok = expect_token(p, .Ident);
}
name, ok := unquote_string(p, name_tok);
if !ok { error(p, tok.pos, "Unable to unquote string"); }
expect_token(p, .Assign);
elem, _ := parse_expr(p);
if _, ok2 := dict[name]; ok2 {
error(p, name_tok.pos, "Previous declaration of %s in this scope", name);
} else {
dict[name] = elem;
}
if p.curr_token.kind == .Semicolon && p.curr_token.lit == "\n" {
next_token(p);
} else if !allow_token(p, .Comma) {
break;
}
}
expect_token(p, .Close_Brace);
return dict, tok.pos;
}
return nil, tok.pos;
}
parse_atom_expr :: proc(p: ^Parser, operand: Value, pos: Pos) -> (Value, Pos) {
loop := true;
for operand := operand; loop; {
#partial switch p.curr_token.kind {
case .Period:
next_token(p);
tok := next_token(p);
#partial switch tok.kind {
case .Ident:
d, ok := operand.(Dict);
if !ok || d == nil {
error(p, tok.pos, "Expected a dictionary");
operand = nil;
continue;
}
name, usok := unquote_string(p, tok);
if !usok { error(p, tok.pos, "Unable to unquote string"); }
val, found := d[name];
if !found {
error(p, tok.pos, "Field %s not found in dictionary", name);
operand = nil;
continue;
}
operand = val;
case:
error(p, tok.pos, "Expected a selector, got %s", tok.kind);
operand = nil;
}
case .Open_Bracket:
expect_token(p, .Open_Bracket);
index, index_pos := parse_expr(p);
expect_token(p, .Close_Bracket);
#partial switch a in operand {
case Array:
i, ok := index.(i64);
if !ok {
error(p, index_pos, "Index must be an integer for an array");
operand = nil;
continue;
}
if 0 <= i && i < i64(len(a)) {
operand = a[i];
} else {
error(p, index_pos, "Index %d out of bounds range 0..%d", i, len(a));
operand = nil;
continue;
}
case Dict:
key, ok := index.(string);
if !ok {
error(p, index_pos, "Index must be a string for a dictionary");
operand = nil;
continue;
}
val, found := a[key];
if found {
operand = val;
} else {
error(p, index_pos, "`%s` was not found in the dictionary", key);
operand = nil;
continue;
}
case:
error(p, index_pos, "Indexing is only allowed on an array or dictionary");
}
case:
loop = false;
}
}
return operand, pos;
}
parse_unary_expr :: proc(p: ^Parser) -> (Value, Pos) {
op := p.curr_token;
#partial switch p.curr_token.kind {
case .At:
next_token(p);
tok := expect_token(p, .String);
v, ok := lookup_value(p, tok.lit);
if !ok { error(p, tok.pos, "Undeclared identifier %s", tok.lit); }
return parse_atom_expr(p, v, tok.pos);
case .Add, .Sub:
next_token(p);
// TODO(bill): Calcuate values as you go!
expr, pos := parse_unary_expr(p);
#partial switch e in expr {
case i64: if op.kind == .Sub { return -e, pos; }
case f64: if op.kind == .Sub { return -e, pos; }
case:
error(p, op.pos, "Unary operator %s can only be used on integers or floats", op.lit);
return nil, op.pos;
}
return expr, op.pos;
case .Not:
next_token(p);
expr, _ := parse_unary_expr(p);
if v, ok := expr.(bool); ok {
return !v, op.pos;
}
error(p, op.pos, "Unary operator %s can only be used on booleans", op.lit);
return nil, op.pos;
}
return parse_atom_expr(p, parse_operand(p));
}
value_order :: proc(v: Value) -> int {
#partial switch _ in v {
case bool, string:
return 1;
case i64:
return 2;
case f64:
return 3;
}
return 0;
}
match_values :: proc(left, right: ^Value) -> bool {
if value_order(right^) < value_order(left^) {
return match_values(right, left);
}
#partial switch x in left^ {
case:
right^ = left^;
case bool, string:
return true;
case i64:
#partial switch y in right^ {
case i64:
return true;
case f64:
left^ = f64(x);
return true;
}
case f64:
#partial switch y in right {
case f64:
return true;
}
}
return false;
}
calculate_binary_value :: proc(p: ^Parser, op: Kind, a_, b_: Value) -> (Value, bool) {
// TODO(bill): Calculate value as you go!
x, y := a_, b_;
match_values(&x, &y);
#partial switch a in x {
case: return x, true;
case bool:
b, ok := y.(bool);
if !ok { return nil, false; }
#partial switch op {
case .Eq: return a == b, true;
case .NotEq: return a != b, true;
case .And: return a && b, true;
case .Or: return a || b, true;
}
case i64:
b, ok := y.(i64);
if !ok { return nil, false; }
#partial switch op {
case .Add: return a + b, true;
case .Sub: return a - b, true;
case .Mul: return a * b, true;
case .Quo: return a / b, true;
case .Rem: return a % b, true;
case .Eq: return a == b, true;
case .NotEq: return a != b, true;
case .Lt: return a < b, true;
case .Gt: return a > b, true;
case .LtEq: return a <= b, true;
case .GtEq: return a >= b, true;
}
case f64:
b, ok := y.(f64);
if !ok { return nil, false; }
#partial switch op {
case .Add: return a + b, true;
case .Sub: return a - b, true;
case .Mul: return a * b, true;
case .Quo: return a / b, true;
case .Eq: return a == b, true;
case .NotEq: return a != b, true;
case .Lt: return a < b, true;
case .Gt: return a > b, true;
case .LtEq: return a <= b, true;
case .GtEq: return a >= b, true;
}
case string:
b, ok := y.(string);
if !ok { return nil, false; }
#partial switch op {
case .Add:
n := len(a) + len(b);
data := make([]byte, n);
copy(data[:], a);
copy(data[len(a):], b);
s := string(data);
append(&p.allocated_strings, s);
return s, true;
case .Eq: return a == b, true;
case .NotEq: return a != b, true;
case .Lt: return a < b, true;
case .Gt: return a > b, true;
case .LtEq: return a <= b, true;
case .GtEq: return a >= b, true;
}
}
return nil, false;
}
parse_binary_expr :: proc(p: ^Parser, prec_in: int) -> (Value, Pos) {
expr, pos := parse_unary_expr(p);
for prec := precedence(p.curr_token.kind); prec >= prec_in; prec -= 1 {
for {
op := p.curr_token;
op_prec := precedence(op.kind);
if op_prec != prec {
break;
}
expect_operator(p);
if op.kind == .Question {
cond := expr;
x, _ := parse_expr(p);
expect_token(p, .Colon);
y, _ := parse_expr(p);
if t, ok := cond.(bool); ok {
expr = t ? x : y;
} else {
error(p, pos, "Condition must be a boolean");
}
} else {
right, right_pos := parse_binary_expr(p, prec+1);
if right == nil {
error(p, right_pos, "Expected expression on the right-hand side of the binary operator %s", op.lit);
}
left := expr;
ok: bool;
expr, ok = calculate_binary_value(p, op.kind, left, right);
if !ok {
error(p, pos, "Invalid binary operation");
}
}
}
}
return expr, pos;
}
parse_expr :: proc(p: ^Parser) -> (Value, Pos) {
return parse_binary_expr(p, 1);
}
expect_semicolon :: proc(p: ^Parser) {
kind := p.curr_token.kind;
#partial switch kind {
case .Comma:
error(p, p.curr_token.pos, "Expected ';', got ','");
next_token(p);
case .Semicolon:
next_token(p);
case .EOF:
// okay
case:
error(p, p.curr_token.pos, "Expected ';', got %s", p.curr_token.lit);
fix_advance(p);
}
}
parse_assignment :: proc(p: ^Parser) -> bool {
top_dict :: proc(p: ^Parser) -> ^Dict {
assert(len(p.dict_stack) > 0);
return p.dict_stack[len(p.dict_stack)-1];
}
if p.curr_token.kind == .Semicolon {
next_token(p);
return true;
}
if p.curr_token.kind == .EOF {
return false;
}
tok := p.curr_token;
if allow_token(p, .Ident) || allow_token(p, .String) {
expect_token(p, .Assign);
name, ok := unquote_string(p, tok);
if !ok { error(p, tok.pos, "Unable to unquote string"); }
expr, _ := parse_expr(p);
d := top_dict(p);
if _, ok2 := d[name]; ok2 {
error(p, tok.pos, "Previous declaration of %s", name);
} else {
d[name] = expr;
}
expect_semicolon(p);
return true;
}
error(p, tok.pos, "Expected an assignment, got %s", kind_to_string[tok.kind]);
fix_advance(p);
return false;
}
+51
View File
@@ -0,0 +1,51 @@
/*
package cel
sample := `
x = 123;
y = 321.456;
z = x * (y - 1) / 2;
w = "foo" + "bar";
# This is a comment
asd = "Semicolons are optional"
a = {id = {b = 123}} # Dict
b = a.id.b
f = [1, 4, 9] # Array
g = f[2]
h = x < y and w == "foobar"
i = h ? 123 : "google"
j = nil
"127.0.0.1" = "value" # Keys can be strings
"foo" = {
"bar" = {
"baz" = 123, # optional commas if newline is present
"zab" = 456,
"abz" = 789,
},
};
bar = @"foo"["bar"].baz
`;
main :: proc() {
p, ok := create_from_string(sample);
if !ok {
return;
}
defer destroy(p);
if p.error_count == 0 {
print(p);
}
}
*/
package cel
+523
View File
@@ -0,0 +1,523 @@
package cel
import "core:fmt"
import "core:unicode/utf8"
using Kind :: enum {
Illegal,
EOF,
Comment,
_literal_start,
Ident,
Integer,
Float,
Char,
String,
_literal_end,
_keyword_start,
True, // true
False, // false
Nil, // nil
_keyword_end,
_operator_start,
Question, // ?
And, // and
Or, // or
Add, // +
Sub, // -
Mul, // *
Quo, // /
Rem, // %
Not, // !
Eq, // ==
NotEq, // !=
Lt, // <
Gt, // >
LtEq, // <=
GtEq, // >=
At, // @
_operator_end,
_punc_start,
Assign, // =
Open_Paren, // (
Close_Paren, // )
Open_Bracket, // [
Close_Bracket, // ]
Open_Brace, // {
Close_Brace, // }
Colon, // :
Semicolon, // ;
Comma, // ,
Period, // .
_punc_end,
}
Pos :: struct {
file: string,
line: int,
column: int,
}
Token :: struct {
kind: Kind,
using pos: Pos,
lit: string,
}
Tokenizer :: struct {
src: []byte,
file: string, // May not be used
curr_rune: rune,
offset: int,
read_offset: int,
line_offset: int,
line_count: int,
insert_semi: bool,
error_count: int,
}
keywords := map[string]Kind{
"true" = True,
"false" = False,
"nil" = Nil,
"and" = And,
"or" = Or,
};
kind_to_string := [len(Kind)]string{
"illegal",
"EOF",
"comment",
"",
"identifier",
"integer",
"float",
"character",
"string",
"",
"",
"true", "false", "nil",
"",
"",
"?", "and", "or",
"+", "-", "*", "/", "%",
"!",
"==", "!=", "<", ">", "<=", ">=",
"@",
"",
"",
"=",
"(", ")",
"[", "]",
"{", "}",
":", ";", ",", ".",
"",
};
precedence :: proc(op: Kind) -> int {
#partial switch op {
case Question:
return 1;
case Or:
return 2;
case And:
return 3;
case Eq, NotEq, Lt, Gt, LtEq, GtEq:
return 4;
case Add, Sub:
return 5;
case Mul, Quo, Rem:
return 6;
}
return 0;
}
token_lookup :: proc(ident: string) -> Kind {
if tok, is_keyword := keywords[ident]; is_keyword {
return tok;
}
return Ident;
}
is_literal :: proc(tok: Kind) -> bool { return _literal_start < tok && tok < _literal_end; }
is_operator :: proc(tok: Kind) -> bool { return _operator_start < tok && tok < _operator_end; }
is_keyword :: proc(tok: Kind) -> bool { return _keyword_start < tok && tok < _keyword_end; }
tokenizer_init :: proc(t: ^Tokenizer, src: []byte, file := "") {
t.src = src;
t.file = file;
t.curr_rune = ' ';
t.offset = 0;
t.read_offset = 0;
t.line_offset = 0;
t.line_count = 1;
advance_to_next_rune(t);
if t.curr_rune == utf8.RUNE_BOM {
advance_to_next_rune(t);
}
}
token_error :: proc(t: ^Tokenizer, msg: string, args: ..any) {
fmt.eprintf("%s(%d:%d) Error: ", t.file, t.line_count, t.read_offset-t.line_offset+1);
fmt.eprintf(msg, ..args);
fmt.eprintln();
t.error_count += 1;
}
advance_to_next_rune :: proc(t: ^Tokenizer) {
if t.read_offset < len(t.src) {
t.offset = t.read_offset;
if t.curr_rune == '\n' {
t.line_offset = t.offset;
t.line_count += 1;
}
r, w := rune(t.src[t.read_offset]), 1;
switch {
case r == 0:
token_error(t, "Illegal character NUL");
case r >= utf8.RUNE_SELF:
r, w = utf8.decode_rune(t.src[t.read_offset:]);
if r == utf8.RUNE_ERROR && w == 1 {
token_error(t, "Illegal utf-8 encoding");
} else if r == utf8.RUNE_BOM && t.offset > 0 {
token_error(t, "Illegal byte order mark");
}
}
t.read_offset += w;
t.curr_rune = r;
} else {
t.offset = len(t.src);
if t.curr_rune == '\n' {
t.line_offset = t.offset;
t.line_count += 1;
}
t.curr_rune = utf8.RUNE_EOF;
}
}
get_pos :: proc(t: ^Tokenizer) -> Pos {
return Pos {
file = t.file,
line = t.line_count,
column = t.offset - t.line_offset + 1,
};
}
is_letter :: proc(r: rune) -> bool {
switch r {
case 'a'..'z', 'A'..'Z', '_':
return true;
}
return false;
}
is_digit :: proc(r: rune) -> bool {
switch r {
case '0'..'9':
return true;
}
return false;
}
skip_whitespace :: proc(t: ^Tokenizer) {
loop: for {
switch t.curr_rune {
case '\n':
if t.insert_semi {
break loop;
}
fallthrough;
case ' ', '\t', '\r', '\v', '\f':
advance_to_next_rune(t);
case:
break loop;
}
}
}
scan_identifier :: proc(t: ^Tokenizer) -> string {
offset := t.offset;
for is_letter(t.curr_rune) || is_digit(t.curr_rune) {
advance_to_next_rune(t);
}
return string(t.src[offset : t.offset]);
}
digit_value :: proc(r: rune) -> int {
switch r {
case '0'..'9': return int(r - '0');
case 'a'..'f': return int(r - 'a' + 10);
case 'A'..'F': return int(r - 'A' + 10);
}
return 16;
}
scan_number :: proc(t: ^Tokenizer, seen_decimal_point: bool) -> (Kind, string) {
scan_mantissa :: proc(t: ^Tokenizer, base: int) {
for digit_value(t.curr_rune) < base || t.curr_rune == '_' {
advance_to_next_rune(t);
}
}
scan_exponent :: proc(t: ^Tokenizer, tok: Kind, offset: int) -> (kind: Kind, text: string) {
kind = tok;
if t.curr_rune == 'e' || t.curr_rune == 'E' {
kind = Float;
advance_to_next_rune(t);
if t.curr_rune == '-' || t.curr_rune == '+' {
advance_to_next_rune(t);
}
if digit_value(t.curr_rune) < 10 {
scan_mantissa(t, 10);
} else {
token_error(t, "Illegal floating point exponent");
}
}
text = string(t.src[offset : t.offset]);
return;
}
scan_fraction :: proc(t: ^Tokenizer, tok: Kind, offset: int) -> (kind: Kind, text: string) {
kind = tok;
if t.curr_rune == '.' {
kind = Float;
advance_to_next_rune(t);
scan_mantissa(t, 10);
}
return scan_exponent(t, kind, offset);
}
offset := t.offset;
tok := Integer;
if seen_decimal_point {
offset -= 1;
tok = Float;
scan_mantissa(t, 10);
return scan_exponent(t, tok, offset);
}
if t.curr_rune == '0' {
offset = t.offset;
advance_to_next_rune(t);
switch t.curr_rune {
case 'b', 'B':
advance_to_next_rune(t);
scan_mantissa(t, 2);
if t.offset - offset <= 2 {
token_error(t, "Illegal binary number");
}
case 'o', 'O':
advance_to_next_rune(t);
scan_mantissa(t, 8);
if t.offset - offset <= 2 {
token_error(t, "Illegal octal number");
}
case 'x', 'X':
advance_to_next_rune(t);
scan_mantissa(t, 16);
if t.offset - offset <= 2 {
token_error(t, "Illegal hexadecimal number");
}
case:
scan_mantissa(t, 10);
switch t.curr_rune {
case '.', 'e', 'E':
return scan_fraction(t, tok, offset);
}
}
return tok, string(t.src[offset:t.offset]);
}
scan_mantissa(t, 10);
return scan_fraction(t, tok, offset);
}
scan :: proc(t: ^Tokenizer) -> Token {
skip_whitespace(t);
offset := t.offset;
tok: Kind;
pos := get_pos(t);
lit: string;
insert_semi := false;
switch r := t.curr_rune; {
case is_letter(r):
insert_semi = true;
lit = scan_identifier(t);
tok = Ident;
if len(lit) > 1 {
tok = token_lookup(lit);
}
case '0' <= r && r <= '9':
insert_semi = true;
tok, lit = scan_number(t, false);
case:
advance_to_next_rune(t);
switch r {
case -1:
if t.insert_semi {
t.insert_semi = false;
return Token{Semicolon, pos, "\n"};
}
return Token{EOF, pos, "\n"};
case '\n':
t.insert_semi = false;
return Token{Semicolon, pos, "\n"};
case '"':
insert_semi = true;
quote := r;
tok = String;
for {
this_r := t.curr_rune;
if this_r == '\n' || r < 0 {
token_error(t, "String literal not terminated");
break;
}
advance_to_next_rune(t);
if this_r == quote {
break;
}
// TODO(bill); Handle properly
if this_r == '\\' && t.curr_rune == quote {
advance_to_next_rune(t);
}
}
lit = string(t.src[offset+1:t.offset-1]);
case '#':
for t.curr_rune != '\n' && t.curr_rune >= 0 {
advance_to_next_rune(t);
}
if t.insert_semi {
t.insert_semi = false;
return Token{Semicolon, pos, "\n"};
}
// Recursive!
return scan(t);
case '?': tok = Question;
case ':': tok = Colon;
case '@': tok = At;
case ';':
tok = Semicolon;
lit = ";";
case ',': tok = Comma;
case '(':
tok = Open_Paren;
case ')':
insert_semi = true;
tok = Close_Paren;
case '[':
tok = Open_Bracket;
case ']':
insert_semi = true;
tok = Close_Bracket;
case '{':
tok = Open_Brace;
case '}':
insert_semi = true;
tok = Close_Brace;
case '+': tok = Add;
case '-': tok = Sub;
case '*': tok = Mul;
case '/': tok = Quo;
case '%': tok = Rem;
case '!':
tok = Not;
if t.curr_rune == '=' {
advance_to_next_rune(t);
tok = NotEq;
}
case '=':
tok = Assign;
if t.curr_rune == '=' {
advance_to_next_rune(t);
tok = Eq;
}
case '<':
tok = Lt;
if t.curr_rune == '=' {
advance_to_next_rune(t);
tok = LtEq;
}
case '>':
tok = Gt;
if t.curr_rune == '=' {
advance_to_next_rune(t);
tok = GtEq;
}
case '.':
if '0' <= t.curr_rune && t.curr_rune <= '9' {
insert_semi = true;
tok, lit = scan_number(t, true);
} else {
tok = Period;
}
case:
if r != utf8.RUNE_BOM {
token_error(t, "Illegal character '%r'", r);
}
insert_semi = t.insert_semi;
tok = Illegal;
}
}
t.insert_semi = insert_semi;
if lit == "" {
lit = string(t.src[offset:t.offset]);
}
return Token{tok, pos, lit};
}
+406
View File
@@ -0,0 +1,406 @@
// package csv reads and writes comma-separated values (CSV) files.
// This package supports the format described in RFC 4180 <https://tools.ietf.org/html/rfc4180.html>
package csv
import "core:bufio"
import "core:bytes"
import "core:io"
import "core:strings"
import "core:unicode/utf8"
// Reader is a data structure used for reading records from a CSV-encoded file
//
// The associated procedures for Reader expects its input to conform to RFC 4180.
Reader :: struct {
// comma is the field delimiter
// reader_init will set it to be ','
// A "comma" must be a valid rune, nor can it be \r, \n, or the Unicode replacement character (0xfffd)
comma: rune,
// comment, if not 0, is the comment character
// Lines beginning with the comment character without a preceding whitespace are ignored
comment: rune,
// fields_per_record is the number of expected fields per record
// if fields_per_record is >0, 'read' requires each record to have that field count
// if fields_per_record is 0, 'read' sets it to the field count in the first record
// if fields_per_record is <0, no check is made and records may have a variable field count
fields_per_record: int,
// If trim_leading_space is true, leading whitespace in a field is ignored
// This is done even if the field delimiter (comma), is whitespace
trim_leading_space: bool,
// If lazy_quotes is true, a quote may appear in an unquoted field and a non-doubled quote may appear in a quoted field
lazy_quotes: bool,
// reuse_record controls whether calls to 'read' may return a slice using the backing buffer
// for performance
// By default, each call to 'read' returns a newly allocated slice
reuse_record: bool,
// reuse_record_buffer controls whether calls to 'read' clone the strings of each field or uses
// the data stored in record buffer for performance
// By default, each call to 'read' clones the strings of each field
reuse_record_buffer: bool,
// internal buffers
r: bufio.Reader,
line_count: int, // current line being read in the CSV file
raw_buffer: [dynamic]byte,
record_buffer: [dynamic]byte,
field_indices: [dynamic]int,
last_record: [dynamic]string,
sr: strings.Reader, // used by reader_init_with_string
}
Reader_Error_Kind :: enum {
Bare_Quote,
Quote,
Field_Count,
Invalid_Delim,
}
reader_error_kind_string := [Reader_Error_Kind]string{
.Bare_Quote = "bare \" in non-quoted field",
.Quote = "extra or missing \" in quoted field",
.Field_Count = "wrong field count",
.Invalid_Delim = "invalid delimiter",
};
Reader_Error :: struct {
kind: Reader_Error_Kind,
start_line: int,
line: int,
column: int,
expected, got: int, // used by .Field_Count
}
Error :: union {
Reader_Error,
io.Error,
}
DEFAULT_RECORD_BUFFER_CAPACITY :: 256;
// reader_init initializes a new Reader from r
reader_init :: proc(reader: ^Reader, r: io.Reader, buffer_allocator := context.allocator) {
reader.comma = ',';
context.allocator = buffer_allocator;
reserve(&reader.record_buffer, DEFAULT_RECORD_BUFFER_CAPACITY);
reserve(&reader.raw_buffer, 0);
reserve(&reader.field_indices, 0);
reserve(&reader.last_record, 0);
bufio.reader_init(&reader.r, r);
}
// reader_init_with_string initializes a new Reader from s
reader_init_with_string :: proc(reader: ^Reader, s: string, buffer_allocator := context.allocator) {
strings.reader_init(&reader.sr, s);
r, _ := io.to_reader(strings.reader_to_stream(&reader.sr));
reader_init(reader, r, buffer_allocator);
}
// reader_destroy destroys a Reader
reader_destroy :: proc(r: ^Reader) {
delete(r.raw_buffer);
delete(r.record_buffer);
delete(r.field_indices);
delete(r.last_record);
bufio.reader_destroy(&r.r);
}
// read reads a single record (a slice of fields) from r
//
// All \r\n sequences are normalized to \n, including multi-line field
read :: proc(r: ^Reader, allocator := context.allocator) -> (record: []string, err: Error) {
if r.reuse_record {
record, err = _read_record(r, &r.last_record, allocator);
resize(&r.last_record, len(record));
copy(r.last_record[:], record);
} else {
record, err = _read_record(r, nil, allocator);
}
return;
}
// is_io_error checks where an Error is a specific io.Error kind
is_io_error :: proc(err: Error, io_err: io.Error) -> bool {
if v, ok := err.(io.Error); ok {
return v == io_err;
}
return false;
}
// read_all reads all the remaining records from r.
// Each record is a slice of fields.
// read_all is defined to read until an EOF, and does not treat, and does not treat EOF as an error
read_all :: proc(r: ^Reader, allocator := context.allocator) -> ([][]string, Error) {
context.allocator = allocator;
records: [dynamic][]string;
for {
record, rerr := _read_record(r, nil, allocator);
if is_io_error(rerr, .EOF) {
return records[:], nil;
}
if rerr != nil {
return nil, rerr;
}
append(&records, record);
}
}
// read reads a single record (a slice of fields) from the provided input.
read_from_string :: proc(input: string, record_allocator := context.allocator, buffer_allocator := context.allocator) -> (record: []string, n: int, err: Error) {
ir: strings.Reader;
strings.reader_init(&ir, input);
input_reader, _ := io.to_reader(strings.reader_to_stream(&ir));
r: Reader;
reader_init(&r, input_reader, buffer_allocator);
defer reader_destroy(&r);
record, err = read(&r, record_allocator);
n = int(r.r.r);
return;
}
// read_all reads all the remaining records from the provided input.
read_all_from_string :: proc(input: string, records_allocator := context.allocator, buffer_allocator := context.allocator) -> ([][]string, Error) {
ir: strings.Reader;
strings.reader_init(&ir, input);
input_reader, _ := io.to_reader(strings.reader_to_stream(&ir));
r: Reader;
reader_init(&r, input_reader, buffer_allocator);
defer reader_destroy(&r);
return read_all(&r, records_allocator);
}
@private
is_valid_delim :: proc(r: rune) -> bool {
switch r {
case 0, '"', '\r', '\n', utf8.RUNE_ERROR:
return false;
}
return utf8.valid_rune(r);
}
@private
_read_record :: proc(r: ^Reader, dst: ^[dynamic]string, allocator := context.allocator) -> ([]string, Error) {
read_line :: proc(r: ^Reader) -> ([]byte, io.Error) {
line, err := bufio.reader_read_slice(&r.r, '\n');
if err == .Buffer_Full {
clear(&r.raw_buffer);
append(&r.raw_buffer, ..line);
for err == .Buffer_Full {
line, err = bufio.reader_read_slice(&r.r, '\n');
append(&r.raw_buffer, ..line);
}
line = r.raw_buffer[:];
}
if len(line) > 0 && err == .EOF {
err = nil;
if line[len(line)-1] == '\r' {
line = line[:len(line)-1];
}
}
r.line_count += 1;
// normalize \r\n to \n
n := len(line);
for n >= 2 && string(line[n-2:]) == "\r\n" {
line[n-2] = '\n';
line = line[:n-1];
}
return line, err;
}
length_newline :: proc(b: []byte) -> int {
if len(b) > 0 && b[len(b)-1] == '\n' {
return 1;
}
return 0;
}
next_rune :: proc(b: []byte) -> rune {
r, _ := utf8.decode_rune(b);
return r;
}
if r.comma == r.comment ||
!is_valid_delim(r.comma) ||
(r.comment != 0 && !is_valid_delim(r.comment)) {
err := Reader_Error{
kind = .Invalid_Delim,
line = r.line_count,
};
return nil, err;
}
line, full_line: []byte;
err_read: io.Error;
for err_read == nil {
line, err_read = read_line(r);
if r.comment != 0 && next_rune(line) == r.comment {
line = nil;
continue;
}
if err_read == nil && len(line) == length_newline(line) {
line = nil;
continue;
}
full_line = line;
break;
}
if is_io_error(err_read, .EOF) {
return nil, err_read;
}
err: Error;
quote_len :: len(`"`);
comma_len := utf8.rune_size(r.comma);
record_line := r.line_count;
clear(&r.record_buffer);
clear(&r.field_indices);
parse_field: for {
if r.trim_leading_space {
line = bytes.trim_left_space(line);
}
if len(line) == 0 || line[0] != '"' {
i := bytes.index_rune(line, r.comma);
field := line;
if i >= 0 {
field = field[:i];
} else {
field = field[:len(field) - length_newline(field)];
}
if !r.lazy_quotes {
if j := bytes.index_byte(field, '"'); j >= 0 {
column := utf8.rune_count(full_line[:len(full_line) - len(line[j:])]);
err = Reader_Error{
kind = .Bare_Quote,
start_line = record_line,
line = r.line_count,
column = column,
};
break parse_field;
}
}
append(&r.record_buffer, ..field);
append(&r.field_indices, len(r.record_buffer));
if i >= 0 {
line = line[i+comma_len:];
continue parse_field;
}
break parse_field;
} else {
line = line[quote_len:];
for {
i := bytes.index_byte(line, '"');
switch {
case i >= 0:
append(&r.record_buffer, ..line[:i]);
line = line[i+quote_len:];
switch ch := next_rune(line); {
case ch == '"': // append quote
append(&r.record_buffer, '"');
line = line[quote_len:];
case ch == r.comma: // end of field
line = line[comma_len:];
append(&r.field_indices, len(r.record_buffer));
continue parse_field;
case length_newline(line) == len(line): // end of line
append(&r.field_indices, len(r.record_buffer));
break parse_field;
case r.lazy_quotes: // bare quote
append(&r.record_buffer, '"');
case: // invalid non-escaped quote
column := utf8.rune_count(full_line[:len(full_line) - len(line) - quote_len]);
err = Reader_Error{
kind = .Quote,
start_line = record_line,
line = r.line_count,
column = column,
};
break parse_field;
}
case len(line) > 0:
append(&r.record_buffer, ..line);
if err_read != nil {
break parse_field;
}
line, err_read = read_line(r);
if is_io_error(err_read, .EOF) {
err_read = nil;
}
full_line = line;
case:
if !r.lazy_quotes && err_read == nil {
column := utf8.rune_count(full_line);
err = Reader_Error{
kind = .Quote,
start_line = record_line,
line = r.line_count,
column = column,
};
break parse_field;
}
append(&r.field_indices, len(r.record_buffer));
break parse_field;
}
}
}
}
if err == nil && err_read != nil {
err = err_read;
}
context.allocator = allocator;
dst := dst;
str := string(r.record_buffer[:]);
if dst == nil {
// use local variable
dst = &([dynamic]string){};
}
clear(dst);
resize(dst, len(r.field_indices));
pre_idx: int;
for idx, i in r.field_indices {
field := str[pre_idx:idx];
if !r.reuse_record_buffer {
field = strings.clone(field);
}
dst[i] = field;
pre_idx = idx;
}
if r.fields_per_record > 0 {
if len(dst) != r.fields_per_record && err == nil {
err = Reader_Error{
kind = .Field_Count,
start_line = record_line,
line = r.line_count,
expected = r.fields_per_record,
got = len(dst),
};
}
} else if r.fields_per_record == 0 {
r.fields_per_record = len(dst);
}
return dst[:], err;
}
+147
View File
@@ -0,0 +1,147 @@
package csv
import "core:io"
import "core:strings"
import "core:unicode/utf8"
// Writer is a data structure used for writing records using a CSV-encoding.
Writer :: struct {
// Field delimiter (set to ',' with writer_init)
comma: rune,
// if set to true, \r\n will be used as the line terminator
use_crlf: bool,
w: io.Writer,
}
// writer_init initializes a Writer that writes to w
writer_init :: proc(writer: ^Writer, w: io.Writer) {
writer.comma = ',';
writer.w = w;
}
// write writes a single CSV records to w with any of the necessarily quoting.
// A record is a slice of strings, where each string is a single field.
//
// If the underlying io.Writer requires flushing, make sure to call io.flush
write :: proc(w: ^Writer, record: []string) -> io.Error {
CHAR_SET :: "\n\r\"";
field_needs_quoting :: proc(w: ^Writer, field: string) -> bool {
switch {
case field == "": // No need to quote empty strings
return false;
case field == `\.`: // Postgres is weird
return true;
case w.comma < utf8.RUNE_SELF: // ASCII optimization
for i in 0..<len(field) {
switch field[i] {
case '\n', '\r', '"', byte(w.comma):
return true;
}
}
case:
if strings.contains_rune(field, w.comma) >= 0 {
return true;
}
if strings.contains_any(field, CHAR_SET) {
return true;
}
}
// Leading spaces need quoting
r, _ := utf8.decode_rune_in_string(field);
return strings.is_space(r);
}
if !is_valid_delim(w.comma) {
return .No_Progress; // TODO(bill): Is this a good error?
}
for _, field_idx in record {
// NOTE(bill): declared like this so that the field can be modified later if necessary
field := record[field_idx];
if field_idx > 0 {
if _, err := io.write_rune(w.w, w.comma); err != nil {
return err;
}
}
if !field_needs_quoting(w, field) {
if _, err := io.write_string(w.w, field); err != nil {
return err;
}
continue;
}
if err := io.write_byte(w.w, '"'); err != nil {
return err;
}
for len(field) > 0 {
i := strings.index_any(field, CHAR_SET);
if i < 0 {
i = len(field);
}
if _, err := io.write_string(w.w, field[:i]); err != nil {
return err;
}
field = field[i:];
if len(field) > 0 {
switch field[0] {
case '\r':
if !w.use_crlf {
if err := io.write_byte(w.w, '\r'); err != nil {
return err;
}
}
case '\n':
if w.use_crlf {
if _, err := io.write_string(w.w, "\r\n"); err != nil {
return err;
}
} else {
if err := io.write_byte(w.w, '\n'); err != nil {
return err;
}
}
case '"':
if _, err := io.write_string(w.w, `""`); err != nil {
return err;
}
}
field = field[1:];
}
}
if err := io.write_byte(w.w, '"'); err != nil {
return err;
}
}
if w.use_crlf {
_, err := io.write_string(w.w, "\r\n");
return err;
}
return io.write_byte(w.w, '\n');
}
// write_all writes multiple CSV records to w using write, and then flushes (if necessary).
write_all :: proc(w: ^Writer, records: [][]string) -> io.Error {
for record in records {
err := write(w, record);
if err != nil {
return err;
}
}
return writer_flush(w);
}
// writer_flush flushes the underlying io.Writer.
// If the underlying io.Writer does not support flush, nil is returned.
writer_flush :: proc(w: ^Writer) -> io.Error {
return io.flush(auto_cast w.w);
}
+316
View File
@@ -0,0 +1,316 @@
package json
import "core:mem"
import "core:math/bits"
import "core:runtime"
import "core:strconv"
import "core:strings"
Marshal_Error :: enum {
None,
Unsupported_Type,
Invalid_Data,
}
marshal :: proc(v: any, allocator := context.allocator) -> ([]byte, Marshal_Error) {
b: strings.Builder;
strings.init_builder(&b, allocator);
err := marshal_arg(&b, v);
if err != .None {
strings.destroy_builder(&b);
return nil, err;
}
if len(b.buf) == 0 {
strings.destroy_builder(&b);
return nil, err;
}
return b.buf[:], err;
}
marshal_arg :: proc(b: ^strings.Builder, v: any) -> Marshal_Error {
using strings;
using runtime;
if v == nil {
write_string(b, "null");
return .None;
}
ti := type_info_base(type_info_of(v.id));
a := any{v.data, ti.id};
switch info in ti.variant {
case Type_Info_Named:
unreachable();
case Type_Info_Integer:
buf: [21]byte;
u: u64;
switch i in a {
case i8: u = u64(i);
case i16: u = u64(i);
case i32: u = u64(i);
case i64: u = u64(i);
case int: u = u64(i);
case u8: u = u64(i);
case u16: u = u64(i);
case u32: u = u64(i);
case u64: u = u64(i);
case uint: u = u64(i);
case uintptr: u = u64(i);
case i16le: u = u64(i);
case i32le: u = u64(i);
case i64le: u = u64(i);
case u16le: u = u64(i);
case u32le: u = u64(i);
case u64le: u = u64(i);
case i16be: u = u64(i);
case i32be: u = u64(i);
case i64be: u = u64(i);
case u16be: u = u64(i);
case u32be: u = u64(i);
case u64be: u = u64(i);
}
s := strconv.append_bits(buf[:], u, 10, info.signed, 8*ti.size, "0123456789", nil);
write_string(b, s);
case Type_Info_Rune:
r := a.(rune);
write_byte(b, '"');
write_escaped_rune(b, r, '"', true);
write_byte(b, '"');
case Type_Info_Float:
val: f64;
switch f in a {
case f16: val = f64(f);
case f32: val = f64(f);
case f64: val = f64(f);
}
buf: [386]byte;
str := strconv.append_float(buf[1:], val, 'f', 2*ti.size, 8*ti.size);
s := buf[:len(str)+1];
if s[1] == '+' || s[1] == '-' {
s = s[1:];
} else {
s[0] = '+';
}
if s[0] == '+' {
s = s[1:];
}
write_string(b, string(s));
case Type_Info_Complex:
return .Unsupported_Type;
case Type_Info_Quaternion:
return .Unsupported_Type;
case Type_Info_String:
switch s in a {
case string: write_quoted_string(b, s);
case cstring: write_quoted_string(b, string(s));
}
case Type_Info_Boolean:
val: bool;
switch b in a {
case bool: val = bool(b);
case b8: val = bool(b);
case b16: val = bool(b);
case b32: val = bool(b);
case b64: val = bool(b);
}
write_string_builder(b, val ? "true" : "false");
case Type_Info_Any:
return .Unsupported_Type;
case Type_Info_Type_Id:
return .Unsupported_Type;
case Type_Info_Pointer:
return .Unsupported_Type;
case Type_Info_Procedure:
return .Unsupported_Type;
case Type_Info_Tuple:
return .Unsupported_Type;
case Type_Info_Enumerated_Array:
return .Unsupported_Type;
case Type_Info_Simd_Vector:
return .Unsupported_Type;
case Type_Info_Relative_Pointer:
return .Unsupported_Type;
case Type_Info_Relative_Slice:
return .Unsupported_Type;
case Type_Info_Array:
write_byte(b, '[');
for i in 0..<info.count {
if i > 0 { write_string(b, ", "); }
data := uintptr(v.data) + uintptr(i*info.elem_size);
marshal_arg(b, any{rawptr(data), info.elem.id});
}
write_byte(b, ']');
case Type_Info_Dynamic_Array:
write_byte(b, '[');
array := cast(^mem.Raw_Dynamic_Array)v.data;
for i in 0..<array.len {
if i > 0 { write_string(b, ", "); }
data := uintptr(array.data) + uintptr(i*info.elem_size);
marshal_arg(b, any{rawptr(data), info.elem.id});
}
write_byte(b, ']');
case Type_Info_Slice:
write_byte(b, '[');
slice := cast(^mem.Raw_Slice)v.data;
for i in 0..<slice.len {
if i > 0 { write_string(b, ", "); }
data := uintptr(slice.data) + uintptr(i*info.elem_size);
marshal_arg(b, any{rawptr(data), info.elem.id});
}
write_byte(b, ']');
case Type_Info_Map:
m := (^mem.Raw_Map)(v.data);
write_byte(b, '{');
if m != nil {
if info.generated_struct == nil {
return .Unsupported_Type;
}
entries := &m.entries;
gs := type_info_base(info.generated_struct).variant.(Type_Info_Struct);
ed := type_info_base(gs.types[1]).variant.(Type_Info_Dynamic_Array);
entry_type := ed.elem.variant.(Type_Info_Struct);
entry_size := ed.elem_size;
for i in 0..<entries.len {
if i > 0 { write_string(b, ", "); }
data := uintptr(entries.data) + uintptr(i*entry_size);
key := rawptr(data + entry_type.offsets[2]);
value := rawptr(data + entry_type.offsets[3]);
marshal_arg(b, any{key, info.key.id});
write_string(b, ": ");
marshal_arg(b, any{value, info.value.id});
}
}
write_byte(b, '}');
case Type_Info_Struct:
write_byte(b, '{');
for name, i in info.names {
if i > 0 { write_string(b, ", "); }
write_quoted_string(b, name);
write_string(b, ": ");
id := info.types[i].id;
data := rawptr(uintptr(v.data) + info.offsets[i]);
marshal_arg(b, any{data, id});
}
write_byte(b, '}');
case Type_Info_Union:
tag_ptr := uintptr(v.data) + info.tag_offset;
tag_any := any{rawptr(tag_ptr), info.tag_type.id};
tag: i64 = -1;
switch i in tag_any {
case u8: tag = i64(i);
case i8: tag = i64(i);
case u16: tag = i64(i);
case i16: tag = i64(i);
case u32: tag = i64(i);
case i32: tag = i64(i);
case u64: tag = i64(i);
case i64: tag = i64(i);
case: panic("Invalid union tag type");
}
if v.data == nil || tag == 0 {
write_string(b, "null");
} else {
id := info.variants[tag-1].id;
marshal_arg(b, any{v.data, id});
}
case Type_Info_Enum:
return marshal_arg(b, any{v.data, info.base.id});
case Type_Info_Bit_Set:
is_bit_set_different_endian_to_platform :: proc(ti: ^runtime.Type_Info) -> bool {
if ti == nil {
return false;
}
t := runtime.type_info_base(ti);
#partial switch info in t.variant {
case runtime.Type_Info_Integer:
switch info.endianness {
case .Platform: return false;
case .Little: return ODIN_ENDIAN != "little";
case .Big: return ODIN_ENDIAN != "big";
}
}
return false;
}
bit_data: u64;
bit_size := u64(8*ti.size);
do_byte_swap := is_bit_set_different_endian_to_platform(info.underlying);
switch bit_size {
case 0: bit_data = 0;
case 8:
x := (^u8)(v.data)^;
bit_data = u64(x);
case 16:
x := (^u16)(v.data)^;
if do_byte_swap {
x = bits.byte_swap(x);
}
bit_data = u64(x);
case 32:
x := (^u32)(v.data)^;
if do_byte_swap {
x = bits.byte_swap(x);
}
bit_data = u64(x);
case 64:
x := (^u64)(v.data)^;
if do_byte_swap {
x = bits.byte_swap(x);
}
bit_data = u64(x);
case: panic("unknown bit_size size");
}
write_u64(b, bit_data);
return .Unsupported_Type;
}
return .None;
}
+459
View File
@@ -0,0 +1,459 @@
package json
import "core:mem"
import "core:unicode/utf8"
import "core:strconv"
Parser :: struct {
tok: Tokenizer,
prev_token: Token,
curr_token: Token,
spec: Specification,
allocator: mem.Allocator,
unmarshal_data: any,
parse_integers: bool,
}
make_parser :: proc(data: []byte, spec := Specification.JSON, parse_integers := false, allocator := context.allocator) -> Parser {
p: Parser;
p.tok = make_tokenizer(data, spec, parse_integers);
p.spec = spec;
p.allocator = allocator;
assert(p.allocator.procedure != nil);
advance_token(&p);
return p;
}
parse :: proc(data: []byte, spec := Specification.JSON, parse_integers := false, allocator := context.allocator) -> (Value, Error) {
context.allocator = allocator;
p := make_parser(data, spec, parse_integers, allocator);
if p.spec == Specification.JSON5 {
return parse_value(&p);
}
return parse_object(&p);
}
token_end_pos :: proc(tok: Token) -> Pos {
end := tok.pos;
end.offset += len(tok.text);
return end;
}
advance_token :: proc(p: ^Parser) -> (Token, Error) {
err: Error;
p.prev_token = p.curr_token;
p.curr_token, err = get_token(&p.tok);
return p.prev_token, err;
}
allow_token :: proc(p: ^Parser, kind: Token_Kind) -> bool {
if p.curr_token.kind == kind {
advance_token(p);
return true;
}
return false;
}
expect_token :: proc(p: ^Parser, kind: Token_Kind) -> Error {
prev := p.curr_token;
advance_token(p);
if prev.kind == kind {
return .None;
}
return .Unexpected_Token;
}
parse_value :: proc(p: ^Parser) -> (value: Value, err: Error) {
value.pos = p.curr_token.pos;
defer value.end = token_end_pos(p.prev_token);
token := p.curr_token;
#partial switch token.kind {
case .Null:
value.value = Null{};
advance_token(p);
return;
case .False:
value.value = Boolean(false);
advance_token(p);
return;
case .True:
value.value = Boolean(true);
advance_token(p);
return;
case .Integer:
i, _ := strconv.parse_i64(token.text);
value.value = Integer(i);
advance_token(p);
return;
case .Float:
f, _ := strconv.parse_f64(token.text);
value.value = Float(f);
advance_token(p);
return;
case .String:
value.value = String(unquote_string(token, p.spec, p.allocator));
advance_token(p);
return;
case .Open_Brace:
return parse_object(p);
case .Open_Bracket:
return parse_array(p);
case:
if p.spec == Specification.JSON5 {
#partial switch token.kind {
case .Infinity:
inf: u64 = 0x7ff0000000000000;
if token.text[0] == '-' {
inf = 0xfff0000000000000;
}
value.value = transmute(f64)inf;
advance_token(p);
return;
case .NaN:
nan: u64 = 0x7ff7ffffffffffff;
if token.text[0] == '-' {
nan = 0xfff7ffffffffffff;
}
value.value = transmute(f64)nan;
advance_token(p);
return;
}
}
}
err = .Unexpected_Token;
advance_token(p);
return;
}
parse_array :: proc(p: ^Parser) -> (value: Value, err: Error) {
value.pos = p.curr_token.pos;
defer value.end = token_end_pos(p.prev_token);
if err = expect_token(p, .Open_Bracket); err != .None {
return;
}
array: Array;
array.allocator = p.allocator;
defer if err != .None {
for elem in array {
destroy_value(elem);
}
delete(array);
}
for p.curr_token.kind != .Close_Bracket {
elem, elem_err := parse_value(p);
if elem_err != .None {
err = elem_err;
return;
}
append(&array, elem);
// Disallow trailing commas for the time being
if allow_token(p, .Comma) {
continue;
} else {
break;
}
}
if err = expect_token(p, .Close_Bracket); err != .None {
return;
}
value.value = array;
return;
}
clone_string :: proc(s: string, allocator: mem.Allocator) -> string {
n := len(s);
b := make([]byte, n+1, allocator);
copy(b, s);
b[n] = 0;
return string(b[:n]);
}
parse_object_key :: proc(p: ^Parser) -> (key: string, err: Error) {
tok := p.curr_token;
if p.spec == Specification.JSON5 {
if tok.kind == .String {
expect_token(p, .String);
key = unquote_string(tok, p.spec, p.allocator);
return;
} else if tok.kind == .Ident {
expect_token(p, .Ident);
key = clone_string(tok.text, p.allocator);
return;
}
}
if tok_err := expect_token(p, .String); tok_err != .None {
err = .Expected_String_For_Object_Key;
return;
}
key = unquote_string(tok, p.spec, p.allocator);
return;
}
parse_object :: proc(p: ^Parser) -> (value: Value, err: Error) {
value.pos = p.curr_token.pos;
defer value.end = token_end_pos(p.prev_token);
if err = expect_token(p, .Open_Brace); err != .None {
value.pos = p.curr_token.pos;
return;
}
obj: Object;
obj.allocator = p.allocator;
defer if err != .None {
for key, elem in obj {
delete(key, p.allocator);
destroy_value(elem);
}
delete(obj);
}
for p.curr_token.kind != .Close_Brace {
key: string;
key, err = parse_object_key(p);
if err != .None {
delete(key, p.allocator);
value.pos = p.curr_token.pos;
return;
}
if colon_err := expect_token(p, .Colon); colon_err != .None {
err = .Expected_Colon_After_Key;
value.pos = p.curr_token.pos;
return;
}
elem, elem_err := parse_value(p);
if elem_err != .None {
err = elem_err;
value.pos = p.curr_token.pos;
return;
}
if key in obj {
err = .Duplicate_Object_Key;
value.pos = p.curr_token.pos;
delete(key, p.allocator);
return;
}
obj[key] = elem;
if p.spec == Specification.JSON5 {
// Allow trailing commas
if allow_token(p, .Comma) {
continue;
}
} else {
// Disallow trailing commas
if allow_token(p, .Comma) {
continue;
} else {
break;
}
}
}
if err = expect_token(p, .Close_Brace); err != .None {
value.pos = p.curr_token.pos;
return;
}
value.value = obj;
return;
}
// IMPORTANT NOTE(bill): unquote_string assumes a mostly valid string
unquote_string :: proc(token: Token, spec: Specification, allocator := context.allocator) -> string {
get_u2_rune :: proc(s: string) -> rune {
if len(s) < 4 || s[0] != '\\' || s[1] != 'x' {
return -1;
}
r: rune;
for c in s[2:4] {
x: rune;
switch c {
case '0'..'9': x = c - '0';
case 'a'..'f': x = c - 'a' + 10;
case 'A'..'F': x = c - 'A' + 10;
case: return -1;
}
r = r*16 + x;
}
return r;
}
get_u4_rune :: proc(s: string) -> rune {
if len(s) < 6 || s[0] != '\\' || s[1] != 'u' {
return -1;
}
r: rune;
for c in s[2:6] {
x: rune;
switch c {
case '0'..'9': x = c - '0';
case 'a'..'f': x = c - 'a' + 10;
case 'A'..'F': x = c - 'A' + 10;
case: return -1;
}
r = r*16 + x;
}
return r;
}
if token.kind != .String {
return "";
}
s := token.text;
if len(s) <= 2 {
return "";
}
quote := s[0];
if s[0] != s[len(s)-1] {
// Invalid string
return "";
}
s = s[1:len(s)-1];
i := 0;
for i < len(s) {
c := s[i];
if c == '\\' || c == quote || c < ' ' {
break;
}
if c < utf8.RUNE_SELF {
i += 1;
continue;
}
r, w := utf8.decode_rune_in_string(s);
if r == utf8.RUNE_ERROR && w == 1 {
break;
}
i += w;
}
if i == len(s) {
return clone_string(s, allocator);
}
b := make([]byte, len(s) + 2*utf8.UTF_MAX, allocator);
w := copy(b, s[0:i]);
loop: for i < len(s) {
c := s[i];
switch {
case c == '\\':
i += 1;
if i >= len(s) {
break loop;
}
switch s[i] {
case: break loop;
case '"', '\'', '\\', '/':
b[w] = s[i];
i += 1;
w += 1;
case 'b':
b[w] = '\b';
i += 1;
w += 1;
case 'f':
b[w] = '\f';
i += 1;
w += 1;
case 'r':
b[w] = '\r';
i += 1;
w += 1;
case 't':
b[w] = '\t';
i += 1;
w += 1;
case 'n':
b[w] = '\n';
i += 1;
w += 1;
case 'u':
i -= 1; // Include the \u in the check for sanity sake
r := get_u4_rune(s[i:]);
if r < 0 {
break loop;
}
i += 6;
buf, buf_width := utf8.encode_rune(r);
copy(b[w:], buf[:buf_width]);
w += buf_width;
case '0':
if spec == Specification.JSON5 {
b[w] = '\x00';
i += 1;
w += 1;
} else {
break loop;
}
case 'v':
if spec == Specification.JSON5 {
b[w] = '\v';
i += 1;
w += 1;
} else {
break loop;
}
case 'x':
if spec == Specification.JSON5 {
i -= 1; // Include the \x in the check for sanity sake
r := get_u2_rune(s[i:]);
if r < 0 {
break loop;
}
i += 4;
buf, buf_width := utf8.encode_rune(r);
copy(b[w:], buf[:buf_width]);
w += buf_width;
} else {
break loop;
}
}
case c == quote, c < ' ':
break loop;
case c < utf8.RUNE_SELF:
b[w] = c;
i += 1;
w += 1;
case:
r, width := utf8.decode_rune_in_string(s[i:]);
i += width;
buf, buf_width := utf8.encode_rune(r);
assert(buf_width <= width);
copy(b[w:], buf[:buf_width]);
w += buf_width;
}
}
return string(b[:w]);
}
+484
View File
@@ -0,0 +1,484 @@
package json
import "core:unicode/utf8"
Token :: struct {
using pos: Pos,
kind: Token_Kind,
text: string,
}
Token_Kind :: enum {
Invalid,
EOF,
Null,
False,
True,
Infinity,
NaN,
Ident,
Integer,
Float,
String,
Colon,
Comma,
Open_Brace,
Close_Brace,
Open_Bracket,
Close_Bracket,
}
Tokenizer :: struct {
using pos: Pos,
data: []byte,
r: rune, // current rune
w: int, // current rune width in bytes
curr_line_offset: int,
spec: Specification,
parse_integers: bool,
}
make_tokenizer :: proc(data: []byte, spec := Specification.JSON, parse_integers := false) -> Tokenizer {
t := Tokenizer{pos = {line=1}, data = data, spec = spec, parse_integers = parse_integers};
next_rune(&t);
if t.r == utf8.RUNE_BOM {
next_rune(&t);
}
return t;
}
next_rune :: proc(t: ^Tokenizer) -> rune #no_bounds_check {
if t.offset >= len(t.data) {
return utf8.RUNE_EOF;
}
t.offset += t.w;
t.r, t.w = utf8.decode_rune(t.data[t.offset:]);
t.pos.column = t.offset - t.curr_line_offset;
return t.r;
}
get_token :: proc(t: ^Tokenizer) -> (token: Token, err: Error) {
skip_digits :: proc(t: ^Tokenizer) {
for t.offset < len(t.data) {
if '0' <= t.r && t.r <= '9' {
// Okay
} else {
return;
}
next_rune(t);
}
}
skip_hex_digits :: proc(t: ^Tokenizer) {
for t.offset < len(t.data) {
next_rune(t);
switch t.r {
case '0'..'9', 'a'..'f', 'A'..'F':
// Okay
case:
return;
}
}
}
scan_espace :: proc(t: ^Tokenizer) -> bool {
switch t.r {
case '"', '\'', '\\', '/', 'b', 'n', 'r', 't', 'f':
next_rune(t);
return true;
case 'u':
// Expect 4 hexadecimal digits
for i := 0; i < 4; i += 1 {
r := next_rune(t);
switch r {
case '0'..'9', 'a'..'f', 'A'..'F':
// Okay
case:
return false;
}
}
case:
// Ignore the next rune regardless
next_rune(t);
}
return false;
}
skip_whitespace :: proc(t: ^Tokenizer) -> rune {
loop: for t.offset < len(t.data) {
switch t.r {
case ' ', '\t', '\v', '\f', '\r':
next_rune(t);
case '\n':
t.line += 1;
t.curr_line_offset = t.offset;
t.pos.column = 1;
next_rune(t);
case:
if t.spec == .JSON5 {
switch t.r {
case 0x2028, 0x2029, 0xFEFF:
next_rune(t);
continue loop;
}
}
break loop;
}
}
return t.r;
}
skip_to_next_line :: proc(t: ^Tokenizer) {
for t.offset < len(t.data) {
r := next_rune(t);
if r == '\n' {
return;
}
}
}
skip_alphanum :: proc(t: ^Tokenizer) {
for t.offset < len(t.data) {
switch next_rune(t) {
case 'A'..'Z', 'a'..'z', '0'..'9', '_':
continue;
}
return;
}
}
skip_whitespace(t);
token.pos = t.pos;
token.kind = .Invalid;
curr_rune := t.r;
next_rune(t);
block: switch curr_rune {
case utf8.RUNE_ERROR:
err = .Illegal_Character;
case utf8.RUNE_EOF, '\x00':
token.kind = .EOF;
err = .EOF;
case 'A'..'Z', 'a'..'z', '_':
token.kind = .Ident;
skip_alphanum(t);
switch str := string(t.data[token.offset:t.offset]); str {
case "null": token.kind = .Null;
case "false": token.kind = .False;
case "true": token.kind = .True;
case:
if t.spec == .JSON5 {
switch str {
case "Infinity": token.kind = .Infinity;
case "NaN": token.kind = .NaN;
}
}
}
case '+':
err = .Illegal_Character;
if t.spec != .JSON5 {
break;
}
fallthrough;
case '-':
switch t.r {
case '0'..'9':
// Okay
case:
// Illegal use of +/-
err = .Illegal_Character;
if t.spec == .JSON5 {
if t.r == 'I' || t.r == 'N' {
skip_alphanum(t);
}
switch string(t.data[token.offset:t.offset]) {
case "-Infinity": token.kind = .Infinity;
case "-NaN": token.kind = .NaN;
}
}
break block;
}
fallthrough;
case '0'..'9':
token.kind = t.parse_integers ? .Integer : .Float;
if t.spec == .JSON5 { // Hexadecimal Numbers
if curr_rune == '0' && (t.r == 'x' || t.r == 'X') {
next_rune(t);
skip_hex_digits(t);
break;
}
}
skip_digits(t);
if t.r == '.' {
token.kind = .Float;
next_rune(t);
skip_digits(t);
}
if t.r == 'e' || t.r == 'E' {
switch r := next_rune(t); r {
case '+', '-':
next_rune(t);
}
skip_digits(t);
}
str := string(t.data[token.offset:t.offset]);
if !is_valid_number(str, t.spec) {
err = .Invalid_Number;
}
case '.':
err = .Illegal_Character;
if t.spec == .JSON5 { // Allow leading decimal point
skip_digits(t);
if t.r == 'e' || t.r == 'E' {
switch r := next_rune(t); r {
case '+', '-':
next_rune(t);
}
skip_digits(t);
}
str := string(t.data[token.offset:t.offset]);
if !is_valid_number(str, t.spec) {
err = .Invalid_Number;
}
}
case '\'':
err = .Illegal_Character;
if t.spec != .JSON5 {
break;
}
fallthrough;
case '"':
token.kind = .String;
quote := curr_rune;
for t.offset < len(t.data) {
r := t.r;
if r == '\n' || r < 0 {
err = .String_Not_Terminated;
break;
}
next_rune(t);
if r == quote {
break;
}
if r == '\\' {
scan_espace(t);
}
}
str := string(t.data[token.offset : t.offset]);
if !is_valid_string_literal(str, t.spec) {
err = .Invalid_String;
}
case ',': token.kind = .Comma;
case ':': token.kind = .Colon;
case '{': token.kind = .Open_Brace;
case '}': token.kind = .Close_Brace;
case '[': token.kind = .Open_Bracket;
case ']': token.kind = .Close_Bracket;
case '/':
err = .Illegal_Character;
if t.spec == .JSON5 {
switch t.r {
case '/':
// Single-line comments
skip_to_next_line(t);
return get_token(t);
case '*':
// None-nested multi-line comments
for t.offset < len(t.data) {
next_rune(t);
if t.r == '*' {
next_rune(t);
if t.r == '/' {
next_rune(t);
return get_token(t);
}
}
}
err = .EOF;
}
}
case: err = .Illegal_Character;
}
token.text = string(t.data[token.offset : t.offset]);
return;
}
is_valid_number :: proc(str: string, spec: Specification) -> bool {
s := str;
if s == "" {
return false;
}
if s[0] == '-' {
s = s[1:];
if s == "" {
return false;
}
} else if spec == .JSON5 {
if s[0] == '+' { // Allow positive sign
s = s[1:];
if s == "" {
return false;
}
}
}
switch s[0] {
case '0':
s = s[1:];
case '1'..'9':
s = s[1:];
for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
s = s[1:];
}
case '.':
if spec == .JSON5 { // Allow leading decimal point
s = s[1:];
} else {
return false;
}
case:
return false;
}
if spec == .JSON5 {
if len(s) == 1 && s[0] == '.' { // Allow trailing decimal point
return true;
}
}
if len(s) >= 2 && s[0] == '.' && '0' <= s[1] && s[1] <= '9' {
s = s[2:];
for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
s = s[1:];
}
}
if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') {
s = s[1:];
switch s[0] {
case '+', '-':
s = s[1:];
if s == "" {
return false;
}
}
for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
s = s[1:];
}
}
// The string should be empty now to be valid
return s == "";
}
is_valid_string_literal :: proc(str: string, spec: Specification) -> bool {
s := str;
if len(s) < 2 {
return false;
}
quote := s[0];
if s[0] != s[len(s)-1] {
return false;
}
if s[0] != '"' || s[len(s)-1] != '"' {
if spec == .JSON5 {
if s[0] != '\'' || s[len(s)-1] != '\'' {
return false;
}
} else {
return false;
}
}
s = s[1 : len(s)-1];
i := 0;
for i < len(s) {
c := s[i];
switch {
case c == '\\':
i += 1;
if i >= len(s) {
return false;
}
switch s[i] {
case '"', '\'', '\\', '/', 'b', 'n', 'r', 't', 'f':
i += 1;
case 'u':
if i >= len(s) {
return false;
}
hex := s[i+1:];
if len(hex) < 4 {
return false;
}
hex = hex[:4];
i += 5;
for j := 0; j < 4; j += 1 {
c2 := hex[j];
switch c2 {
case '0'..'9', 'a'..'z', 'A'..'Z':
// Okay
case:
return false;
}
}
case: return false;
}
case c == quote, c < ' ':
return false;
case c < utf8.RUNE_SELF:
i += 1;
case:
r, width := utf8.decode_rune_in_string(s[i:]);
if r == utf8.RUNE_ERROR && width == 1 {
return false;
}
i += width;
}
}
if i == len(s) {
return true;
}
return true;
}
+76
View File
@@ -0,0 +1,76 @@
package json
Specification :: enum {
JSON,
JSON5, // https://json5.org/
// MJSON, // http://bitsquid.blogspot.com/2009/09/json-configuration-data.html
}
Null :: distinct rawptr;
Integer :: i64;
Float :: f64;
Boolean :: bool;
String :: string;
Array :: distinct [dynamic]Value;
Object :: distinct map[string]Value;
Value :: struct {
pos, end: Pos,
value: union {
Null,
Integer,
Float,
Boolean,
String,
Array,
Object,
},
}
Pos :: struct {
offset: int,
line: int,
column: int,
}
Error :: enum {
None,
EOF, // Not necessarily an error
// Tokenizing Errors
Illegal_Character,
Invalid_Number,
String_Not_Terminated,
Invalid_String,
// Parsing Errors
Unexpected_Token,
Expected_String_For_Object_Key,
Duplicate_Object_Key,
Expected_Colon_After_Key,
}
destroy_value :: proc(value: Value) {
#partial switch v in value.value {
case Object:
for key, elem in v {
delete(key);
destroy_value(elem);
}
delete(v);
case Array:
for elem in v {
destroy_value(elem);
}
delete(v);
case String:
delete(v);
}
}
+122
View File
@@ -0,0 +1,122 @@
package json
import "core:mem"
// NOTE(bill): is_valid will not check for duplicate keys
is_valid :: proc(data: []byte, spec := Specification.JSON, parse_integers := false) -> bool {
p := make_parser(data, spec, parse_integers, mem.nil_allocator());
if p.spec == Specification.JSON5 {
return validate_value(&p);
}
return validate_object(&p);
}
validate_object_key :: proc(p: ^Parser) -> bool {
tok := p.curr_token;
if p.spec == Specification.JSON5 {
if tok.kind == .String {
expect_token(p, .String);
return true;
} else if tok.kind == .Ident {
expect_token(p, .Ident);
return true;
}
}
err := expect_token(p, .String);
return err == Error.None;
}
validate_object :: proc(p: ^Parser) -> bool {
if err := expect_token(p, .Open_Brace); err != Error.None {
return false;
}
for p.curr_token.kind != .Close_Brace {
if !validate_object_key(p) {
return false;
}
if colon_err := expect_token(p, .Colon); colon_err != Error.None {
return false;
}
if !validate_value(p) {
return false;
}
if p.spec == Specification.JSON5 {
// Allow trailing commas
if allow_token(p, .Comma) {
continue;
}
} else {
// Disallow trailing commas
if allow_token(p, .Comma) {
continue;
} else {
break;
}
}
}
if err := expect_token(p, .Close_Brace); err != Error.None {
return false;
}
return true;
}
validate_array :: proc(p: ^Parser) -> bool {
if err := expect_token(p, .Open_Bracket); err != Error.None {
return false;
}
for p.curr_token.kind != .Close_Bracket {
if !validate_value(p) {
return false;
}
// Disallow trailing commas for the time being
if allow_token(p, .Comma) {
continue;
} else {
break;
}
}
if err := expect_token(p, .Close_Bracket); err != Error.None {
return false;
}
return true;
}
validate_value :: proc(p: ^Parser) -> bool {
token := p.curr_token;
#partial switch token.kind {
case .Null, .False, .True:
advance_token(p);
return true;
case .Integer, .Float:
advance_token(p);
return true;
case .String:
advance_token(p);
return is_valid_string_literal(token.text, p.spec);
case .Open_Brace:
return validate_object(p);
case .Open_Bracket:
return validate_array(p);
case:
if p.spec == Specification.JSON5 {
#partial switch token.kind {
case .Infinity, .NaN:
advance_token(p);
return true;
}
}
}
return false;
}
-1196
View File
File diff suppressed because it is too large Load Diff
+2089
View File
File diff suppressed because it is too large Load Diff
+7 -204
View File
@@ -1,218 +1,21 @@
import "core:mem.odin"
package hash
adler32 :: proc(data: []u8) -> u32 {
ADLER_CONST :: 65521;
a, b: u32 = 1, 0;
for x in data {
a = (a + u32(x)) % ADLER_CONST;
b = (b + a) % ADLER_CONST;
}
return (b << 16) | a;
}
crc32 :: proc(data: []u8) -> u32 {
result := ~u32(0);
crc32 :: proc(data: []byte, seed := u32(0)) -> u32 #no_bounds_check {
result := ~u32(seed);
for b in data {
result = result>>8 ~ _crc32_table[(result ~ u32(b)) & 0xff];
}
return ~result;
}
crc64 :: proc(data: []u8) -> u64 {
result := ~u64(0);
crc64 :: proc(data: []byte, seed := u32(0)) -> u64 #no_bounds_check {
result := ~u64(seed);
for b in data {
result = result>>8 ~ _crc64_table[(result ~ u64(b)) & 0xff];
}
return ~result;
}
fnv32 :: proc(data: []u8) -> u32 {
h: u32 = 0x811c9dc5;
for b in data {
h = (h * 0x01000193) ~ u32(b);
}
return h;
}
fnv64 :: proc(data: []u8) -> u64 {
h: u64 = 0xcbf29ce484222325;
for b in data {
h = (h * 0x100000001b3) ~ u64(b);
}
return h;
}
fnv32a :: proc(data: []u8) -> u32 {
h: u32 = 0x811c9dc5;
for b in data {
h = (h ~ u32(b)) * 0x01000193;
}
return h;
}
fnv64a :: proc(data: []u8) -> u64 {
h: u64 = 0xcbf29ce484222325;
for b in data {
h = (h ~ u64(b)) * 0x100000001b3;
}
return h;
}
murmur32 :: proc(data: []u8) -> u32 {
c1_32: u32 : 0xcc9e2d51;
c2_32: u32 : 0x1b873593;
h1: u32 = 0;
nblocks := len(data)/4;
p := &data[0];
p1 := p + 4*nblocks;
for ; p < p1; p += 4 {
k1 := (cast(^u32)p)^;
k1 *= c1_32;
k1 = (k1 << 15) | (k1 >> 17);
k1 *= c2_32;
h1 ~= k1;
h1 = (h1 << 13) | (h1 >> 19);
h1 = h1*5 + 0xe6546b64;
}
tail := data[nblocks*4 ..];
k1: u32;
switch len(tail)&3 {
case 3:
k1 ~= u32(tail[2]) << 16;
fallthrough;
case 2:
k1 ~= u32(tail[2]) << 8;
fallthrough;
case 1:
k1 ~= u32(tail[0]);
k1 *= c1_32;
k1 = (k1 << 15) | (k1 >> 17) ;
k1 *= c2_32;
h1 ~= k1;
}
h1 ~= u32(len(data));
h1 ~= h1 >> 16;
h1 *= 0x85ebca6b;
h1 ~= h1 >> 13;
h1 *= 0xc2b2ae35;
h1 ~= h1 >> 16;
return h1;
}
murmur64 :: proc(data: []u8) -> u64 {
SEED :: 0x9747b28c;
when size_of(int) == 8 {
m :: 0xc6a4a7935bd1e995;
r :: 47;
h: u64 = SEED ~ (u64(len(data)) * m);
data64 := mem.slice_ptr(cast(^u64)&data[0], len(data)/size_of(u64));
for _, i in data64 {
k := data64[i];
k *= m;
k ~= k>>r;
k *= m;
h ~= k;
h *= m;
}
switch len(data)&7 {
case 7: h ~= u64(data[6]) << 48; fallthrough;
case 6: h ~= u64(data[5]) << 40; fallthrough;
case 5: h ~= u64(data[4]) << 32; fallthrough;
case 4: h ~= u64(data[3]) << 24; fallthrough;
case 3: h ~= u64(data[2]) << 16; fallthrough;
case 2: h ~= u64(data[1]) << 8; fallthrough;
case 1:
h ~= u64(data[0]);
h *= m;
}
h ~= h>>r;
h *= m;
h ~= h>>r;
return h;
} else {
m :: 0x5bd1e995;
r :: 24;
h1 := u32(SEED) ~ u32(len(data));
h2 := u32(SEED) >> 32;
data32 := mem.slice_ptr(cast(^u32)&data[0], len(data)/size_of(u32));
len := len(data);
i := 0;
for len >= 8 {
k1, k2: u32;
k1 = data32[i]; i += 1;
k1 *= m;
k1 ~= k1>>r;
k1 *= m;
h1 *= m;
h1 ~= k1;
len -= 4;
k2 = data32[i]; i += 1;
k2 *= m;
k2 ~= k2>>r;
k2 *= m;
h2 *= m;
h2 ~= k2;
len -= 4;
}
if len >= 4 {
k1: u32;
k1 = data32[i]; i += 1;
k1 *= m;
k1 ~= k1>>r;
k1 *= m;
h1 *= m;
h1 ~= k1;
len -= 4;
}
// TODO(bill): Fix this
#no_bounds_check data8 := slice_to_bytes(data32[i..])[..3];
switch len {
case 3:
h2 ~= u32(data8[2]) << 16;
fallthrough;
case 2:
h2 ~= u32(data8[1]) << 8;
fallthrough;
case 1:
h2 ~= u32(data8[0]);
h2 *= m;
}
h1 ~= h2>>18;
h1 *= m;
h2 ~= h1>>22;
h2 *= m;
h1 ~= h2>>17;
h1 *= m;
h2 ~= h1>>19;
h2 *= m;
return u64(h1)<<32 | u64(h2);
}
}
_crc32_table := [256]u32{
@private _crc32_table := [256]u32{
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
@@ -278,7 +81,7 @@ _crc32_table := [256]u32{
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
};
_crc64_table := [256]u64{
@private _crc64_table := [256]u64{
0x0000000000000000, 0x42f0e1eba9ea3693, 0x85e1c3d753d46d26, 0xc711223cfa3e5bb5,
0x493366450e42ecdf, 0x0bc387aea7a8da4c, 0xccd2a5925d9681f9, 0x8e224479f47cb76a,
0x9266cc8a1c85d9be, 0xd0962d61b56fef2d, 0x17870f5d4f51b498, 0x5577eeb6e6bb820b,
+229
View File
@@ -0,0 +1,229 @@
package hash
import "core:mem"
adler32 :: proc(data: []byte, seed := u32(1)) -> u32 {
ADLER_CONST :: 65521;
a, b: u32 = seed & 0xFFFF, seed >> 16;
for x in data {
a = (a + u32(x)) % ADLER_CONST;
b = (b + a) % ADLER_CONST;
}
return (b << 16) | a;
}
djb2 :: proc(data: []byte) -> u32 {
hash: u32 = 5381;
for b in data {
hash = (hash << 5) + hash + u32(b); // hash * 33 + u32(b)
}
return hash;
}
fnv32 :: proc(data: []byte) -> u32 {
h: u32 = 0x811c9dc5;
for b in data {
h = (h * 0x01000193) ~ u32(b);
}
return h;
}
fnv64 :: proc(data: []byte) -> u64 {
h: u64 = 0xcbf29ce484222325;
for b in data {
h = (h * 0x100000001b3) ~ u64(b);
}
return h;
}
fnv32a :: proc(data: []byte) -> u32 {
h: u32 = 0x811c9dc5;
for b in data {
h = (h ~ u32(b)) * 0x01000193;
}
return h;
}
fnv64a :: proc(data: []byte) -> u64 {
h: u64 = 0xcbf29ce484222325;
for b in data {
h = (h ~ u64(b)) * 0x100000001b3;
}
return h;
}
jenkins :: proc(data: []byte) -> u32 {
hash: u32 = 0;
for b in data {
hash += u32(b);
hash += hash << 10;
hash ~= hash >> 6;
}
hash += hash << 3;
hash ~= hash >> 11;
hash += hash << 15;
return hash;
}
murmur32 :: proc(data: []byte) -> u32 {
c1_32: u32 : 0xcc9e2d51;
c2_32: u32 : 0x1b873593;
h1: u32 = 0;
nblocks := len(data)/4;
p := raw_data(data);
p1 := mem.ptr_offset(p, 4*nblocks);
for ; p < p1; p = mem.ptr_offset(p, 4) {
k1 := (cast(^u32)p)^;
k1 *= c1_32;
k1 = (k1 << 15) | (k1 >> 17);
k1 *= c2_32;
h1 ~= k1;
h1 = (h1 << 13) | (h1 >> 19);
h1 = h1*5 + 0xe6546b64;
}
tail := data[nblocks*4:];
k1: u32;
switch len(tail)&3 {
case 3:
k1 ~= u32(tail[2]) << 16;
fallthrough;
case 2:
k1 ~= u32(tail[2]) << 8;
fallthrough;
case 1:
k1 ~= u32(tail[0]);
k1 *= c1_32;
k1 = (k1 << 15) | (k1 >> 17) ;
k1 *= c2_32;
h1 ~= k1;
}
h1 ~= u32(len(data));
h1 ~= h1 >> 16;
h1 *= 0x85ebca6b;
h1 ~= h1 >> 13;
h1 *= 0xc2b2ae35;
h1 ~= h1 >> 16;
return h1;
}
murmur64 :: proc(data: []byte) -> u64 {
SEED :: 0x9747b28c;
when size_of(int) == 8 {
m :: 0xc6a4a7935bd1e995;
r :: 47;
h: u64 = SEED ~ (u64(len(data)) * m);
data64 := mem.slice_ptr(cast(^u64)raw_data(data), len(data)/size_of(u64));
for _, i in data64 {
k := data64[i];
k *= m;
k ~= k>>r;
k *= m;
h ~= k;
h *= m;
}
switch len(data)&7 {
case 7: h ~= u64(data[6]) << 48; fallthrough;
case 6: h ~= u64(data[5]) << 40; fallthrough;
case 5: h ~= u64(data[4]) << 32; fallthrough;
case 4: h ~= u64(data[3]) << 24; fallthrough;
case 3: h ~= u64(data[2]) << 16; fallthrough;
case 2: h ~= u64(data[1]) << 8; fallthrough;
case 1:
h ~= u64(data[0]);
h *= m;
}
h ~= h>>r;
h *= m;
h ~= h>>r;
return h;
} else {
m :: 0x5bd1e995;
r :: 24;
h1 := u32(SEED) ~ u32(len(data));
h2 := u32(SEED) >> 32;
data32 := mem.slice_ptr(cast(^u32)raw_data(data), len(data)/size_of(u32));
len := len(data);
i := 0;
for len >= 8 {
k1, k2: u32;
k1 = data32[i]; i += 1;
k1 *= m;
k1 ~= k1>>r;
k1 *= m;
h1 *= m;
h1 ~= k1;
len -= 4;
k2 = data32[i]; i += 1;
k2 *= m;
k2 ~= k2>>r;
k2 *= m;
h2 *= m;
h2 ~= k2;
len -= 4;
}
if len >= 4 {
k1: u32;
k1 = data32[i]; i += 1;
k1 *= m;
k1 ~= k1>>r;
k1 *= m;
h1 *= m;
h1 ~= k1;
len -= 4;
}
// TODO(bill): Fix this
#no_bounds_check data8 := mem.slice_to_bytes(data32[i:])[:3];
switch len {
case 3:
h2 ~= u32(data8[2]) << 16;
fallthrough;
case 2:
h2 ~= u32(data8[1]) << 8;
fallthrough;
case 1:
h2 ~= u32(data8[0]);
h2 *= m;
}
h1 ~= h2>>18;
h1 *= m;
h2 ~= h1>>22;
h2 *= m;
h1 ~= h2>>17;
h1 *= m;
h2 ~= h1>>19;
h2 *= m;
return u64(h1)<<32 | u64(h2);
}
}
sdbm :: proc(data: []byte) -> u32 {
hash: u32 = 0;
for b in data {
hash = u32(b) + (hash<<6) + (hash<<16) - hash;
}
return hash;
}
+40
View File
@@ -0,0 +1,40 @@
package hash
ginger_hash8 :: proc(x: u8) -> u8 {
h := x * 251;
h += ~(x << 3);
h ~= (x >> 1);
h += ~(x << 7);
h ~= (x >> 6);
h += (x << 2);
return h;
}
ginger_hash16 :: proc(x: u16) -> u16 {
z := (x << 8) | (x >> 8);
h := z;
h += ~(z << 5);
h ~= (z >> 2);
h += ~(z << 13);
h ~= (z >> 10);
h += ~(z << 4);
h = (h << 10) | (h >> 10);
return h;
}
ginger8 :: proc(data: []byte) -> u8 {
h := ginger_hash8(0);
for b in data {
h ~= ginger_hash8(b);
}
return h;
}
ginger16 :: proc(data: []byte) -> u16 {
h := ginger_hash16(0);
for b in data {
h ~= ginger_hash16(u16(b));
}
return h;
}
+163
View File
@@ -0,0 +1,163 @@
// This is purely for documentation
//+ignore
package intrinsics
// Types
simd_vector :: proc($N: int, $T: typeid) -> type/#simd[N]T
soa_struct :: proc($N: int, $T: typeid) -> type/#soa[N]T
// Volatile
volatile_load :: proc(dst: ^$T) -> T ---
volatile_store :: proc(dst: ^$T, val: T) -> T ---
// Trapping
debug_trap :: proc() ---
trap :: proc() -> ! ---
// Atomics
atomic_fence :: proc() ---
atomic_fence_acq :: proc() ---
atomic_fence_rel :: proc() ---
atomic_fence_acqrel :: proc() ---
atomic_store :: proc(dst: ^$T, val: T) ---
atomic_store_rel :: proc(dst: ^$T, val: T) ---
atomic_store_relaxed :: proc(dst: ^$T, val: T) ---
atomic_store_unordered :: proc(dst: ^$T, val: T) ---
atomic_load :: proc(dst: ^$T) -> T ---
atomic_load_acq :: proc(dst: ^$T) -> T ---
atomic_load_relaxed :: proc(dst: ^$T) -> T ---
atomic_load_unordered :: proc(dst: ^$T) -> T ---
atomic_add :: proc(dst; ^$T, val: T) -> T ---
atomic_add_acq :: proc(dst; ^$T, val: T) -> T ---
atomic_add_rel :: proc(dst; ^$T, val: T) -> T ---
atomic_add_acqrel :: proc(dst; ^$T, val: T) -> T ---
atomic_add_relaxed :: proc(dst; ^$T, val: T) -> T ---
atomic_sub :: proc(dst; ^$T, val: T) -> T ---
atomic_sub_acq :: proc(dst; ^$T, val: T) -> T ---
atomic_sub_rel :: proc(dst; ^$T, val: T) -> T ---
atomic_sub_acqrel :: proc(dst; ^$T, val: T) -> T ---
atomic_sub_relaxed :: proc(dst; ^$T, val: T) -> T ---
atomic_and :: proc(dst; ^$T, val: T) -> T ---
atomic_and_acq :: proc(dst; ^$T, val: T) -> T ---
atomic_and_rel :: proc(dst; ^$T, val: T) -> T ---
atomic_and_acqrel :: proc(dst; ^$T, val: T) -> T ---
atomic_and_relaxed :: proc(dst; ^$T, val: T) -> T ---
atomic_nand :: proc(dst; ^$T, val: T) -> T ---
atomic_nand_acq :: proc(dst; ^$T, val: T) -> T ---
atomic_nand_rel :: proc(dst; ^$T, val: T) -> T ---
atomic_nand_acqrel :: proc(dst; ^$T, val: T) -> T ---
atomic_nand_relaxed :: proc(dst; ^$T, val: T) -> T ---
atomic_or :: proc(dst; ^$T, val: T) -> T ---
atomic_or_acq :: proc(dst; ^$T, val: T) -> T ---
atomic_or_rel :: proc(dst; ^$T, val: T) -> T ---
atomic_or_acqrel :: proc(dst; ^$T, val: T) -> T ---
atomic_or_relaxed :: proc(dst; ^$T, val: T) -> T ---
atomic_xor :: proc(dst; ^$T, val: T) -> T ---
atomic_xor_acq :: proc(dst; ^$T, val: T) -> T ---
atomic_xor_rel :: proc(dst; ^$T, val: T) -> T ---
atomic_xor_acqrel :: proc(dst; ^$T, val: T) -> T ---
atomic_xor_relaxed :: proc(dst; ^$T, val: T) -> T ---
atomic_xchg :: proc(dst; ^$T, val: T) -> T ---
atomic_xchg_acq :: proc(dst; ^$T, val: T) -> T ---
atomic_xchg_rel :: proc(dst; ^$T, val: T) -> T ---
atomic_xchg_acqrel :: proc(dst; ^$T, val: T) -> T ---
atomic_xchg_relaxed :: proc(dst; ^$T, val: T) -> T ---
atomic_cxchg :: proc(dst: ^$T, old, new: T) -> (T, /*option*/bool) ---
atomic_cxchg_acq :: proc(dst: ^$T, old, new: T) -> (T, /*option*/bool) ---
atomic_cxchg_rel :: proc(dst: ^$T, old, new: T) -> (T, /*option*/bool) ---
atomic_cxchg_acqrel :: proc(dst: ^$T, old, new: T) -> (T, /*option*/bool) ---
atomic_cxchg_relaxed :: proc(dst: ^$T, old, new: T) -> (T, /*option*/bool) ---
atomic_cxchg_failrelaxed :: proc(dst: ^$T, old, new: T) -> (T, /*option*/bool) ---
atomic_cxchg_failacq :: proc(dst: ^$T, old, new: T) -> (T, /*option*/bool) ---
atomic_cxchg_acq_failrelaxed :: proc(dst: ^$T, old, new: T) -> (T, /*option*/bool) ---
atomic_cxchg_acqrel_failrelaxed :: proc(dst: ^$T, old, new: T) -> (T, /*option*/bool) ---
atomic_cxchgweak :: proc(dst: ^$T, old, new: T) -> (T, /*option*/bool) ---
atomic_cxchgweak_acq :: proc(dst: ^$T, old, new: T) -> (T, /*option*/bool) ---
atomic_cxchgweak_rel :: proc(dst: ^$T, old, new: T) -> (T, /*option*/bool) ---
atomic_cxchgweak_acqrel :: proc(dst: ^$T, old, new: T) -> (T, /*option*/bool) ---
atomic_cxchgweak_relaxed :: proc(dst: ^$T, old, new: T) -> (T, /*option*/bool) ---
atomic_cxchgweak_failrelaxed :: proc(dst: ^$T, old, new: T) -> (T, /*option*/bool) ---
atomic_cxchgweak_failacq :: proc(dst: ^$T, old, new: T) -> (T, /*option*/bool) ---
atomic_cxchgweak_acq_failrelaxed :: proc(dst: ^$T, old, new: T) -> (T, /*option*/bool) ---
atomic_cxchgweak_acqrel_failrelaxed :: proc(dst: ^$T, old, new: T) -> (T, /*option*/bool) ---
// Instructions
alloca :: proc(size, align: int) -> ^u8 ---
cpu_relax :: proc() ---
read_cycle_counter :: proc() -> i64 ---
// Compiler Hints
expect :: proc(val, expected_val: T) -> T ---
// Constant type tests
type_base_type :: proc($T: typeid) -> type ---
type_core_type :: proc($T: typeid) -> type ---
type_elem_type :: proc($T: typeid) -> type ---
type_is_boolean :: proc($T: typeid) -> bool ---
type_is_integer :: proc($T: typeid) -> bool ---
type_is_rune :: proc($T: typeid) -> bool ---
type_is_float :: proc($T: typeid) -> bool ---
type_is_complex :: proc($T: typeid) -> bool ---
type_is_quaternion :: proc($T: typeid) -> bool ---
type_is_string :: proc($T: typeid) -> bool ---
type_is_typeid :: proc($T: typeid) -> bool ---
type_is_any :: proc($T: typeid) -> bool ---
type_is_endian_little :: proc($T: typeid) -> bool ---
type_is_endian_big :: proc($T: typeid) -> bool ---
type_is_unsigned :: proc($T: typeid) -> bool ---
type_is_numeric :: proc($T: typeid) -> bool ---
type_is_ordered :: proc($T: typeid) -> bool ---
type_is_ordered_numeric :: proc($T: typeid) -> bool ---
type_is_indexable :: proc($T: typeid) -> bool ---
type_is_sliceable :: proc($T: typeid) -> bool ---
type_is_comparable :: proc($T: typeid) -> bool ---
type_is_simple_compare :: proc($T: typeid) -> bool --- // easily compared using memcmp (== and !=)
type_is_dereferenceable :: proc($T: typeid) -> bool ---
type_is_valid_map_key :: proc($T: typeid) -> bool ---
type_is_named :: proc($T: typeid) -> bool ---
type_is_pointer :: proc($T: typeid) -> bool ---
type_is_array :: proc($T: typeid) -> bool ---
type_is_enumerated_array :: proc($T: typeid) -> bool ---
type_is_slice :: proc($T: typeid) -> bool ---
type_is_dynamic_array :: proc($T: typeid) -> bool ---
type_is_map :: proc($T: typeid) -> bool ---
type_is_struct :: proc($T: typeid) -> bool ---
type_is_union :: proc($T: typeid) -> bool ---
type_is_enum :: proc($T: typeid) -> bool ---
type_is_proc :: proc($T: typeid) -> bool ---
type_is_bit_set :: proc($T: typeid) -> bool ---
type_is_simd_vector :: proc($T: typeid) -> bool ---
type_has_nil :: proc($T: typeid) -> bool ---
type_is_specialization_of :: proc($T, $S: typeid) -> bool ---
type_has_field :: proc($T: typeid, $name: string) -> bool ---
type_proc_parameter_count :: proc($T: typeid) -> int where type_is_proc(T) ---
type_proc_return_count :: proc($T: typeid) -> int where type_is_proc(T) ---
type_proc_parameter_type :: proc($T: typeid, index: int) -> typeid where type_is_proc(T) ---
type_proc_return_type :: proc($T: typeid, index: int) -> typeid where type_is_proc(T) ---
type_polymorphic_record_parameter_count :: proc($T: typeid) -> typeid ---
type_polymorphic_record_parameter_value :: proc($T: typeid, index: int) -> $V ---
type_field_index_of :: proc($T: typeid, $name: string) -> uintptr ---
type_equal_proc :: proc($T: typeid) -> (equal: proc "contextless" (rawptr, rawptr) -> bool) ---
type_hasher_proc :: proc($T: typeid) -> (hasher: proc "contextless" (data: rawptr, seed: uintptr) -> uintptr) ---
+194
View File
@@ -0,0 +1,194 @@
package io
to_reader :: proc(s: Stream) -> (r: Reader, ok: bool = true) {
r.stream = s;
if s.stream_vtable == nil || s.impl_read == nil {
ok = false;
}
return;
}
to_writer :: proc(s: Stream) -> (w: Writer, ok: bool = true) {
w.stream = s;
if s.stream_vtable == nil || s.impl_write == nil {
ok = false;
}
return;
}
to_closer :: proc(s: Stream) -> (c: Closer, ok: bool = true) {
c.stream = s;
if s.stream_vtable == nil || s.impl_close == nil {
ok = false;
}
return;
}
to_flusher :: proc(s: Stream) -> (f: Flusher, ok: bool = true) {
f.stream = s;
if s.stream_vtable == nil || s.impl_flush == nil {
ok = false;
}
return;
}
to_seeker :: proc(s: Stream) -> (seeker: Seeker, ok: bool = true) {
seeker.stream = s;
if s.stream_vtable == nil || s.impl_seek == nil {
ok = false;
}
return;
}
to_read_writer :: proc(s: Stream) -> (r: Read_Writer, ok: bool = true) {
r.stream = s;
if s.stream_vtable == nil || s.impl_read == nil || s.impl_write == nil {
ok = false;
}
return;
}
to_read_closer :: proc(s: Stream) -> (r: Read_Closer, ok: bool = true) {
r.stream = s;
if s.stream_vtable == nil || s.impl_read == nil || s.impl_close == nil {
ok = false;
}
return;
}
to_read_write_closer :: proc(s: Stream) -> (r: Read_Write_Closer, ok: bool = true) {
r.stream = s;
if s.stream_vtable == nil || s.impl_read == nil || s.impl_write == nil || s.impl_close == nil {
ok = false;
}
return;
}
to_read_write_seeker :: proc(s: Stream) -> (r: Read_Write_Seeker, ok: bool = true) {
r.stream = s;
if s.stream_vtable == nil || s.impl_read == nil || s.impl_write == nil || s.impl_seek == nil {
ok = false;
}
return;
}
to_write_flusher :: proc(s: Stream) -> (w: Write_Flusher, ok: bool = true) {
w.stream = s;
if s.stream_vtable == nil || s.impl_write == nil || s.impl_flush == nil {
ok = false;
}
return;
}
to_write_flush_closer :: proc(s: Stream) -> (w: Write_Flush_Closer, ok: bool = true) {
w.stream = s;
if s.stream_vtable == nil || s.impl_write == nil || s.impl_flush == nil || s.impl_close == nil {
ok = false;
}
return;
}
to_reader_at :: proc(s: Stream) -> (r: Reader_At, ok: bool = true) {
r.stream = s;
if s.stream_vtable == nil || s.impl_read_at == nil {
ok = false;
}
return;
}
to_writer_at :: proc(s: Stream) -> (w: Writer_At, ok: bool = true) {
w.stream = s;
if s.stream_vtable == nil || s.impl_write_at == nil {
ok = false;
}
return;
}
to_reader_from :: proc(s: Stream) -> (r: Reader_From, ok: bool = true) {
r.stream = s;
if s.stream_vtable == nil || s.impl_read_from == nil {
ok = false;
}
return;
}
to_writer_to :: proc(s: Stream) -> (w: Writer_To, ok: bool = true) {
w.stream = s;
if s.stream_vtable == nil || s.impl_write_to == nil {
ok = false;
}
return;
}
to_write_closer :: proc(s: Stream) -> (w: Write_Closer, ok: bool = true) {
w.stream = s;
if s.stream_vtable == nil || s.impl_write == nil || s.impl_close == nil {
ok = false;
}
return;
}
to_write_seeker :: proc(s: Stream) -> (w: Write_Seeker, ok: bool = true) {
w.stream = s;
if s.stream_vtable == nil || s.impl_write == nil || s.impl_seek == nil {
ok = false;
}
return;
}
to_byte_reader :: proc(s: Stream) -> (b: Byte_Reader, ok: bool = true) {
b.stream = s;
if s.stream_vtable == nil || s.impl_read_byte == nil {
ok = false;
if s.stream_vtable != nil && s.impl_read != nil {
ok = true;
}
}
return;
}
to_byte_scanner :: proc(s: Stream) -> (b: Byte_Scanner, ok: bool = true) {
b.stream = s;
if s.stream_vtable != nil {
if s.impl_unread_byte == nil {
ok = false;
return;
}
if s.impl_read_byte != nil {
ok = true;
} else if s.impl_read != nil {
ok = true;
} else {
ok = false;
}
}
return;
}
to_byte_writer :: proc(s: Stream) -> (b: Byte_Writer, ok: bool = true) {
b.stream = s;
if s.stream_vtable == nil || s.impl_write_byte == nil {
ok = false;
if s.stream_vtable != nil && s.impl_write != nil {
ok = true;
}
}
return;
}
to_rune_reader :: proc(s: Stream) -> (r: Rune_Reader, ok: bool = true) {
r.stream = s;
if s.stream_vtable == nil || s.impl_read_rune == nil {
ok = false;
if s.stream_vtable != nil && s.impl_read != nil {
ok = true;
}
}
return;
}
to_rune_scanner :: proc(s: Stream) -> (r: Rune_Scanner, ok: bool = true) {
r.stream = s;
if s.stream_vtable != nil {
if s.impl_unread_rune == nil {
ok = false;
return;
}
if s.impl_read_rune != nil {
ok = true;
} else if s.impl_read != nil {
ok = true;
} else {
ok = false;
}
} else {
ok = false;
}
return;
}
+514
View File
@@ -0,0 +1,514 @@
package io
import "intrinsics"
import "core:runtime"
import "core:unicode/utf8"
Seek_From :: enum {
Start = 0, // seek relative to the origin of the file
Current = 1, // seek relative to the current offset
End = 2, // seek relative to the end
}
Error :: enum i32 {
// No Error
None = 0,
// EOF is the error returned by `read` when no more input is available
EOF,
// Unexpected_EOF means that EOF was encountered in the middle of reading a fixed-sized block of data
Unexpected_EOF,
// Short_Write means that a write accepted fewer bytes than requested but failed to return an explicit error
Short_Write,
// Invalid_Write means that a write returned an impossible count
Invalid_Write,
// Short_Buffer means that a read required a longer buffer than was provided
Short_Buffer,
// No_Progress is returned by some implementations of `io.Reader` when many calls
// to `read` have failed to return any data or error.
// This is usually a signed of a broken `io.Reader` implementation
No_Progress,
Invalid_Whence,
Invalid_Offset,
Invalid_Unread,
Negative_Read,
Negative_Write,
Negative_Count,
Buffer_Full,
// Unknown means that an error has occurred but cannot be categorized
Unknown,
// Empty is returned when a procedure has not been implemented for an io.Stream
Empty = -1,
}
Close_Proc :: proc(using s: Stream) -> Error;
Flush_Proc :: proc(using s: Stream) -> Error;
Seek_Proc :: proc(using s: Stream, offset: i64, whence: Seek_From) -> (n: i64, err: Error);
Size_Proc :: proc(using s: Stream) -> i64;
Read_Proc :: proc(using s: Stream, p: []byte) -> (n: int, err: Error);
Read_At_Proc :: proc(using s: Stream, p: []byte, off: i64) -> (n: int, err: Error);
Read_From_Proc :: proc(using s: Stream, r: Reader) -> (n: i64, err: Error);
Read_Byte_Proc :: proc(using s: Stream) -> (byte, Error);
Read_Rune_Proc :: proc(using s: Stream) -> (ch: rune, size: int, err: Error);
Unread_Byte_Proc :: proc(using s: Stream) -> Error;
Unread_Rune_Proc :: proc(using s: Stream) -> Error;
Write_Proc :: proc(using s: Stream, p: []byte) -> (n: int, err: Error);
Write_At_Proc :: proc(using s: Stream, p: []byte, off: i64) -> (n: int, err: Error);
Write_To_Proc :: proc(using s: Stream, w: Writer) -> (n: i64, err: Error);
Write_Byte_Proc :: proc(using s: Stream, c: byte) -> Error;
Write_Rune_Proc :: proc(using s: Stream, r: rune) -> (size: int, err: Error);
Destroy_Proc :: proc(using s: Stream) -> Error;
Stream :: struct {
using stream_vtable: ^Stream_VTable,
stream_data: rawptr,
}
Stream_VTable :: struct {
impl_close: Close_Proc,
impl_flush: Flush_Proc,
impl_seek: Seek_Proc,
impl_size: Size_Proc,
impl_read: Read_Proc,
impl_read_at: Read_At_Proc,
impl_read_byte: Read_Byte_Proc,
impl_read_rune: Read_Rune_Proc,
impl_write_to: Write_To_Proc,
impl_write: Write_Proc,
impl_write_at: Write_At_Proc,
impl_write_byte: Write_Byte_Proc,
impl_write_rune: Write_Rune_Proc,
impl_read_from: Read_From_Proc,
impl_unread_byte: Unread_Byte_Proc,
impl_unread_rune: Unread_Rune_Proc,
impl_destroy: Destroy_Proc,
}
Reader :: struct {using stream: Stream};
Writer :: struct {using stream: Stream};
Closer :: struct {using stream: Stream};
Flusher :: struct {using stream: Stream};
Seeker :: struct {using stream: Stream};
Read_Writer :: struct {using stream: Stream};
Read_Closer :: struct {using stream: Stream};
Read_Write_Closer :: struct {using stream: Stream};
Read_Write_Seeker :: struct {using stream: Stream};
Write_Closer :: struct {using stream: Stream};
Write_Seeker :: struct {using stream: Stream};
Write_Flusher :: struct {using stream: Stream};
Write_Flush_Closer :: struct {using stream: Stream};
Reader_At :: struct {using stream: Stream};
Writer_At :: struct {using stream: Stream};
Reader_From :: struct {using stream: Stream};
Writer_To :: struct {using stream: Stream};
Byte_Reader :: struct {using stream: Stream};
Byte_Scanner :: struct {using stream: Stream};
Byte_Writer :: struct {using stream: Stream};
Rune_Reader :: struct {using stream: Stream};
Rune_Scanner :: struct {using stream: Stream};
destroy :: proc(s: Stream) -> Error {
close_err := close({s});
if s.stream_vtable != nil && s.impl_destroy != nil {
return s->impl_destroy();
}
if close_err != .None {
return close_err;
}
return .Empty;
}
read :: proc(s: Reader, p: []byte) -> (n: int, err: Error) {
if s.stream_vtable != nil && s.impl_read != nil {
return s->impl_read(p);
}
return 0, .Empty;
}
write :: proc(s: Writer, p: []byte) -> (n: int, err: Error) {
if s.stream_vtable != nil && s.impl_write != nil {
return s->impl_write(p);
}
return 0, .Empty;
}
seek :: proc(s: Seeker, offset: i64, whence: Seek_From) -> (n: i64, err: Error) {
if s.stream_vtable != nil && s.impl_seek != nil {
return s->impl_seek(offset, whence);
}
return 0, .Empty;
}
close :: proc(s: Closer) -> Error {
if s.stream_vtable != nil && s.impl_close != nil {
return s->impl_close();
}
// Instead of .Empty, .None is fine in this case
return .None;
}
flush :: proc(s: Flusher) -> Error {
if s.stream_vtable != nil && s.impl_flush != nil {
return s->impl_flush();
}
// Instead of .Empty, .None is fine in this case
return .None;
}
size :: proc(s: Stream) -> i64 {
if s.stream_vtable == nil {
return 0;
}
if s.impl_size != nil {
return s->impl_size();
}
if s.impl_seek == nil {
return 0;
}
curr, end: i64;
err: Error;
if curr, err = s->impl_seek(0, .Current); err != nil {
return 0;
}
if end, err = s->impl_seek(0, .End); err != nil {
return 0;
}
if _, err = s->impl_seek(curr, .Start); err != nil {
return 0;
}
return end;
}
read_at :: proc(r: Reader_At, p: []byte, offset: i64) -> (n: int, err: Error) {
if r.stream_vtable == nil {
return 0, .Empty;
}
if r.impl_read_at != nil {
return r->impl_read_at(p, offset);
}
if r.impl_seek == nil || r.impl_read == nil {
return 0, .Empty;
}
curr_offset: i64;
curr_offset, err = r->impl_seek(offset, .Current);
if err != nil {
return 0, err;
}
n, err = r->impl_read(p);
_, err1 := r->impl_seek(curr_offset, .Start);
if err1 != nil && err == nil {
err = err1;
}
return;
}
write_at :: proc(w: Writer_At, p: []byte, offset: i64) -> (n: int, err: Error) {
if w.stream_vtable == nil {
return 0, .Empty;
}
if w.impl_write_at != nil {
return w->impl_write_at(p, offset);
}
if w.impl_seek == nil || w.impl_write == nil {
return 0, .Empty;
}
curr_offset: i64;
curr_offset, err = w->impl_seek(offset, .Current);
if err != nil {
return 0, err;
}
n, err = w->impl_write(p);
_, err1 := w->impl_seek(curr_offset, .Start);
if err1 != nil && err == nil {
err = err1;
}
return;
}
write_to :: proc(r: Writer_To, w: Writer) -> (n: i64, err: Error) {
if r.stream_vtable == nil || w.stream_vtable == nil {
return 0, .Empty;
}
if r.impl_write_to != nil {
return r->impl_write_to(w);
}
return 0, .Empty;
}
read_from :: proc(w: Reader_From, r: Reader) -> (n: i64, err: Error) {
if r.stream_vtable == nil || w.stream_vtable == nil {
return 0, .Empty;
}
if r.impl_read_from != nil {
return w->impl_read_from(r);
}
return 0, .Empty;
}
read_byte :: proc(r: Byte_Reader) -> (byte, Error) {
if r.stream_vtable == nil {
return 0, .Empty;
}
if r.impl_read_byte != nil {
return r->impl_read_byte();
}
if r.impl_read == nil {
return 0, .Empty;
}
b: [1]byte;
_, err := r->impl_read(b[:]);
return b[0], err;
}
write_byte :: proc{
write_byte_to_byte_writer,
write_byte_to_writer,
};
write_byte_to_byte_writer :: proc(w: Byte_Writer, c: byte) -> Error {
return _write_byte(w, c);
}
write_byte_to_writer :: proc(w: Writer, c: byte) -> Error {
return _write_byte(auto_cast w, c);
}
@(private)
_write_byte :: proc(w: Byte_Writer, c: byte) -> Error {
if w.stream_vtable == nil {
return .Empty;
}
if w.impl_write_byte != nil {
return w->impl_write_byte(c);
}
if w.impl_write == nil {
return .Empty;
}
b := [1]byte{c};
_, err := w->impl_write(b[:]);
return err;
}
read_rune :: proc(br: Rune_Reader) -> (ch: rune, size: int, err: Error) {
if br.stream_vtable == nil {
return 0, 0, .Empty;
}
if br.impl_read_rune != nil {
return br->impl_read_rune();
}
if br.impl_read == nil {
return 0, 0, .Empty;
}
b: [utf8.UTF_MAX]byte;
_, err = br->impl_read(b[:1]);
s0 := b[0];
ch = rune(s0);
size = 1;
if err != nil {
return;
}
if ch < utf8.RUNE_SELF {
return;
}
x := utf8.accept_sizes[s0];
if x >= 0xf0 {
mask := rune(x) << 31 >> 31;
ch = ch &~ mask | utf8.RUNE_ERROR&mask;
return;
}
sz := int(x&7);
n: int;
n, err = br->impl_read(b[1:sz]);
if err != nil || n+1 < sz {
ch = utf8.RUNE_ERROR;
return;
}
ch, size = utf8.decode_rune(b[:sz]);
return;
}
unread_byte :: proc(s: Byte_Scanner) -> Error {
if s.stream_vtable != nil && s.impl_unread_byte != nil {
return s->impl_unread_byte();
}
return .Empty;
}
unread_rune :: proc(s: Rune_Scanner) -> Error {
if s.stream_vtable != nil && s.impl_unread_rune != nil {
return s->impl_unread_rune();
}
return .Empty;
}
write_string :: proc(s: Writer, str: string) -> (n: int, err: Error) {
return write(s, transmute([]byte)str);
}
write_rune :: proc(s: Writer, r: rune) -> (size: int, err: Error) {
if s.stream_vtable != nil && s.impl_write_rune != nil {
return s->impl_write_rune(r);
}
if r < utf8.RUNE_SELF {
err = write_byte(s, byte(r));
if err == nil {
size = 1;
}
return;
}
buf, w := utf8.encode_rune(r);
return write(s, buf[:w]);
}
read_full :: proc(r: Reader, buf: []byte) -> (n: int, err: Error) {
return read_at_least(r, buf, len(buf));
}
read_at_least :: proc(r: Reader, buf: []byte, min: int) -> (n: int, err: Error) {
if len(buf) < min {
return 0, .Short_Buffer;
}
for n < min && err == nil {
nn: int;
nn, err = read(r, buf[n:]);
n += n;
}
if n >= min {
err = nil;
} else if n > 0 && err == .EOF {
err = .Unexpected_EOF;
}
return;
}
// copy copies from src to dst till either EOF is reached on src or an error occurs
// It returns the number of bytes copied and the first error that occurred whilst copying, if any.
copy :: proc(dst: Writer, src: Reader) -> (written: i64, err: Error) {
return _copy_buffer(dst, src, nil);
}
// copy_buffer is the same as copy except that it stages through the provided buffer (if one is required)
// rather than allocating a temporary one on the stack through `intrinsics.alloca`
// If buf is `nil`, it is allocate through `intrinsics.alloca`; otherwise if it has zero length, it will panic
copy_buffer :: proc(dst: Writer, src: Reader, buf: []byte) -> (written: i64, err: Error) {
if buf != nil && len(buf) == 0 {
panic("empty buffer in io.copy_buffer");
}
return _copy_buffer(dst, src, buf);
}
// copy_n copies n bytes (or till an error) from src to dst.
// It returns the number of bytes copied and the first error that occurred whilst copying, if any.
// On return, written == n IFF err == nil
copy_n :: proc(dst: Writer, src: Reader, n: i64) -> (written: i64, err: Error) {
nsrc := limited_reader_init(&Limited_Reader{}, src, n);
written, err = copy(dst, nsrc);
if written == n {
return n, nil;
}
if written < n && err == nil {
// src stopped early and must have been an EOF
err = .EOF;
}
return;
}
@(private)
_copy_buffer :: proc(dst: Writer, src: Reader, buf: []byte) -> (written: i64, err: Error) {
if dst.stream_vtable == nil || src.stream_vtable == nil {
return 0, .Empty;
}
if src.impl_write_to != nil {
return src->impl_write_to(dst);
}
if src.impl_read_from != nil {
return dst->impl_read_from(src);
}
buf := buf;
if buf == nil {
DEFAULT_SIZE :: 4 * 1024;
size := DEFAULT_SIZE;
if src.stream_vtable == _limited_reader_vtable {
l := (^Limited_Reader)(src.stream_data);
if i64(size) > l.n {
if l.n < 1 {
size = 1;
} else {
size = int(l.n);
}
}
}
// NOTE(bill): alloca is fine here
buf = transmute([]byte)runtime.Raw_Slice{intrinsics.alloca(size, 2*align_of(rawptr)), size};
}
for {
nr, er := read(src, buf);
if nr > 0 {
nw, ew := write(dst, buf[0:nr]);
if nw > 0 {
written += i64(nw);
}
if ew != nil {
err = ew;
break;
}
if nr != nw {
err = .Short_Write;
break;
}
}
if er != nil {
if er != .EOF {
err = er;
}
break;
}
}
return;
}
+95
View File
@@ -0,0 +1,95 @@
package io
Multi_Reader :: struct {
readers: [dynamic]Reader,
}
@(private)
_multi_reader_vtable := &Stream_VTable{
impl_read = proc(s: Stream, p: []byte) -> (n: int, err: Error) {
mr := (^Multi_Reader)(s.stream_data);
for len(mr.readers) > 0 {
r := mr.readers[0];
n, err = read(r, p);
if err == .EOF {
ordered_remove(&mr.readers, 0);
}
if n > 0 || err != .EOF {
if err == .EOF && len(mr.readers) > 0 {
// Don't return EOF yet, more readers remain
err = nil;
}
return;
}
}
return 0, .EOF;
},
};
multi_reader_init :: proc(mr: ^Multi_Reader, readers: ..Reader, allocator := context.allocator) -> (r: Reader) {
all_readers := make([dynamic]Reader, 0, len(readers), allocator);
for w in readers {
if w.stream_vtable == _multi_reader_vtable {
other := (^Multi_Reader)(w.stream_data);
append(&all_readers, ..other.readers[:]);
} else {
append(&all_readers, w);
}
}
mr.readers = all_readers;
r.stream_vtable = _multi_reader_vtable;
r.stream_data = mr;
return;
}
multi_reader_destroy :: proc(mr: ^Multi_Reader) {
delete(mr.readers);
}
Multi_Writer :: struct {
writers: [dynamic]Writer,
}
@(private)
_multi_writer_vtable := &Stream_VTable{
impl_write = proc(s: Stream, p: []byte) -> (n: int, err: Error) {
mw := (^Multi_Writer)(s.stream_data);
for w in mw.writers {
n, err = write(w, p);
if err != nil {
return;
}
if n != len(p) {
err = .Short_Write;
return;
}
}
return len(p), nil;
},
};
multi_writer_init :: proc(mw: ^Multi_Writer, writers: ..Writer, allocator := context.allocator) -> (out: Writer) {
mw.writers = make([dynamic]Writer, 0, len(writers), allocator);
for w in writers {
if w.stream_vtable == _multi_writer_vtable {
other := (^Multi_Writer)(w.stream_data);
append(&mw.writers, ..other.writers[:]);
} else {
append(&mw.writers, w);
}
}
out.stream_vtable = _multi_writer_vtable;
out.stream_data = mw;
return;
}
multi_writer_destroy :: proc(mw: ^Multi_Writer) {
delete(mw.writers);
}
+176
View File
@@ -0,0 +1,176 @@
package io
import "core:strconv"
write_u64 :: proc(w: Writer, i: u64, base: int = 10) -> (n: int, err: Error) {
buf: [32]byte;
s := strconv.append_bits(buf[:], i, base, false, 64, strconv.digits, nil);
return write_string(w, s);
}
write_i64 :: proc(w: Writer, i: i64, base: int = 10) -> (n: int, err: Error) {
buf: [32]byte;
s := strconv.append_bits(buf[:], u64(i), base, true, 64, strconv.digits, nil);
return write_string(w, s);
}
write_uint :: proc(w: Writer, i: uint, base: int = 10) -> (n: int, err: Error) {
return write_u64(w, u64(i), base);
}
write_int :: proc(w: Writer, i: int, base: int = 10) -> (n: int, err: Error) {
return write_i64(w, i64(i), base);
}
Tee_Reader :: struct {
r: Reader,
w: Writer,
}
@(private)
_tee_reader_vtable := &Stream_VTable{
impl_read = proc(s: Stream, p: []byte) -> (n: int, err: Error) {
t := (^Tee_Reader)(s.stream_data);
n, err = read(t.r, p);
if n > 0 {
if wn, werr := write(t.w, p[:n]); werr != nil {
return wn, werr;
}
}
return;
},
};
// tee_reader_init returns a Reader that writes to 'w' what it reads from 'r'
// All reads from 'r' performed through it are matched with a corresponding write to 'w'
// There is no internal buffering done
// The write must complete before th read completes
// Any error encountered whilst writing is reported as a 'read' error
// tee_reader_init must call io.destroy when done with
tee_reader_init :: proc(t: ^Tee_Reader, r: Reader, w: Writer, allocator := context.allocator) -> Reader {
t.r, t.w = r, w;
return tee_reader_to_reader(t);
}
tee_reader_to_reader :: proc(t: ^Tee_Reader) -> (r: Reader) {
r.stream_data = t;
r.stream_vtable = _tee_reader_vtable;
return;
}
// A Limited_Reader reads from r but limits the amount of data returned to just n bytes.
// Each call to read updates n to reflect the new amount remaining.
// read returns EOF when n <= 0 or when the underlying r returns EOF.
Limited_Reader :: struct {
r: Reader, // underlying reader
n: i64, // max_bytes
}
@(private)
_limited_reader_vtable := &Stream_VTable{
impl_read = proc(s: Stream, p: []byte) -> (n: int, err: Error) {
l := (^Limited_Reader)(s.stream_data);
if l.n <= 0 {
return 0, .EOF;
}
p := p;
if i64(len(p)) > l.n {
p = p[0:l.n];
}
n, err = read(l.r, p);
l.n -= i64(n);
return;
},
};
limited_reader_init :: proc(l: ^Limited_Reader, r: Reader, n: i64) -> Reader {
l.r = r;
l.n = n;
return limited_reader_to_reader(l);
}
limited_reader_to_reader :: proc(l: ^Limited_Reader) -> (r: Reader) {
r.stream_vtable = _limited_reader_vtable;
r.stream_data = l;
return;
}
// Section_Reader implements read, seek, and read_at on a section of an underlying Reader_At
Section_Reader :: struct {
r: Reader_At,
base: i64,
off: i64,
limit: i64,
}
section_reader_init :: proc(s: ^Section_Reader, r: Reader_At, off: i64, n: i64) {
s.r = r;
s.off = off;
s.limit = off + n;
return;
}
section_reader_to_stream :: proc(s: ^Section_Reader) -> (out: Stream) {
out.stream_data = s;
out.stream_vtable = _section_reader_vtable;
return;
}
@(private)
_section_reader_vtable := &Stream_VTable{
impl_read = proc(stream: Stream, p: []byte) -> (n: int, err: Error) {
s := (^Section_Reader)(stream.stream_data);
if s.off >= s.limit {
return 0, .EOF;
}
p := p;
if max := s.limit - s.off; i64(len(p)) > max {
p = p[0:max];
}
n, err = read_at(s.r, p, s.off);
s.off += i64(n);
return;
},
impl_read_at = proc(stream: Stream, p: []byte, off: i64) -> (n: int, err: Error) {
s := (^Section_Reader)(stream.stream_data);
p, off := p, off;
if off < 0 || off >= s.limit - s.base {
return 0, .EOF;
}
off += s.base;
if max := s.limit - off; i64(len(p)) > max {
p = p[0:max];
n, err = read_at(s.r, p, off);
if err == nil {
err = .EOF;
}
return;
}
return read_at(s.r, p, off);
},
impl_seek = proc(stream: Stream, offset: i64, whence: Seek_From) -> (n: i64, err: Error) {
s := (^Section_Reader)(stream.stream_data);
offset := offset;
switch whence {
case:
return 0, .Invalid_Whence;
case .Start:
offset += s.base;
case .Current:
offset += s.off;
case .End:
offset += s.limit;
}
if offset < s.base {
return 0, .Invalid_Offset;
}
s.off = offset;
n = offset - s.base;
return;
},
impl_size = proc(stream: Stream) -> i64 {
s := (^Section_Reader)(stream.stream_data);
return s.limit - s.base;
},
};
+162
View File
@@ -0,0 +1,162 @@
package log
import "core:fmt";
import "core:strings";
import "core:os";
import "core:time";
Level_Headers := [?]string{
0..<10 = "[DEBUG] --- ",
10..<20 = "[INFO ] --- ",
20..<30 = "[WARN ] --- ",
30..<40 = "[ERROR] --- ",
40..<50 = "[FATAL] --- ",
};
Default_Console_Logger_Opts :: Options{
.Level,
.Terminal_Color,
.Short_File_Path,
.Line,
.Procedure,
} | Full_Timestamp_Opts;
Default_File_Logger_Opts :: Options{
.Level,
.Short_File_Path,
.Line,
.Procedure,
} | Full_Timestamp_Opts;
File_Console_Logger_Data :: struct {
file_handle: os.Handle,
ident: string,
}
create_file_logger :: proc(h: os.Handle, lowest := Level.Debug, opt := Default_File_Logger_Opts, ident := "") -> Logger {
data := new(File_Console_Logger_Data);
data.file_handle = h;
data.ident = ident;
return Logger{file_console_logger_proc, data, lowest, opt};
}
destroy_file_logger :: proc(log: ^Logger) {
data := cast(^File_Console_Logger_Data)log.data;
if data.file_handle != os.INVALID_HANDLE {
os.close(data.file_handle);
}
free(data);
}
create_console_logger :: proc(lowest := Level.Debug, opt := Default_Console_Logger_Opts, ident := "") -> Logger {
data := new(File_Console_Logger_Data);
data.file_handle = os.INVALID_HANDLE;
data.ident = ident;
return Logger{file_console_logger_proc, data, lowest, opt};
}
destroy_console_logger :: proc(log: ^Logger) {
free(log.data);
}
file_console_logger_proc :: proc(logger_data: rawptr, level: Level, text: string, options: Options, location := #caller_location) {
data := cast(^File_Console_Logger_Data)logger_data;
h: os.Handle = os.stdout if level <= Level.Error else os.stderr;
if data.file_handle != os.INVALID_HANDLE {
h = data.file_handle;
}
backing: [1024]byte; //NOTE(Hoej): 1024 might be too much for a header backing, unless somebody has really long paths.
buf := strings.builder_from_slice(backing[:]);
do_level_header(options, level, &buf);
when time.IS_SUPPORTED {
if Full_Timestamp_Opts & options != nil {
fmt.sbprint(&buf, "[");
t := time.now();
y, m, d := time.date(t);
h, min, s := time.clock(t);
if .Date in options { fmt.sbprintf(&buf, "%d-%02d-%02d ", y, m, d); }
if .Time in options { fmt.sbprintf(&buf, "%02d:%02d:%02d", h, min, s); }
fmt.sbprint(&buf, "] ");
}
}
do_location_header(options, &buf, location);
if .Thread_Id in options {
// NOTE(Oskar): not using context.thread_id here since that could be
// incorrect when replacing context for a thread.
fmt.sbprintf(&buf, "[{}] ", os.current_thread_id());
}
if data.ident != "" {
fmt.sbprintf(&buf, "[%s] ", data.ident);
}
//TODO(Hoej): When we have better atomics and such, make this thread-safe
fmt.fprintf(h, "%s %s\n", strings.to_string(buf), text);
}
do_level_header :: proc(opts: Options, level: Level, str: ^strings.Builder) {
RESET :: "\x1b[0m";
RED :: "\x1b[31m";
YELLOW :: "\x1b[33m";
DARK_GREY :: "\x1b[90m";
col := RESET;
switch level {
case .Debug: col = DARK_GREY;
case .Info: col = RESET;
case .Warning: col = YELLOW;
case .Error, .Fatal: col = RED;
}
if .Level in opts {
if .Terminal_Color in opts {
fmt.sbprint(str, col);
}
fmt.sbprint(str, Level_Headers[level]);
if .Terminal_Color in opts {
fmt.sbprint(str, RESET);
}
}
}
do_location_header :: proc(opts: Options, buf: ^strings.Builder, location := #caller_location) {
if Location_Header_Opts & opts == nil {
return;
}
fmt.sbprint(buf, "[");
file := location.file_path;
if .Short_File_Path in opts {
last := 0;
for r, i in location.file_path {
if r == '/' {
last = i+1;
}
}
file = location.file_path[last:];
}
if Location_File_Opts & opts != nil {
fmt.sbprint(buf, file);
}
if .Line in opts {
if Location_File_Opts & opts != nil {
fmt.sbprint(buf, ":");
}
fmt.sbprint(buf, location.line);
}
if .Procedure in opts {
if (Location_File_Opts | {.Line}) & opts != nil {
fmt.sbprint(buf, ":");
}
fmt.sbprintf(buf, "%s()", location.procedure);
}
fmt.sbprint(buf, "] ");
}
+145
View File
@@ -0,0 +1,145 @@
package log
import "core:runtime"
import "core:fmt"
// NOTE(bill, 2019-12-31): These are defined in `package runtime` as they are used in the `context`. This is to prevent an import definition cycle.
Level :: runtime.Logger_Level;
/*
Logger_Level :: enum {
Debug = 0,
Info = 10,
Warning = 20,
Error = 30,
Fatal = 40,
}
*/
Option :: runtime.Logger_Option;
/*
Option :: enum {
Level,
Date,
Time,
Short_File_Path,
Long_File_Path,
Line,
Procedure,
Terminal_Color
}
*/
Options :: runtime.Logger_Options;
/*
Options :: bit_set[Option];
*/
Full_Timestamp_Opts :: Options{
.Date,
.Time,
};
Location_Header_Opts :: Options{
.Short_File_Path,
.Long_File_Path,
.Line,
.Procedure,
};
Location_File_Opts :: Options{
.Short_File_Path,
.Long_File_Path,
};
Logger_Proc :: runtime.Logger_Proc;
/*
Logger_Proc :: #type proc(data: rawptr, level: Level, text: string, options: Options, location := #caller_location);
*/
Logger :: runtime.Logger;
/*
Logger :: struct {
procedure: Logger_Proc,
data: rawptr,
lowest_level: Level,
options: Logger_Options,
}
*/
nil_logger_proc :: proc(data: rawptr, level: Level, text: string, options: Options, location := #caller_location) {
// Do nothing
}
nil_logger :: proc() -> Logger {
return Logger{nil_logger_proc, nil, Level.Debug, nil};
}
// TODO(bill): Should these be redesigned so that they are do not rely upon `package fmt`?
debugf :: proc(fmt_str: string, args: ..any, location := #caller_location) {
logf(level=.Debug, fmt_str=fmt_str, args=args, location=location);
}
infof :: proc(fmt_str: string, args: ..any, location := #caller_location) {
logf(level=.Info, fmt_str=fmt_str, args=args, location=location);
}
warnf :: proc(fmt_str: string, args: ..any, location := #caller_location) {
logf(level=.Warning, fmt_str=fmt_str, args=args, location=location);
}
errorf :: proc(fmt_str: string, args: ..any, location := #caller_location) {
logf(level=.Error, fmt_str=fmt_str, args=args, location=location);
}
fatalf :: proc(fmt_str: string, args: ..any, location := #caller_location) {
logf(level=.Fatal, fmt_str=fmt_str, args=args, location=location);
}
debug :: proc(args: ..any, sep := " ", location := #caller_location) {
log(level=.Debug, args=args, sep=sep, location=location);
}
info :: proc(args: ..any, sep := " ", location := #caller_location) {
log(level=.Info, args=args, sep=sep, location=location);
}
warn :: proc(args: ..any, sep := " ", location := #caller_location) {
log(level=.Warning, args=args, sep=sep, location=location);
}
error :: proc(args: ..any, sep := " ", location := #caller_location) {
log(level=.Error, args=args, sep=sep, location=location);
}
fatal :: proc(args: ..any, sep := " ", location := #caller_location) {
log(level=.Fatal, args=args, sep=sep, location=location);
}
panic :: proc(args: ..any, location := #caller_location) -> ! {
log(level=.Fatal, args=args, location=location);
runtime.panic("log.panic", location);
}
panicf :: proc(fmt_str: string, args: ..any, location := #caller_location) -> ! {
logf(level=.Fatal, fmt_str=fmt_str, args=args, location=location);
runtime.panic("log.panicf", location);
}
log :: proc(level: Level, args: ..any, sep := " ", location := #caller_location) {
logger := context.logger;
if logger.procedure == nil {
return;
}
if level < logger.lowest_level {
return;
}
str := fmt.tprint(args=args, sep=sep); //NOTE(Hoej): While tprint isn't thread-safe, no logging is.
logger.procedure(logger.data, level, str, logger.options, location);
}
logf :: proc(level: Level, fmt_str: string, args: ..any, location := #caller_location) {
logger := context.logger;
if logger.procedure == nil {
return;
}
if level < logger.lowest_level {
return;
}
str := fmt.tprintf(fmt_str, ..args);
logger.procedure(logger.data, level, str, logger.options, location);
}
+29
View File
@@ -0,0 +1,29 @@
package log
Multi_Logger_Data :: struct {
loggers: []Logger,
}
create_multi_logger :: proc(logs: ..Logger) -> Logger {
data := new(Multi_Logger_Data);
data.loggers = make([]Logger, len(logs));
copy(data.loggers, logs);
return Logger{multi_logger_proc, data, Level.Debug, nil};
}
destroy_multi_logger :: proc(log : ^Logger) {
free(log.data);
log^ = nil_logger();
}
multi_logger_proc :: proc(logger_data: rawptr, level: Level, text: string,
options: Options, location := #caller_location) {
data := cast(^Multi_Logger_Data)logger_data;
for log in data.loggers {
if level < log.lowest_level {
return;
}
log.procedure(log.data, level, text, log.options, location);
}
}
-374
View File
@@ -1,374 +0,0 @@
TAU :: 6.28318530717958647692528676655900576;
PI :: 3.14159265358979323846264338327950288;
ONE_OVER_TAU :: 0.636619772367581343075535053490057448;
ONE_OVER_PI :: 0.159154943091895335768883763372514362;
E :: 2.71828182845904523536;
SQRT_TWO :: 1.41421356237309504880168872420969808;
SQRT_THREE :: 1.73205080756887729352744634150587236;
SQRT_FIVE :: 2.23606797749978969640917366873127623;
LOG_TWO :: 0.693147180559945309417232121458176568;
LOG_TEN :: 2.30258509299404568401799145468436421;
EPSILON :: 1.19209290e-7;
τ :: TAU;
π :: PI;
Vec2 :: [2]f32;
Vec3 :: [3]f32;
Vec4 :: [4]f32;
// Column major
Mat2 :: [2][2]f32;
Mat3 :: [3][3]f32;
Mat4 :: [4][4]f32;
Complex :: complex64;
@(default_calling_convention="c")
foreign __llvm_core {
@(link_name="llvm.sqrt.f32")
sqrt :: proc(x: f32) -> f32 ---;
@(link_name="llvm.sqrt.f64")
sqrt :: proc(x: f64) -> f64 ---;
@(link_name="llvm.sin.f32")
sin :: proc(θ: f32) -> f32 ---;
@(link_name="llvm.sin.f64")
sin :: proc(θ: f64) -> f64 ---;
@(link_name="llvm.cos.f32")
cos :: proc(θ: f32) -> f32 ---;
@(link_name="llvm.cos.f64")
cos :: proc(θ: f64) -> f64 ---;
@(link_name="llvm.pow.f32")
pow :: proc(x, power: f32) -> f32 ---;
@(link_name="llvm.pow.f64")
pow :: proc(x, power: f64) -> f64 ---;
@(link_name="llvm.fmuladd.f32")
fmuladd :: proc(a, b, c: f32) -> f32 ---;
@(link_name="llvm.fmuladd.f64")
fmuladd :: proc(a, b, c: f64) -> f64 ---;
}
tan :: proc "c" (θ: f32) -> f32 do return sin(θ)/cos(θ);
tan :: proc "c" (θ: f64) -> f64 do return sin(θ)/cos(θ);
lerp :: proc(a, b: $T, t: $E) -> (x: T) do return a*(1-t) + b*t;
unlerp :: proc(a, b, x: f32) -> (t: f32) do return (x-a)/(b-a);
unlerp :: proc(a, b, x: f64) -> (t: f64) do return (x-a)/(b-a);
sign :: proc(x: f32) -> f32 { return x >= 0 ? +1 : -1; }
sign :: proc(x: f64) -> f64 { return x >= 0 ? +1 : -1; }
copy_sign :: proc(x, y: f32) -> f32 {
ix := transmute(u32)x;
iy := transmute(u32)y;
ix &= 0x7fff_ffff;
ix |= iy & 0x8000_0000;
return transmute(f32)ix;
}
copy_sign :: proc(x, y: f64) -> f64 {
ix := transmute(u64)x;
iy := transmute(u64)y;
ix &= 0x7fff_ffff_ffff_ff;
ix |= iy & 0x8000_0000_0000_0000;
return transmute(f64)ix;
}
round :: proc(x: f32) -> f32 { return x >= 0 ? floor(x + 0.5) : ceil(x - 0.5); }
round :: proc(x: f64) -> f64 { return x >= 0 ? floor(x + 0.5) : ceil(x - 0.5); }
floor :: proc(x: f32) -> f32 { return x >= 0 ? f32(i64(x)) : f32(i64(x-0.5)); } // TODO: Get accurate versions
floor :: proc(x: f64) -> f64 { return x >= 0 ? f64(i64(x)) : f64(i64(x-0.5)); } // TODO: Get accurate versions
ceil :: proc(x: f32) -> f32 { return x < 0 ? f32(i64(x)) : f32(i64(x+1)); }// TODO: Get accurate versions
ceil :: proc(x: f64) -> f64 { return x < 0 ? f64(i64(x)) : f64(i64(x+1)); }// TODO: Get accurate versions
remainder :: proc(x, y: f32) -> f32 do return x - round(x/y) * y;
remainder :: proc(x, y: f64) -> f64 do return x - round(x/y) * y;
mod :: proc(x, y: f32) -> f32 {
result: f32;
y = abs(y);
result = remainder(abs(x), y);
if sign(result) < 0 {
result += y;
}
return copy_sign(result, x);
}
mod :: proc(x, y: f64) -> f64 {
result: f64;
y = abs(y);
result = remainder(abs(x), y);
if sign(result) < 0 {
result += y;
}
return copy_sign(result, x);
}
to_radians :: proc(degrees: f32) -> f32 do return degrees * TAU / 360;
to_degrees :: proc(radians: f32) -> f32 do return radians * 360 / TAU;
dot :: proc(a, b: $T/[$N]$E) -> E {
res: E;
for i in 0..N do res += a[i] * b[i];
return res;
}
cross :: proc(x, y: $T/[3]$E) -> T {
a := swizzle(x, 1, 2, 0) * swizzle(y, 2, 0, 1);
b := swizzle(x, 2, 0, 1) * swizzle(y, 1, 2, 0);
return T(a - b);
}
mag :: proc(v: $T/[$N]$E) -> E do return sqrt(dot(v, v));
norm :: proc(v: $T/[$N]$E) -> T do return v / mag(v);
norm0 :: proc(v: $T/[$N]$E) -> T {
m := mag(v);
return m == 0 ? 0 : v/m;
}
mat4_identity :: proc() -> Mat4 {
return Mat4{
{1, 0, 0, 0},
{0, 1, 0, 0},
{0, 0, 1, 0},
{0, 0, 0, 1},
};
}
mat4_transpose :: proc(m: Mat4) -> Mat4 {
for j in 0..4 {
for i in 0..4 {
m[i][j], m[j][i] = m[j][i], m[i][j];
}
}
return m;
}
mul :: proc(a, b: Mat4) -> Mat4 {
c: Mat4;
for j in 0..4 {
for i in 0..4 {
c[j][i] = a[0][i]*b[j][0] +
a[1][i]*b[j][1] +
a[2][i]*b[j][2] +
a[3][i]*b[j][3];
}
}
return c;
}
mul :: proc(m: Mat4, v: Vec4) -> Vec4 {
return Vec4{
m[0][0]*v[0] + m[1][0]*v[1] + m[2][0]*v[2] + m[3][0]*v[3],
m[0][1]*v[0] + m[1][1]*v[1] + m[2][1]*v[2] + m[3][1]*v[3],
m[0][2]*v[0] + m[1][2]*v[1] + m[2][2]*v[2] + m[3][2]*v[3],
m[0][3]*v[0] + m[1][3]*v[1] + m[2][3]*v[2] + m[3][3]*v[3],
};
}
inverse :: proc(m: Mat4) -> Mat4 {
o: Mat4;
sf00 := m[2][2] * m[3][3] - m[3][2] * m[2][3];
sf01 := m[2][1] * m[3][3] - m[3][1] * m[2][3];
sf02 := m[2][1] * m[3][2] - m[3][1] * m[2][2];
sf03 := m[2][0] * m[3][3] - m[3][0] * m[2][3];
sf04 := m[2][0] * m[3][2] - m[3][0] * m[2][2];
sf05 := m[2][0] * m[3][1] - m[3][0] * m[2][1];
sf06 := m[1][2] * m[3][3] - m[3][2] * m[1][3];
sf07 := m[1][1] * m[3][3] - m[3][1] * m[1][3];
sf08 := m[1][1] * m[3][2] - m[3][1] * m[1][2];
sf09 := m[1][0] * m[3][3] - m[3][0] * m[1][3];
sf10 := m[1][0] * m[3][2] - m[3][0] * m[1][2];
sf11 := m[1][1] * m[3][3] - m[3][1] * m[1][3];
sf12 := m[1][0] * m[3][1] - m[3][0] * m[1][1];
sf13 := m[1][2] * m[2][3] - m[2][2] * m[1][3];
sf14 := m[1][1] * m[2][3] - m[2][1] * m[1][3];
sf15 := m[1][1] * m[2][2] - m[2][1] * m[1][2];
sf16 := m[1][0] * m[2][3] - m[2][0] * m[1][3];
sf17 := m[1][0] * m[2][2] - m[2][0] * m[1][2];
sf18 := m[1][0] * m[2][1] - m[2][0] * m[1][1];
o[0][0] = +(m[1][1] * sf00 - m[1][2] * sf01 + m[1][3] * sf02);
o[0][1] = -(m[1][0] * sf00 - m[1][2] * sf03 + m[1][3] * sf04);
o[0][2] = +(m[1][0] * sf01 - m[1][1] * sf03 + m[1][3] * sf05);
o[0][3] = -(m[1][0] * sf02 - m[1][1] * sf04 + m[1][2] * sf05);
o[1][0] = -(m[0][1] * sf00 - m[0][2] * sf01 + m[0][3] * sf02);
o[1][1] = +(m[0][0] * sf00 - m[0][2] * sf03 + m[0][3] * sf04);
o[1][2] = -(m[0][0] * sf01 - m[0][1] * sf03 + m[0][3] * sf05);
o[1][3] = +(m[0][0] * sf02 - m[0][1] * sf04 + m[0][2] * sf05);
o[2][0] = +(m[0][1] * sf06 - m[0][2] * sf07 + m[0][3] * sf08);
o[2][1] = -(m[0][0] * sf06 - m[0][2] * sf09 + m[0][3] * sf10);
o[2][2] = +(m[0][0] * sf11 - m[0][1] * sf09 + m[0][3] * sf12);
o[2][3] = -(m[0][0] * sf08 - m[0][1] * sf10 + m[0][2] * sf12);
o[3][0] = -(m[0][1] * sf13 - m[0][2] * sf14 + m[0][3] * sf15);
o[3][1] = +(m[0][0] * sf13 - m[0][2] * sf16 + m[0][3] * sf17);
o[3][2] = -(m[0][0] * sf14 - m[0][1] * sf16 + m[0][3] * sf18);
o[3][3] = +(m[0][0] * sf15 - m[0][1] * sf17 + m[0][2] * sf18);
ood := 1.0 / (m[0][0] * o[0][0] +
m[0][1] * o[0][1] +
m[0][2] * o[0][2] +
m[0][3] * o[0][3]);
o[0][0] *= ood;
o[0][1] *= ood;
o[0][2] *= ood;
o[0][3] *= ood;
o[1][0] *= ood;
o[1][1] *= ood;
o[1][2] *= ood;
o[1][3] *= ood;
o[2][0] *= ood;
o[2][1] *= ood;
o[2][2] *= ood;
o[2][3] *= ood;
o[3][0] *= ood;
o[3][1] *= ood;
o[3][2] *= ood;
o[3][3] *= ood;
return o;
}
mat4_translate :: proc(v: Vec3) -> Mat4 {
m := mat4_identity();
m[3][0] = v[0];
m[3][1] = v[1];
m[3][2] = v[2];
m[3][3] = 1;
return m;
}
mat4_rotate :: proc(v: Vec3, angle_radians: f32) -> Mat4 {
c := cos(angle_radians);
s := sin(angle_radians);
a := norm(v);
t := a * (1-c);
rot := mat4_identity();
rot[0][0] = c + t[0]*a[0];
rot[0][1] = 0 + t[0]*a[1] + s*a[2];
rot[0][2] = 0 + t[0]*a[2] - s*a[1];
rot[0][3] = 0;
rot[1][0] = 0 + t[1]*a[0] - s*a[2];
rot[1][1] = c + t[1]*a[1];
rot[1][2] = 0 + t[1]*a[2] + s*a[0];
rot[1][3] = 0;
rot[2][0] = 0 + t[2]*a[0] + s*a[1];
rot[2][1] = 0 + t[2]*a[1] - s*a[0];
rot[2][2] = c + t[2]*a[2];
rot[2][3] = 0;
return rot;
}
scale :: proc(m: Mat4, v: Vec3) -> Mat4 {
m[0][0] *= v[0];
m[1][1] *= v[1];
m[2][2] *= v[2];
return m;
}
scale :: proc(m: Mat4, s: f32) -> Mat4 {
m[0][0] *= s;
m[1][1] *= s;
m[2][2] *= s;
return m;
}
look_at :: proc(eye, centre, up: Vec3) -> Mat4 {
f := norm(centre - eye);
s := norm(cross(f, up));
u := cross(s, f);
return Mat4{
{+s[0], +u[0], -f[0], 0},
{+s[1], +u[1], -f[1], 0},
{+s[2], +u[2], -f[2], 0},
{-dot(s, eye), -dot(u, eye), dot(f, eye), 1},
};
}
perspective :: proc(fovy, aspect, near, far: f32) -> Mat4 {
m: Mat4;
tan_half_fovy := tan(0.5 * fovy);
m[0][0] = 1.0 / (aspect*tan_half_fovy);
m[1][1] = 1.0 / (tan_half_fovy);
m[2][2] = -(far + near) / (far - near);
m[2][3] = -1.0;
m[3][2] = -2.0*far*near / (far - near);
return m;
}
ortho3d :: proc(left, right, bottom, top, near, far: f32) -> Mat4 {
m := mat4_identity();
m[0][0] = +2.0 / (right - left);
m[1][1] = +2.0 / (top - bottom);
m[2][2] = -2.0 / (far - near);
m[3][0] = -(right + left) / (right - left);
m[3][1] = -(top + bottom) / (top - bottom);
m[3][2] = -(far + near) / (far - near);
return m;
}
F32_DIG :: 6;
F32_EPSILON :: 1.192092896e-07;
F32_GUARD :: 0;
F32_MANT_DIG :: 24;
F32_MAX :: 3.402823466e+38;
F32_MAX_10_EXP :: 38;
F32_MAX_EXP :: 128;
F32_MIN :: 1.175494351e-38;
F32_MIN_10_EXP :: -37;
F32_MIN_EXP :: -125;
F32_NORMALIZE :: 0;
F32_RADIX :: 2;
F32_ROUNDS :: 1;
F64_DIG :: 15; // # of decimal digits of precision
F64_EPSILON :: 2.2204460492503131e-016; // smallest such that 1.0+F64_EPSILON != 1.0
F64_MANT_DIG :: 53; // # of bits in mantissa
F64_MAX :: 1.7976931348623158e+308; // max value
F64_MAX_10_EXP :: 308; // max decimal exponent
F64_MAX_EXP :: 1024; // max binary exponent
F64_MIN :: 2.2250738585072014e-308; // min positive value
F64_MIN_10_EXP :: -307; // min decimal exponent
F64_MIN_EXP :: -1021; // min binary exponent
F64_RADIX :: 2; // exponent radix
F64_ROUNDS :: 1; // addition rounding: near
+656
View File
@@ -0,0 +1,656 @@
package math_bits
import "core:runtime"
U8_MIN :: 0;
U16_MIN :: 0;
U32_MIN :: 0;
U64_MIN :: 0;
U8_MAX :: 1 << 8 - 1;
U16_MAX :: 1 << 16 - 1;
U32_MAX :: 1 << 32 - 1;
U64_MAX :: 1 << 64 - 1;
I8_MIN :: - 1 << 7;
I16_MIN :: - 1 << 15;
I32_MIN :: - 1 << 31;
I64_MIN :: - 1 << 63;
I8_MAX :: 1 << 7 - 1;
I16_MAX :: 1 << 15 - 1;
I32_MAX :: 1 << 31 - 1;
I64_MAX :: 1 << 63 - 1;
@(default_calling_convention="none")
foreign {
@(link_name="llvm.ctpop.i8") count_ones8 :: proc(i: u8) -> u8 ---
@(link_name="llvm.ctpop.i16") count_ones16 :: proc(i: u16) -> u16 ---
@(link_name="llvm.ctpop.i32") count_ones32 :: proc(i: u32) -> u32 ---
@(link_name="llvm.ctpop.i64") count_ones64 :: proc(i: u64) -> u64 ---
@(link_name="llvm.cttz.i8") trailing_zeros8 :: proc(i: u8, is_zero_undef := false) -> u8 ---
@(link_name="llvm.cttz.i16") trailing_zeros16 :: proc(i: u16, is_zero_undef := false) -> u16 ---
@(link_name="llvm.cttz.i32") trailing_zeros32 :: proc(i: u32, is_zero_undef := false) -> u32 ---
@(link_name="llvm.cttz.i64") trailing_zeros64 :: proc(i: u64, is_zero_undef := false) -> u64 ---
@(link_name="llvm.bitreverse.i8") reverse_bits8 :: proc(i: u8) -> u8 ---
@(link_name="llvm.bitreverse.i16") reverse_bits16 :: proc(i: u16) -> u16 ---
@(link_name="llvm.bitreverse.i32") reverse_bits32 :: proc(i: u32) -> u32 ---
@(link_name="llvm.bitreverse.i64") reverse_bits64 :: proc(i: u64) -> u64 ---
}
trailing_zeros_uint :: proc(i: uint) -> uint {
when size_of(uint) == size_of(u64) {
return uint(trailing_zeros64(u64(i)));
} else {
return uint(trailing_zeros32(u32(i)));
}
}
leading_zeros_u8 :: proc(i: u8) -> int {
return 8*size_of(i) - len_u8(i);
}
leading_zeros_u16 :: proc(i: u16) -> int {
return 8*size_of(i) - len_u16(i);
}
leading_zeros_u32 :: proc(i: u32) -> int {
return 8*size_of(i) - len_u32(i);
}
leading_zeros_u64 :: proc(i: u64) -> int {
return 8*size_of(i) - len_u64(i);
}
byte_swap_u16 :: proc(x: u16) -> u16 {
return runtime.bswap_16(x);
}
byte_swap_u32 :: proc(x: u32) -> u32 {
return runtime.bswap_32(x);
}
byte_swap_u64 :: proc(x: u64) -> u64 {
return runtime.bswap_64(x);
}
byte_swap_i16 :: proc(x: i16) -> i16 {
return i16(runtime.bswap_16(u16(x)));
}
byte_swap_i32 :: proc(x: i32) -> i32 {
return i32(runtime.bswap_32(u32(x)));
}
byte_swap_i64 :: proc(x: i64) -> i64 {
return i64(runtime.bswap_64(u64(x)));
}
byte_swap_u128 :: proc(x: u128) -> u128 {
return runtime.bswap_128(x);
}
byte_swap_i128 :: proc(x: i128) -> i128 {
return i128(runtime.bswap_128(u128(x)));
}
byte_swap_uint :: proc(i: uint) -> uint {
when size_of(uint) == size_of(u32) {
return uint(byte_swap_u32(u32(i)));
} else {
return uint(byte_swap_u64(u64(i)));
}
}
byte_swap_int :: proc(i: int) -> int {
when size_of(int) == size_of(i32) {
return int(byte_swap_i32(i32(i)));
} else {
return int(byte_swap_i64(i64(i)));
}
}
byte_swap :: proc{
byte_swap_u16,
byte_swap_u32,
byte_swap_u64,
byte_swap_u128,
byte_swap_i16,
byte_swap_i32,
byte_swap_i64,
byte_swap_i128,
byte_swap_uint,
byte_swap_int,
};
count_zeros8 :: proc(i: u8) -> u8 { return 8 - count_ones8(i); }
count_zeros16 :: proc(i: u16) -> u16 { return 16 - count_ones16(i); }
count_zeros32 :: proc(i: u32) -> u32 { return 32 - count_ones32(i); }
count_zeros64 :: proc(i: u64) -> u64 { return 64 - count_ones64(i); }
rotate_left8 :: proc(x: u8, k: int) -> u8 {
n :: 8;
s := uint(k) & (n-1);
return x <<s | x>>(n-s);
}
rotate_left16 :: proc(x: u16, k: int) -> u16 {
n :: 16;
s := uint(k) & (n-1);
return x <<s | x>>(n-s);
}
rotate_left32 :: proc(x: u32, k: int) -> u32 {
n :: 32;
s := uint(k) & (n-1);
return x <<s | x>>(n-s);
}
rotate_left64 :: proc(x: u64, k: int) -> u64 {
n :: 64;
s := uint(k) & (n-1);
return x <<s | x>>(n-s);
}
rotate_left :: proc(x: uint, k: int) -> uint {
n :: 8*size_of(uint);
s := uint(k) & (n-1);
return x <<s | x>>(n-s);
}
from_be_u8 :: proc(i: u8) -> u8 { return i; }
from_be_u16 :: proc(i: u16) -> u16 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
from_be_u32 :: proc(i: u32) -> u32 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
from_be_u64 :: proc(i: u64) -> u64 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
from_be_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
from_le_u8 :: proc(i: u8) -> u8 { return i; }
from_le_u16 :: proc(i: u16) -> u16 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
from_le_u32 :: proc(i: u32) -> u32 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
from_le_u64 :: proc(i: u64) -> u64 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
from_le_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
to_be_u8 :: proc(i: u8) -> u8 { return i; }
to_be_u16 :: proc(i: u16) -> u16 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
to_be_u32 :: proc(i: u32) -> u32 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
to_be_u64 :: proc(i: u64) -> u64 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
to_be_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
to_le_u8 :: proc(i: u8) -> u8 { return i; }
to_le_u16 :: proc(i: u16) -> u16 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
to_le_u32 :: proc(i: u32) -> u32 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
to_le_u64 :: proc(i: u64) -> u64 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
to_le_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
@(default_calling_convention="none")
foreign {
@(link_name="llvm.uadd.with.overflow.i8") overflowing_add_u8 :: proc(lhs, rhs: u8) -> (u8, bool) ---
@(link_name="llvm.sadd.with.overflow.i8") overflowing_add_i8 :: proc(lhs, rhs: i8) -> (i8, bool) ---
@(link_name="llvm.uadd.with.overflow.i16") overflowing_add_u16 :: proc(lhs, rhs: u16) -> (u16, bool) ---
@(link_name="llvm.sadd.with.overflow.i16") overflowing_add_i16 :: proc(lhs, rhs: i16) -> (i16, bool) ---
@(link_name="llvm.uadd.with.overflow.i32") overflowing_add_u32 :: proc(lhs, rhs: u32) -> (u32, bool) ---
@(link_name="llvm.sadd.with.overflow.i32") overflowing_add_i32 :: proc(lhs, rhs: i32) -> (i32, bool) ---
@(link_name="llvm.uadd.with.overflow.i64") overflowing_add_u64 :: proc(lhs, rhs: u64) -> (u64, bool) ---
@(link_name="llvm.sadd.with.overflow.i64") overflowing_add_i64 :: proc(lhs, rhs: i64) -> (i64, bool) ---
}
overflowing_add_uint :: proc(lhs, rhs: uint) -> (uint, bool) {
when size_of(uint) == size_of(u32) {
x, ok := overflowing_add_u32(u32(lhs), u32(rhs));
return uint(x), ok;
} else {
x, ok := overflowing_add_u64(u64(lhs), u64(rhs));
return uint(x), ok;
}
}
overflowing_add_int :: proc(lhs, rhs: int) -> (int, bool) {
when size_of(int) == size_of(i32) {
x, ok := overflowing_add_i32(i32(lhs), i32(rhs));
return int(x), ok;
} else {
x, ok := overflowing_add_i64(i64(lhs), i64(rhs));
return int(x), ok;
}
}
overflowing_add :: proc{
overflowing_add_u8, overflowing_add_i8,
overflowing_add_u16, overflowing_add_i16,
overflowing_add_u32, overflowing_add_i32,
overflowing_add_u64, overflowing_add_i64,
overflowing_add_uint, overflowing_add_int,
};
@(default_calling_convention="none")
foreign {
@(link_name="llvm.usub.with.overflow.i8") overflowing_sub_u8 :: proc(lhs, rhs: u8) -> (u8, bool) ---
@(link_name="llvm.ssub.with.overflow.i8") overflowing_sub_i8 :: proc(lhs, rhs: i8) -> (i8, bool) ---
@(link_name="llvm.usub.with.overflow.i16") overflowing_sub_u16 :: proc(lhs, rhs: u16) -> (u16, bool) ---
@(link_name="llvm.ssub.with.overflow.i16") overflowing_sub_i16 :: proc(lhs, rhs: i16) -> (i16, bool) ---
@(link_name="llvm.usub.with.overflow.i32") overflowing_sub_u32 :: proc(lhs, rhs: u32) -> (u32, bool) ---
@(link_name="llvm.ssub.with.overflow.i32") overflowing_sub_i32 :: proc(lhs, rhs: i32) -> (i32, bool) ---
@(link_name="llvm.usub.with.overflow.i64") overflowing_sub_u64 :: proc(lhs, rhs: u64) -> (u64, bool) ---
@(link_name="llvm.ssub.with.overflow.i64") overflowing_sub_i64 :: proc(lhs, rhs: i64) -> (i64, bool) ---
}
overflowing_sub_uint :: proc(lhs, rhs: uint) -> (uint, bool) {
when size_of(uint) == size_of(u32) {
x, ok := overflowing_sub_u32(u32(lhs), u32(rhs));
return uint(x), ok;
} else {
x, ok := overflowing_sub_u64(u64(lhs), u64(rhs));
return uint(x), ok;
}
}
overflowing_sub_int :: proc(lhs, rhs: int) -> (int, bool) {
when size_of(int) == size_of(i32) {
x, ok := overflowing_sub_i32(i32(lhs), i32(rhs));
return int(x), ok;
} else {
x, ok := overflowing_sub_i64(i64(lhs), i64(rhs));
return int(x), ok;
}
}
overflowing_sub :: proc{
overflowing_sub_u8, overflowing_sub_i8,
overflowing_sub_u16, overflowing_sub_i16,
overflowing_sub_u32, overflowing_sub_i32,
overflowing_sub_u64, overflowing_sub_i64,
overflowing_sub_uint, overflowing_sub_int,
};
@(default_calling_convention="none")
foreign {
@(link_name="llvm.umul.with.overflow.i8") overflowing_mul_u8 :: proc(lhs, rhs: u8) -> (u8, bool) ---
@(link_name="llvm.smul.with.overflow.i8") overflowing_mul_i8 :: proc(lhs, rhs: i8) -> (i8, bool) ---
@(link_name="llvm.umul.with.overflow.i16") overflowing_mul_u16 :: proc(lhs, rhs: u16) -> (u16, bool) ---
@(link_name="llvm.smul.with.overflow.i16") overflowing_mul_i16 :: proc(lhs, rhs: i16) -> (i16, bool) ---
@(link_name="llvm.umul.with.overflow.i32") overflowing_mul_u32 :: proc(lhs, rhs: u32) -> (u32, bool) ---
@(link_name="llvm.smul.with.overflow.i32") overflowing_mul_i32 :: proc(lhs, rhs: i32) -> (i32, bool) ---
@(link_name="llvm.umul.with.overflow.i64") overflowing_mul_u64 :: proc(lhs, rhs: u64) -> (u64, bool) ---
@(link_name="llvm.smul.with.overflow.i64") overflowing_mul_i64 :: proc(lhs, rhs: i64) -> (i64, bool) ---
}
overflowing_mul_uint :: proc(lhs, rhs: uint) -> (uint, bool) {
when size_of(uint) == size_of(u32) {
x, ok := overflowing_mul_u32(u32(lhs), u32(rhs));
return uint(x), ok;
} else {
x, ok := overflowing_mul_u64(u64(lhs), u64(rhs));
return uint(x), ok;
}
}
overflowing_mul_int :: proc(lhs, rhs: int) -> (int, bool) {
when size_of(int) == size_of(i32) {
x, ok := overflowing_mul_i32(i32(lhs), i32(rhs));
return int(x), ok;
} else {
x, ok := overflowing_mul_i64(i64(lhs), i64(rhs));
return int(x), ok;
}
}
overflowing_mul :: proc{
overflowing_mul_u8, overflowing_mul_i8,
overflowing_mul_u16, overflowing_mul_i16,
overflowing_mul_u32, overflowing_mul_i32,
overflowing_mul_u64, overflowing_mul_i64,
overflowing_mul_uint, overflowing_mul_int,
};
len_u8 :: proc(x: u8) -> int {
return int(len_u8_table[x]);
}
len_u16 :: proc(x: u16) -> (n: int) {
x := x;
if x >= 1<<8 {
x >>= 8;
n = 8;
}
return n + int(len_u8_table[x]);
}
len_u32 :: proc(x: u32) -> (n: int) {
x := x;
if x >= 1<<16 {
x >>= 16;
n = 16;
}
if x >= 1<<8 {
x >>= 8;
n += 8;
}
return n + int(len_u8_table[x]);
}
len_u64 :: proc(x: u64) -> (n: int) {
x := x;
if x >= 1<<32 {
x >>= 32;
n = 32;
}
if x >= 1<<16 {
x >>= 16;
n += 16;
}
if x >= 1<<8 {
x >>= 8;
n += 8;
}
return n + int(len_u8_table[x]);
}
len_uint :: proc(x: uint) -> (n: int) {
when size_of(uint) == size_of(u64) {
return len_u64(u64(x));
} else {
return len_u32(u32(x));
}
}
// returns the minimum number of bits required to represent x
len :: proc{len_u8, len_u16, len_u32, len_u64, len_uint};
add_u32 :: proc(x, y, carry: u32) -> (sum, carry_out: u32) {
yc := y + carry;
sum = x + yc;
if sum < x || yc < y {
carry_out = 1;
}
return;
}
add_u64 :: proc(x, y, carry: u64) -> (sum, carry_out: u64) {
yc := y + carry;
sum = x + yc;
if sum < x || yc < y {
carry_out = 1;
}
return;
}
add_uint :: proc(x, y, carry: uint) -> (sum, carry_out: uint) {
yc := y + carry;
sum = x + yc;
if sum < x || yc < y {
carry_out = 1;
}
return;
}
add :: proc{add_u32, add_u64, add_uint};
sub_u32 :: proc(x, y, borrow: u32) -> (diff, borrow_out: u32) {
yb := y + borrow;
diff = x - yb;
if diff > x || yb < y {
borrow_out = 1;
}
return;
}
sub_u64 :: proc(x, y, borrow: u64) -> (diff, borrow_out: u64) {
yb := y + borrow;
diff = x - yb;
if diff > x || yb < y {
borrow_out = 1;
}
return;
}
sub_uint :: proc(x, y, borrow: uint) -> (diff, borrow_out: uint) {
yb := y + borrow;
diff = x - yb;
if diff > x || yb < y {
borrow_out = 1;
}
return;
}
sub :: proc{sub_u32, sub_u64, sub_uint};
mul_u32 :: proc(x, y: u32) -> (hi, lo: u32) {
z := u64(x) * u64(y);
hi, lo = u32(z>>32), u32(z);
return;
}
mul_u64 :: proc(x, y: u64) -> (hi, lo: u64) {
mask :: 1<<32 - 1;
x0, x1 := x & mask, x >> 32;
y0, y1 := y & mask, y >> 32;
w0 := x0 * y0;
t := x1*y0 + w0>>32;
w1, w2 := t & mask, t >> 32;
w1 += x0 * y1;
hi = x1*y1 + w2 + w1>>32;
lo = x * y;
return;
}
mul_uint :: proc(x, y: uint) -> (hi, lo: uint) {
when size_of(uint) == size_of(u32) {
a, b := mul_u32(u32(x), u32(y));
} else {
#assert(size_of(uint) == size_of(u64));
a, b := mul_u64(u64(x), u64(y));
}
return uint(a), uint(b);
}
mul :: proc{mul_u32, mul_u64, mul_uint};
div_u32 :: proc(hi, lo, y: u32) -> (quo, rem: u32) {
assert(y != 0 && y <= hi);
z := u64(hi)<<32 | u64(lo);
quo, rem = u32(z/u64(y)), u32(z%u64(y));
return;
}
div_u64 :: proc(hi, lo, y: u64) -> (quo, rem: u64) {
y := y;
two32 :: 1 << 32;
mask32 :: two32 - 1;
if y == 0 {
panic("divide error");
}
if y <= hi {
panic("overflow error");
}
s := uint(leading_zeros_u64(y));
y <<= s;
yn1 := y >> 32;
yn0 := y & mask32;
un32 := hi<<s | lo>>(64-s);
un10 := lo << s;
un1 := un10 >> 32;
un0 := un10 & mask32;
q1 := un32 / yn1;
rhat := un32 - q1*yn1;
for q1 >= two32 || q1*yn0 > two32*rhat+un1 {
q1 -= 1;
rhat += yn1;
if rhat >= two32 {
break;
}
}
un21 := un32*two32 + un1 - q1*y;
q0 := un21 / yn1;
rhat = un21 - q0*yn1;
for q0 >= two32 || q0*yn0 > two32*rhat+un0 {
q0 -= 1;
rhat += yn1;
if rhat >= two32 {
break;
}
}
return q1*two32 + q0, (un21*two32 + un0 - q0*y) >> s;
}
div_uint :: proc(hi, lo, y: uint) -> (quo, rem: uint) {
when size_of(uint) == size_of(u32) {
a, b := div_u32(u32(hi), u32(lo), u32(y));
} else {
#assert(size_of(uint) == size_of(u64));
a, b := div_u64(u64(hi), u64(lo), u64(y));
}
return uint(a), uint(b);
}
div :: proc{div_u32, div_u64, div_uint};
is_power_of_two_u8 :: proc(i: u8) -> bool { return i > 0 && (i & (i-1)) == 0; }
is_power_of_two_i8 :: proc(i: i8) -> bool { return i > 0 && (i & (i-1)) == 0; }
is_power_of_two_u16 :: proc(i: u16) -> bool { return i > 0 && (i & (i-1)) == 0; }
is_power_of_two_i16 :: proc(i: i16) -> bool { return i > 0 && (i & (i-1)) == 0; }
is_power_of_two_u32 :: proc(i: u32) -> bool { return i > 0 && (i & (i-1)) == 0; }
is_power_of_two_i32 :: proc(i: i32) -> bool { return i > 0 && (i & (i-1)) == 0; }
is_power_of_two_u64 :: proc(i: u64) -> bool { return i > 0 && (i & (i-1)) == 0; }
is_power_of_two_i64 :: proc(i: i64) -> bool { return i > 0 && (i & (i-1)) == 0; }
is_power_of_two_uint :: proc(i: uint) -> bool { return i > 0 && (i & (i-1)) == 0; }
is_power_of_two_int :: proc(i: int) -> bool { return i > 0 && (i & (i-1)) == 0; }
is_power_of_two :: proc{
is_power_of_two_u8, is_power_of_two_i8,
is_power_of_two_u16, is_power_of_two_i16,
is_power_of_two_u32, is_power_of_two_i32,
is_power_of_two_u64, is_power_of_two_i64,
is_power_of_two_uint, is_power_of_two_int,
};
@private
len_u8_table := [256]u8{
0 = 0,
1 = 1,
2..<4 = 2,
4..<8 = 3,
8..<16 = 4,
16..<32 = 5,
32..<64 = 6,
64..<128 = 7,
128..<256 = 8,
};
bitfield_extract_u8 :: proc(value: u8, offset, bits: uint) -> u8 { return (value >> offset) & u8(1<<bits - 1); }
bitfield_extract_u16 :: proc(value: u16, offset, bits: uint) -> u16 { return (value >> offset) & u16(1<<bits - 1); }
bitfield_extract_u32 :: proc(value: u32, offset, bits: uint) -> u32 { return (value >> offset) & u32(1<<bits - 1); }
bitfield_extract_u64 :: proc(value: u64, offset, bits: uint) -> u64 { return (value >> offset) & u64(1<<bits - 1); }
bitfield_extract_u128 :: proc(value: u128, offset, bits: uint) -> u128 { return (value >> offset) & u128(1<<bits - 1); }
bitfield_extract_uint :: proc(value: uint, offset, bits: uint) -> uint { return (value >> offset) & uint(1<<bits - 1); }
bitfield_extract_i8 :: proc(value: i8, offset, bits: uint) -> i8 {
v := (u8(value) >> offset) & u8(1<<bits - 1);
m := u8(1<<(bits-1));
r := (v~m) - m;
return i8(r);
}
bitfield_extract_i16 :: proc(value: i16, offset, bits: uint) -> i16 {
v := (u16(value) >> offset) & u16(1<<bits - 1);
m := u16(1<<(bits-1));
r := (v~m) - m;
return i16(r);
}
bitfield_extract_i32 :: proc(value: i32, offset, bits: uint) -> i32 {
v := (u32(value) >> offset) & u32(1<<bits - 1);
m := u32(1<<(bits-1));
r := (v~m) - m;
return i32(r);
}
bitfield_extract_i64 :: proc(value: i64, offset, bits: uint) -> i64 {
v := (u64(value) >> offset) & u64(1<<bits - 1);
m := u64(1<<(bits-1));
r := (v~m) - m;
return i64(r);
}
bitfield_extract_i128 :: proc(value: i128, offset, bits: uint) -> i128 {
v := (u128(value) >> offset) & u128(1<<bits - 1);
m := u128(1<<(bits-1));
r := (v~m) - m;
return i128(r);
}
bitfield_extract_int :: proc(value: int, offset, bits: uint) -> int {
v := (uint(value) >> offset) & uint(1<<bits - 1);
m := uint(1<<(bits-1));
r := (v~m) - m;
return int(r);
}
bitfield_extract :: proc{
bitfield_extract_u8,
bitfield_extract_u16,
bitfield_extract_u32,
bitfield_extract_u64,
bitfield_extract_u128,
bitfield_extract_uint,
bitfield_extract_i8,
bitfield_extract_i16,
bitfield_extract_i32,
bitfield_extract_i64,
bitfield_extract_i128,
bitfield_extract_int,
};
bitfield_insert_u8 :: proc(base, insert: u8, offset, bits: uint) -> u8 {
mask := u8(1<<bits - 1);
return (base &~ (mask<<offset)) | ((insert&mask) << offset);
}
bitfield_insert_u16 :: proc(base, insert: u16, offset, bits: uint) -> u16 {
mask := u16(1<<bits - 1);
return (base &~ (mask<<offset)) | ((insert&mask) << offset);
}
bitfield_insert_u32 :: proc(base, insert: u32, offset, bits: uint) -> u32 {
mask := u32(1<<bits - 1);
return (base &~ (mask<<offset)) | ((insert&mask) << offset);
}
bitfield_insert_u64 :: proc(base, insert: u64, offset, bits: uint) -> u64 {
mask := u64(1<<bits - 1);
return (base &~ (mask<<offset)) | ((insert&mask) << offset);
}
bitfield_insert_u128 :: proc(base, insert: u128, offset, bits: uint) -> u128 {
mask := u128(1<<bits - 1);
return (base &~ (mask<<offset)) | ((insert&mask) << offset);
}
bitfield_insert_uint :: proc(base, insert: uint, offset, bits: uint) -> uint {
mask := uint(1<<bits - 1);
return (base &~ (mask<<offset)) | ((insert&mask) << offset);
}
bitfield_insert_i8 :: proc(base, insert: i8, offset, bits: uint) -> i8 {
mask := i8(1<<bits - 1);
return (base &~ (mask<<offset)) | ((insert&mask) << offset);
}
bitfield_insert_i16 :: proc(base, insert: i16, offset, bits: uint) -> i16 {
mask := i16(1<<bits - 1);
return (base &~ (mask<<offset)) | ((insert&mask) << offset);
}
bitfield_insert_i32 :: proc(base, insert: i32, offset, bits: uint) -> i32 {
mask := i32(1<<bits - 1);
return (base &~ (mask<<offset)) | ((insert&mask) << offset);
}
bitfield_insert_i64 :: proc(base, insert: i64, offset, bits: uint) -> i64 {
mask := i64(1<<bits - 1);
return (base &~ (mask<<offset)) | ((insert&mask) << offset);
}
bitfield_insert_i128 :: proc(base, insert: i128, offset, bits: uint) -> i128 {
mask := i128(1<<bits - 1);
return (base &~ (mask<<offset)) | ((insert&mask) << offset);
}
bitfield_insert_int :: proc(base, insert: int, offset, bits: uint) -> int {
mask := int(1<<bits - 1);
return (base &~ (mask<<offset)) | ((insert&mask) << offset);
}
bitfield_insert :: proc{
bitfield_insert_u8,
bitfield_insert_u16,
bitfield_insert_u32,
bitfield_insert_u64,
bitfield_insert_u128,
bitfield_insert_uint,
bitfield_insert_i8,
bitfield_insert_i16,
bitfield_insert_i32,
bitfield_insert_i64,
bitfield_insert_i128,
bitfield_insert_int,
};
+133
View File
@@ -0,0 +1,133 @@
package math_fixed
import "core:math"
import "core:strconv"
import "intrinsics"
_ :: intrinsics;
Fixed :: struct($Backing: typeid, Fraction_Width: uint)
where
intrinsics.type_is_integer(Backing),
0 <= Fraction_Width,
Fraction_Width <= 8*size_of(Backing) {
i: Backing,
}
Fixed4_4 :: distinct Fixed(i8, 4);
Fixed5_3 :: distinct Fixed(i8, 3);
Fixed6_2 :: distinct Fixed(i8, 2);
Fixed7_1 :: distinct Fixed(i8, 1);
Fixed8_8 :: distinct Fixed(i16, 8);
Fixed13_3 :: distinct Fixed(i16, 3);
Fixed16_16 :: distinct Fixed(i32, 16);
Fixed26_6 :: distinct Fixed(i32, 6);
Fixed32_32 :: distinct Fixed(i64, 32);
Fixed52_12 :: distinct Fixed(i64, 12);
init_from_f64 :: proc(x: ^$T/Fixed($Backing, $Fraction_Width), val: f64) {
i, f := math.modf(val);
x.i = Backing(f * (1<<Fraction_Width));
x.i &= 1<<Fraction_Width - 1;
x.i |= Backing(i) << Fraction_Width;
}
init_from_parts :: proc(x: ^$T/Fixed($Backing, $Fraction_Width), integer, fraction: Backing) {
i, f := math.modf(val);
x.i = fraction;
x.i &= 1<<Fraction_Width - 1;
x.i |= integer;
}
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;
}
add :: proc(x, y: $T/Fixed) -> T {
return {x.i + y.i};
}
sub :: proc(x, y: $T/Fixed) -> T {
return {x.i - y.i};
}
mul :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) {
z.i = intrinsics.fixed_point_mul(x.i, y.i, Fraction_Width);
return;
}
mul_sat :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) {
z.i = intrinsics.fixed_point_mul_sat(x.i, y.i, Fraction_Width);
return;
}
div :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) {
z.i = intrinsics.fixed_point_div(x.i, y.i, Fraction_Width);
return;
}
div_sat :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) {
z.i = intrinsics.fixed_point_div_sat(x.i, y.i, Fraction_Width);
return;
}
floor :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing {
return x.i >> Fraction_Width;
}
ceil :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing {
Integer :: 8*size_of(Backing) - Fraction_Width;
return (x.i + (1 << Integer-1)) >> Fraction_Width;
}
round :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing {
Integer :: 8*size_of(Backing) - Fraction_Width;
return (x.i + (1 << (Integer - 1))) >> Fraction_Width;
}
append :: proc(dst: []byte, x: $T/Fixed($Backing, $Fraction_Width)) -> string {
x := x;
buf: [48]byte;
i := 0;
if x.i < 0 {
buf[i] = '-';
i += 1;
x.i = -x.i;
}
integer := x.i >> Fraction_Width;
fraction := x.i & (1<<Fraction_Width - 1);
s := strconv.append_uint(buf[i:], u64(integer), 10);
i += len(s);
if fraction != 0 {
buf[i] = '.';
i += 1;
for fraction > 0 {
fraction *= 10;
buf[i] = byte('0' + (fraction>>Fraction_Width));
i += 1;
fraction &= 1<<Fraction_Width - 1;
}
}
n := copy(dst, buf[:i]);
return string(dst[:i]);
}
to_string :: proc(x: $T/Fixed($Backing, $Fraction_Width), allocator := context.allocator) -> string {
buf: [48]byte;
s := append(buf[:], x);
str := make([]byte, len(s), allocator);
copy(str, s);
return string(str);
}
+553
View File
@@ -0,0 +1,553 @@
package linalg
import "builtin"
import "core:math"
radians :: proc(degrees: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = degrees * RAD_PER_DEG;
}
} else {
out = degrees * RAD_PER_DEG;
}
return;
}
degrees :: proc(radians: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = radians * DEG_PER_RAD;
}
} else {
out = radians * DEG_PER_RAD;
}
return;
}
min_double :: proc(a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = builtin.min(a[i], b[i]);
}
} else {
out = builtin.min(a, b);
}
return;
}
min_single :: proc(a: $T) -> (out: ELEM_TYPE(T)) where IS_NUMERIC(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
N :: len(T);
when N == 1 {
out = a[0];
} else when N == 2 {
out = builtin.min(a[0], a[1]);
} else {
out = builtin.min(a[0], a[1]);
for i in 2..<N {
out = builtin.min(out, a[i]);
}
}
} else {
out = a;
}
return;
}
min_triple :: proc(a, b, c: $T) -> T where IS_NUMERIC(ELEM_TYPE(T)) {
return min_double(a, min_double(b, c));
}
min :: proc{min_single, min_double, min_triple};
max_double :: proc(a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = builtin.max(a[i], b[i]);
}
} else {
out = builtin.max(a, b);
}
return;
}
max_single :: proc(a: $T) -> (out: ELEM_TYPE(T)) where IS_NUMERIC(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
N :: len(T);
when N == 1 {
out = a[0];
} else when N == 2 {
out = builtin.max(a[0], a[1]);
} else when N == 3 {
out = builtin.max(a[0], a[1], a[3]);
}else {
out = builtin.max(a[0], a[1]);
for i in 2..<N {
out = builtin.max(out, a[i]);
}
}
} else {
out = a;
}
return;
}
max_triple :: proc(a, b, c: $T) -> T where IS_NUMERIC(ELEM_TYPE(T)) {
return max_double(a, max_double(b, c));
}
max :: proc{max_single, max_double, max_triple};
abs :: proc(a: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = builtin.abs(a[i]);
}
} else {
out = builtin.abs(a);
}
return;
}
sign :: proc(a: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = #force_inline math.sign(a[i]);
}
} else {
out = #force_inline math.sign(a);
}
return;
}
clamp :: proc(x, a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = builtin.clamp(x[i], a[i], b[i]);
}
} else {
out = builtin.clamp(x, a, b);
}
return;
}
saturate :: proc(x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
return clamp(x, 0.0, 1.0);
}
lerp :: proc(a, b, t: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = a[i]*(1-t[i]) + b[i]*t[i];
}
} else {
out = a * (1.0 - t) + b * t;
}
return;
}
mix :: proc(a, b, t: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = a[i]*(1-t[i]) + b[i]*t[i];
}
} else {
out = a * (1.0 - t) + b * t;
}
return;
}
unlerp :: proc(a, b, x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
return (x - a) / (b - a);
}
step :: proc(e, x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = x[i] < e[i] ? 0.0 : 1.0;
}
} else {
out = x < e ? 0.0 : 1.0;
}
return;
}
smoothstep :: proc(e0, e1, x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
t := saturate(unlerp(e0, e1, x));
return t * t * (3.0 - 2.0 * t);
}
smootherstep :: proc(e0, e1, x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
t := saturate(unlerp(e0, e1, x));
return t * t * t * (t * (6*t - 15) + 10);
}
sqrt :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = math.sqrt(x[i]);
}
} else {
out = math.sqrt(x);
}
return;
}
inverse_sqrt :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = 1.0/math.sqrt(x[i]);
}
} else {
out = 1.0/math.sqrt(x);
}
return;
}
cos :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = math.cos(x[i]);
}
} else {
out = math.cos(x);
}
return;
}
sin :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = math.sin(x[i]);
}
} else {
out = math.sin(x);
}
return;
}
tan :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = math.tan(x[i]);
}
} else {
out = math.tan(x);
}
return;
}
acos :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = math.acos(x[i]);
}
} else {
out = math.acos(x);
}
return;
}
asin :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = math.asin(x[i]);
}
} else {
out = math.asin(x);
}
return;
}
atan :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = math.atan(x[i]);
}
} else {
out = math.atan(x);
}
return;
}
atan2 :: proc(y, x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = math.atan2(y[i], x[i]);
}
} else {
out = math.atan2(y, x);
}
return;
}
ln :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = math.ln(x[i]);
}
} else {
out = math.ln(x);
}
return;
}
log2 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = INVLN2 * math.ln(x[i]);
}
} else {
out = INVLN2 * math.ln(x);
}
return;
}
log10 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = INVLN10 * math.ln(x[i]);
}
} else {
out = INVLN10 * math.ln(x);
}
return;
}
log :: proc(x, b: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = math.ln(x[i]) / math.ln(cast(ELEM_TYPE(T))b[i]);
}
} else {
out = INVLN10 * math.ln(x) / math.ln(cast(ELEM_TYPE(T))b);
}
return;
}
exp :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = math.exp(x[i]);
}
} else {
out = math.exp(x);
}
return;
}
exp2 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = math.exp(LN2 * x[i]);
}
} else {
out = math.exp(LN2 * x);
}
return;
}
exp10 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = math.exp(LN10 * x[i]);
}
} else {
out = math.exp(LN10 * x);
}
return;
}
pow :: proc(x, e: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = math.pow(x[i], e[i]);
}
} else {
out = math.pow(x, e);
}
return;
}
ceil :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = #force_inline math.ceil(x[i]);
}
} else {
out = #force_inline math.ceil(x);
}
return;
}
floor :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = #force_inline math.floor(x[i]);
}
} else {
out = #force_inline math.floor(x);
}
return;
}
round :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = #force_inline math.round(x[i]);
}
} else {
out = #force_inline math.round(x);
}
return;
}
fract :: proc(x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
f := #force_inline floor(x);
return x - f;
}
mod :: proc(x, m: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
f := #force_inline floor(x / m);
return x - f * m;
}
face_forward :: proc(N, I, N_ref: $T) -> (out: T) where IS_ARRAY(T), IS_FLOAT(ELEM_TYPE(T)) {
return dot(N_ref, I) < 0 ? N : -N;
}
distance :: proc(p0, p1: $V/[$N]$E) -> E where IS_NUMERIC(E) {
return length(p1 - p0);
}
reflect :: proc(I, N: $T) -> (out: T) where IS_ARRAY(T), IS_FLOAT(ELEM_TYPE(T)) {
b := n * (2 * dot(n, i));
return i - b;
}
refract :: proc(I, N: $T) -> (out: T) where IS_ARRAY(T), IS_FLOAT(ELEM_TYPE(T)) {
dv := dot(n, i);
k := 1 - eta*eta - (1 - dv*dv);
a := i * eta;
b := n * eta*dv*math.sqrt(k);
return (a - b) * E(int(k >= 0));
}
is_nan_single :: proc(x: $T) -> bool where IS_FLOAT(T) {
return #force_inline math.is_nan(x);
}
is_nan_array :: proc(x: $A/[$N]$T) -> (out: [N]bool) where IS_FLOAT(T) {
for i in 0..<N {
out[i] = #force_inline is_nan(x[i]);
}
return;
}
is_inf_single :: proc(x: $T) -> bool where IS_FLOAT(T) {
return #force_inline math.is_inf(x);
}
is_inf_array :: proc(x: $A/[$N]$T) -> (out: [N]bool) where IS_FLOAT(T) {
for i in 0..<N {
out[i] = #force_inline is_inf(x[i]);
}
return;
}
classify_single :: proc(x: $T) -> math.Float_Class where IS_FLOAT(T) {
return #force_inline math.classify(x);
}
classify_array :: proc(x: $A/[$N]$T) -> (out: [N]math.Float_Class) where IS_FLOAT(T) {
for i in 0..<N {
out[i] = #force_inline classify_single(x[i]);
}
return;
}
is_nan :: proc{is_nan_single, is_nan_array};
is_inf :: proc{is_inf_single, is_inf_array};
classify :: proc{classify_single, classify_array};
less_than_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x < y; }
less_than_equal_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x <= y; }
greater_than_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x > y; }
greater_than_equal_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x >= y; }
equal_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x == y; }
not_equal_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x != y; }
less_than_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
for i in 0..<N {
out[i] = x[i] < y[i];
}
return;
}
less_than_equal_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
for i in 0..<N {
out[i] = x[i] <= y[i];
}
return;
}
greater_than_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
for i in 0..<N {
out[i] = x[i] > y[i];
}
return;
}
greater_than_equal_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
for i in 0..<N {
out[i] = x[i] >= y[i];
}
return;
}
equal_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
for i in 0..<N {
out[i] = x[i] == y[i];
}
return;
}
not_equal_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
for i in 0..<N {
out[i] = x[i] != y[i];
}
return;
}
less_than :: proc{less_than_single, less_than_array};
less_than_equal :: proc{less_than_equal_single, less_than_equal_array};
greater_than :: proc{greater_than_single, greater_than_array};
greater_than_equal :: proc{greater_than_equal_single, greater_than_equal_array};
equal :: proc{equal_single, equal_array};
not_equal :: proc{not_equal_single, not_equal_array};
any :: proc(x: $A/[$N]bool) -> (out: bool) {
for e in x {
if x {
return true;
}
}
return false;
}
all :: proc(x: $A/[$N]bool) -> (out: bool) {
for e in x {
if !e {
return false;
}
}
return true;
}
not :: proc(x: $A/[$N]bool) -> (out: A) {
for e, i in x {
out[i] = !e;
}
return;
}
+368
View File
@@ -0,0 +1,368 @@
package linalg
import "core:math"
import "intrinsics"
// Generic
TAU :: 6.28318530717958647692528676655900576;
PI :: 3.14159265358979323846264338327950288;
E :: 2.71828182845904523536;
τ :: TAU;
π :: PI;
e :: E;
SQRT_TWO :: 1.41421356237309504880168872420969808;
SQRT_THREE :: 1.73205080756887729352744634150587236;
SQRT_FIVE :: 2.23606797749978969640917366873127623;
LN2 :: 0.693147180559945309417232121458176568;
LN10 :: 2.30258509299404568401799145468436421;
MAX_F64_PRECISION :: 16; // Maximum number of meaningful digits after the decimal point for 'f64'
MAX_F32_PRECISION :: 8; // Maximum number of meaningful digits after the decimal point for 'f32'
RAD_PER_DEG :: TAU/360.0;
DEG_PER_RAD :: 360.0/TAU;
@private IS_NUMERIC :: intrinsics.type_is_numeric;
@private IS_QUATERNION :: intrinsics.type_is_quaternion;
@private IS_ARRAY :: intrinsics.type_is_array;
@private IS_FLOAT :: intrinsics.type_is_float;
@private BASE_TYPE :: intrinsics.type_base_type;
@private ELEM_TYPE :: intrinsics.type_elem_type;
scalar_dot :: proc(a, b: $T) -> T where IS_FLOAT(T), !IS_ARRAY(T) {
return a * b;
}
vector_dot :: proc(a, b: $T/[$N]$E) -> (c: E) where IS_NUMERIC(E) {
for i in 0..<N {
c += a[i] * b[i];
}
return;
}
quaternion64_dot :: proc(a, b: $T/quaternion64) -> (c: f16) {
return a.w*a.w + a.x*b.x + a.y*b.y + a.z*b.z;
}
quaternion128_dot :: proc(a, b: $T/quaternion128) -> (c: f32) {
return a.w*a.w + a.x*b.x + a.y*b.y + a.z*b.z;
}
quaternion256_dot :: proc(a, b: $T/quaternion256) -> (c: f64) {
return a.w*a.w + a.x*b.x + a.y*b.y + a.z*b.z;
}
dot :: proc{scalar_dot, vector_dot, quaternion64_dot, quaternion128_dot, quaternion256_dot};
inner_product :: dot;
outer_product :: proc(a: $A/[$M]$E, b: $B/[$N]E) -> (out: [M][N]E) where IS_NUMERIC(E) {
for i in 0..<M {
for j in 0..<N {
out[i][j] = a[i]*b[j];
}
}
return;
}
quaternion_inverse :: proc(q: $Q) -> Q where IS_QUATERNION(Q) {
return conj(q) * quaternion(1.0/dot(q, q), 0, 0, 0);
}
scalar_cross :: proc(a, b: $T) -> T where IS_FLOAT(T), !IS_ARRAY(T) {
return a * b;
}
vector_cross2 :: proc(a, b: $T/[2]$E) -> E where IS_NUMERIC(E) {
return a[0]*b[1] - b[0]*a[1];
}
vector_cross3 :: proc(a, b: $T/[3]$E) -> (c: T) where IS_NUMERIC(E) {
c[0] = a[1]*b[2] - b[1]*a[2];
c[1] = a[2]*b[0] - b[2]*a[0];
c[2] = a[0]*b[1] - b[0]*a[1];
return;
}
quaternion_cross :: proc(q1, q2: $Q) -> (q3: Q) where IS_QUATERNION(Q) {
q3.x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y;
q3.y = q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z;
q3.z = q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x;
q3.w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z;
return;
}
vector_cross :: proc{scalar_cross, vector_cross2, vector_cross3};
cross :: proc{scalar_cross, vector_cross2, vector_cross3, quaternion_cross};
vector_normalize :: proc(v: $T/[$N]$E) -> T where IS_NUMERIC(E) {
return v / length(v);
}
quaternion_normalize :: proc(q: $Q) -> Q where IS_QUATERNION(Q) {
return q/abs(q);
}
normalize :: proc{vector_normalize, quaternion_normalize};
vector_normalize0 :: proc(v: $T/[$N]$E) -> T where IS_NUMERIC(E) {
m := length(v);
return 0 if m == 0 else v/m;
}
quaternion_normalize0 :: proc(q: $Q) -> Q where IS_QUATERNION(Q) {
m := abs(q);
return 0 if m == 0 else q/m;
}
normalize0 :: proc{vector_normalize0, quaternion_normalize0};
vector_length :: proc(v: $T/[$N]$E) -> E where IS_NUMERIC(E) {
return math.sqrt(dot(v, v));
}
vector_length2 :: proc(v: $T/[$N]$E) -> E where IS_NUMERIC(E) {
return dot(v, v);
}
quaternion_length :: proc(q: $Q) -> Q where IS_QUATERNION(Q) {
return abs(q);
}
quaternion_length2 :: proc(q: $Q) -> Q where IS_QUATERNION(Q) {
return dot(q, q);
}
scalar_triple_product :: proc(a, b, c: $T/[$N]$E) -> E where IS_NUMERIC(E) {
// a . (b x c)
// b . (c x a)
// c . (a x b)
return dot(a, cross(b, c));
}
vector_triple_product :: proc(a, b, c: $T/[$N]$E) -> T where IS_NUMERIC(E) {
// a x (b x c)
// (a . c)b - (a . b)c
return cross(a, cross(b, c));
}
length :: proc{vector_length, quaternion_length};
length2 :: proc{vector_length2, quaternion_length2};
projection :: proc(x, normal: $T/[$N]$E) -> T where IS_NUMERIC(E) {
return dot(x, normal) / dot(normal, normal) * normal;
}
identity :: proc($T: typeid/[$N][N]$E) -> (m: T) {
for i in 0..<N {
m[i][i] = E(1);
}
return m;
}
trace :: proc(m: $T/[$N][N]$E) -> (tr: E) {
for i in 0..<N {
tr += m[i][i];
}
return;
}
transpose :: proc(a: $T/[$N][$M]$E) -> (m: T) {
for j in 0..<M {
for i in 0..<N {
m[j][i] = a[i][j];
}
}
return;
}
matrix_mul :: proc(a, b: $M/[$N][N]$E) -> (c: M)
where !IS_ARRAY(E),
IS_NUMERIC(E) {
for i in 0..<N {
for k in 0..<N {
for j in 0..<N {
c[k][i] += a[j][i] * b[k][j];
}
}
}
return;
}
matrix_comp_mul :: proc(a, b: $M/[$J][$I]$E) -> (c: M)
where !IS_ARRAY(E),
IS_NUMERIC(E) {
for j in 0..<J {
for i in 0..<I {
c[j][i] = a[j][i] * b[j][i];
}
}
return;
}
matrix_mul_differ :: proc(a: $A/[$J][$I]$E, b: $B/[$K][J]E) -> (c: [K][I]E)
where !IS_ARRAY(E),
IS_NUMERIC(E),
I != K {
for k in 0..<K {
for j in 0..<J {
for i in 0..<I {
c[k][i] += a[j][i] * b[k][j];
}
}
}
return;
}
matrix_mul_vector :: proc(a: $A/[$I][$J]$E, b: $B/[I]E) -> (c: B)
where !IS_ARRAY(E),
IS_NUMERIC(E) {
for i in 0..<I {
for j in 0..<J {
c[j] += a[i][j] * b[i];
}
}
return;
}
quaternion_mul_quaternion :: proc(q1, q2: $Q) -> Q where IS_QUATERNION(Q) {
return q1 * q2;
}
quaternion64_mul_vector3 :: proc(q: $Q/quaternion64, v: $V/[3]$F/f16) -> V {
Raw_Quaternion :: struct {xyz: [3]f16, r: f16};
q := transmute(Raw_Quaternion)q;
v := transmute([3]f16)v;
t := cross(2*q.xyz, v);
return V(v + q.r*t + cross(q.xyz, t));
}
quaternion128_mul_vector3 :: proc(q: $Q/quaternion128, v: $V/[3]$F/f32) -> V {
Raw_Quaternion :: struct {xyz: [3]f32, r: f32};
q := transmute(Raw_Quaternion)q;
v := transmute([3]f32)v;
t := cross(2*q.xyz, v);
return V(v + q.r*t + cross(q.xyz, t));
}
quaternion256_mul_vector3 :: proc(q: $Q/quaternion256, v: $V/[3]$F/f64) -> V {
Raw_Quaternion :: struct {xyz: [3]f64, r: f64};
q := transmute(Raw_Quaternion)q;
v := transmute([3]f64)v;
t := cross(2*q.xyz, v);
return V(v + q.r*t + cross(q.xyz, t));
}
quaternion_mul_vector3 :: proc{quaternion64_mul_vector3, quaternion128_mul_vector3, quaternion256_mul_vector3};
mul :: proc{
matrix_mul,
matrix_mul_differ,
matrix_mul_vector,
quaternion64_mul_vector3,
quaternion128_mul_vector3,
quaternion256_mul_vector3,
quaternion_mul_quaternion,
};
vector_to_ptr :: proc(v: ^$V/[$N]$E) -> ^E where IS_NUMERIC(E), N > 0 #no_bounds_check {
return &v[0];
}
matrix_to_ptr :: proc(m: ^$A/[$I][$J]$E) -> ^E where IS_NUMERIC(E), I > 0, J > 0 #no_bounds_check {
return &m[0][0];
}
to_ptr :: proc{vector_to_ptr, matrix_to_ptr};
// Splines
vector_slerp :: proc(x, y: $T/[$N]$E, a: E) -> T {
cos_alpha := dot(x, y);
alpha := math.acos(cos_alpha);
sin_alpha := math.sin(alpha);
t1 := math.sin((1 - a) * alpha) / sin_alpha;
t2 := math.sin(a * alpha) / sin_alpha;
return x * t1 + y * t2;
}
catmull_rom :: proc(v1, v2, v3, v4: $T/[$N]$E, s: E) -> T {
s2 := s*s;
s3 := s2*s;
f1 := -s3 + 2 * s2 - s;
f2 := 3 * s3 - 5 * s2 + 2;
f3 := -3 * s3 + 4 * s2 + s;
f4 := s3 - s2;
return (f1 * v1 + f2 * v2 + f3 * v3 + f4 * v4) * 0.5;
}
hermite :: proc(v1, t1, v2, t2: $T/[$N]$E, s: E) -> T {
s2 := s*s;
s3 := s2*s;
f1 := 2 * s3 - 3 * s2 + 1;
f2 := -2 * s3 + 3 * s2;
f3 := s3 - 2 * s2 + s;
f4 := s3 - s2;
return f1 * v1 + f2 * v2 + f3 * t1 + f4 * t2;
}
cubic :: proc(v1, v2, v3, v4: $T/[$N]$E, s: E) -> T {
return ((v1 * s + v2) * s + v3) * s + v4;
}
array_cast :: proc(v: $A/[$N]$T, $Elem_Type: typeid) -> (w: [N]Elem_Type) {
for i in 0..<N {
w[i] = Elem_Type(v[i]);
}
return;
}
matrix_cast :: proc(v: $A/[$M][$N]$T, $Elem_Type: typeid) -> (w: [M][N]Elem_Type) {
for i in 0..<M {
for j in 0..<N {
w[i][j] = Elem_Type(v[i][j]);
}
}
return;
}
to_f32 :: #force_inline proc(v: $A/[$N]$T) -> [N]f32 { return array_cast(v, f32); }
to_f64 :: #force_inline proc(v: $A/[$N]$T) -> [N]f64 { return array_cast(v, f64); }
to_i8 :: #force_inline proc(v: $A/[$N]$T) -> [N]i8 { return array_cast(v, i8); }
to_i16 :: #force_inline proc(v: $A/[$N]$T) -> [N]i16 { return array_cast(v, i16); }
to_i32 :: #force_inline proc(v: $A/[$N]$T) -> [N]i32 { return array_cast(v, i32); }
to_i64 :: #force_inline proc(v: $A/[$N]$T) -> [N]i64 { return array_cast(v, i64); }
to_int :: #force_inline proc(v: $A/[$N]$T) -> [N]int { return array_cast(v, int); }
to_u8 :: #force_inline proc(v: $A/[$N]$T) -> [N]u8 { return array_cast(v, u8); }
to_u16 :: #force_inline proc(v: $A/[$N]$T) -> [N]u16 { return array_cast(v, u16); }
to_u32 :: #force_inline proc(v: $A/[$N]$T) -> [N]u32 { return array_cast(v, u32); }
to_u64 :: #force_inline proc(v: $A/[$N]$T) -> [N]u64 { return array_cast(v, u64); }
to_uint :: #force_inline proc(v: $A/[$N]$T) -> [N]uint { return array_cast(v, uint); }
to_complex32 :: #force_inline proc(v: $A/[$N]$T) -> [N]complex32 { return array_cast(v, complex32); }
to_complex64 :: #force_inline proc(v: $A/[$N]$T) -> [N]complex64 { return array_cast(v, complex64); }
to_complex128 :: #force_inline proc(v: $A/[$N]$T) -> [N]complex128 { return array_cast(v, complex128); }
to_quaternion64 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion64 { return array_cast(v, quaternion64); }
to_quaternion128 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion128 { return array_cast(v, quaternion128); }
to_quaternion256 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion256 { return array_cast(v, quaternion256); }
File diff suppressed because it is too large Load Diff
+127
View File
@@ -0,0 +1,127 @@
package linalg
Euler_Angle_Order :: enum {
// Tait-Bryan
XYZ,
XZY,
YXZ,
YZX,
ZXY,
ZYX,
// Proper Euler
XYX,
XZX,
YXY,
YZY,
ZXZ,
ZYZ,
}
quaternion_from_euler_angles :: proc{quaternion_from_euler_angles_f16, quaternion_from_euler_angles_f32, quaternion_from_euler_angles_f64};
quaternion_from_euler_angle_x :: proc{quaternion_from_euler_angle_x_f16, quaternion_from_euler_angle_x_f32, quaternion_from_euler_angle_x_f64};
quaternion_from_euler_angle_y :: proc{quaternion_from_euler_angle_y_f16, quaternion_from_euler_angle_y_f32, quaternion_from_euler_angle_y_f64};
quaternion_from_euler_angle_z :: proc{quaternion_from_euler_angle_z_f16, quaternion_from_euler_angle_z_f32, quaternion_from_euler_angle_z_f64};
quaternion_from_pitch_yaw_roll :: proc{quaternion_from_pitch_yaw_roll_f16, quaternion_from_pitch_yaw_roll_f32, quaternion_from_pitch_yaw_roll_f64};
euler_angles_from_quaternion :: proc{euler_angles_from_quaternion_f16, euler_angles_from_quaternion_f32, euler_angles_from_quaternion_f64};
euler_angles_xyz_from_quaternion :: proc{euler_angles_xyz_from_quaternion_f16, euler_angles_xyz_from_quaternion_f32, euler_angles_xyz_from_quaternion_f64};
euler_angles_yxz_from_quaternion :: proc{euler_angles_yxz_from_quaternion_f16, euler_angles_yxz_from_quaternion_f32, euler_angles_yxz_from_quaternion_f64};
euler_angles_xzx_from_quaternion :: proc{euler_angles_xzx_from_quaternion_f16, euler_angles_xzx_from_quaternion_f32, euler_angles_xzx_from_quaternion_f64};
euler_angles_xyx_from_quaternion :: proc{euler_angles_xyx_from_quaternion_f16, euler_angles_xyx_from_quaternion_f32, euler_angles_xyx_from_quaternion_f64};
euler_angles_yxy_from_quaternion :: proc{euler_angles_yxy_from_quaternion_f16, euler_angles_yxy_from_quaternion_f32, euler_angles_yxy_from_quaternion_f64};
euler_angles_yzy_from_quaternion :: proc{euler_angles_yzy_from_quaternion_f16, euler_angles_yzy_from_quaternion_f32, euler_angles_yzy_from_quaternion_f64};
euler_angles_zyz_from_quaternion :: proc{euler_angles_zyz_from_quaternion_f16, euler_angles_zyz_from_quaternion_f32, euler_angles_zyz_from_quaternion_f64};
euler_angles_zxz_from_quaternion :: proc{euler_angles_zxz_from_quaternion_f16, euler_angles_zxz_from_quaternion_f32, euler_angles_zxz_from_quaternion_f64};
euler_angles_xzy_from_quaternion :: proc{euler_angles_xzy_from_quaternion_f16, euler_angles_xzy_from_quaternion_f32, euler_angles_xzy_from_quaternion_f64};
euler_angles_yzx_from_quaternion :: proc{euler_angles_yzx_from_quaternion_f16, euler_angles_yzx_from_quaternion_f32, euler_angles_yzx_from_quaternion_f64};
euler_angles_zyx_from_quaternion :: proc{euler_angles_zyx_from_quaternion_f16, euler_angles_zyx_from_quaternion_f32, euler_angles_zyx_from_quaternion_f64};
euler_angles_zxy_from_quaternion :: proc{euler_angles_zxy_from_quaternion_f16, euler_angles_zxy_from_quaternion_f32, euler_angles_zxy_from_quaternion_f64};
roll_from_quaternion :: proc{roll_from_quaternion_f16, roll_from_quaternion_f32, roll_from_quaternion_f64};
pitch_from_quaternion :: proc{pitch_from_quaternion_f16, pitch_from_quaternion_f32, pitch_from_quaternion_f64};
yaw_from_quaternion :: proc{yaw_from_quaternion_f16, yaw_from_quaternion_f32, yaw_from_quaternion_f64};
pitch_yaw_roll_from_quaternion :: proc{pitch_yaw_roll_from_quaternion_f16, pitch_yaw_roll_from_quaternion_f32, pitch_yaw_roll_from_quaternion_f64};
matrix3_from_euler_angles :: proc{matrix3_from_euler_angles_f16, matrix3_from_euler_angles_f32, matrix3_from_euler_angles_f64};
matrix3_from_euler_angle_x :: proc{matrix3_from_euler_angle_x_f16, matrix3_from_euler_angle_x_f32, matrix3_from_euler_angle_x_f64};
matrix3_from_euler_angle_y :: proc{matrix3_from_euler_angle_y_f16, matrix3_from_euler_angle_y_f32, matrix3_from_euler_angle_y_f64};
matrix3_from_euler_angle_z :: proc{matrix3_from_euler_angle_z_f16, matrix3_from_euler_angle_z_f32, matrix3_from_euler_angle_z_f64};
matrix3_from_derived_euler_angle_x :: proc{matrix3_from_derived_euler_angle_x_f16, matrix3_from_derived_euler_angle_x_f32, matrix3_from_derived_euler_angle_x_f64};
matrix3_from_derived_euler_angle_y :: proc{matrix3_from_derived_euler_angle_y_f16, matrix3_from_derived_euler_angle_y_f32, matrix3_from_derived_euler_angle_y_f64};
matrix3_from_derived_euler_angle_z :: proc{matrix3_from_derived_euler_angle_z_f16, matrix3_from_derived_euler_angle_z_f32, matrix3_from_derived_euler_angle_z_f64};
matrix3_from_euler_angles_xy :: proc{matrix3_from_euler_angles_xy_f16, matrix3_from_euler_angles_xy_f32, matrix3_from_euler_angles_xy_f64};
matrix3_from_euler_angles_yx :: proc{matrix3_from_euler_angles_yx_f16, matrix3_from_euler_angles_yx_f32, matrix3_from_euler_angles_yx_f64};
matrix3_from_euler_angles_xz :: proc{matrix3_from_euler_angles_xz_f16, matrix3_from_euler_angles_xz_f32, matrix3_from_euler_angles_xz_f64};
matrix3_from_euler_angles_zx :: proc{matrix3_from_euler_angles_zx_f16, matrix3_from_euler_angles_zx_f32, matrix3_from_euler_angles_zx_f64};
matrix3_from_euler_angles_yz :: proc{matrix3_from_euler_angles_yz_f16, matrix3_from_euler_angles_yz_f32, matrix3_from_euler_angles_yz_f64};
matrix3_from_euler_angles_zy :: proc{matrix3_from_euler_angles_zy_f16, matrix3_from_euler_angles_zy_f32, matrix3_from_euler_angles_zy_f64};
matrix3_from_euler_angles_xyz :: proc{matrix3_from_euler_angles_xyz_f16, matrix3_from_euler_angles_xyz_f32, matrix3_from_euler_angles_xyz_f64};
matrix3_from_euler_angles_yxz :: proc{matrix3_from_euler_angles_yxz_f16, matrix3_from_euler_angles_yxz_f32, matrix3_from_euler_angles_yxz_f64};
matrix3_from_euler_angles_xzx :: proc{matrix3_from_euler_angles_xzx_f16, matrix3_from_euler_angles_xzx_f32, matrix3_from_euler_angles_xzx_f64};
matrix3_from_euler_angles_xyx :: proc{matrix3_from_euler_angles_xyx_f16, matrix3_from_euler_angles_xyx_f32, matrix3_from_euler_angles_xyx_f64};
matrix3_from_euler_angles_yxy :: proc{matrix3_from_euler_angles_yxy_f16, matrix3_from_euler_angles_yxy_f32, matrix3_from_euler_angles_yxy_f64};
matrix3_from_euler_angles_yzy :: proc{matrix3_from_euler_angles_yzy_f16, matrix3_from_euler_angles_yzy_f32, matrix3_from_euler_angles_yzy_f64};
matrix3_from_euler_angles_zyz :: proc{matrix3_from_euler_angles_zyz_f16, matrix3_from_euler_angles_zyz_f32, matrix3_from_euler_angles_zyz_f64};
matrix3_from_euler_angles_zxz :: proc{matrix3_from_euler_angles_zxz_f16, matrix3_from_euler_angles_zxz_f32, matrix3_from_euler_angles_zxz_f64};
matrix3_from_euler_angles_xzy :: proc{matrix3_from_euler_angles_xzy_f16, matrix3_from_euler_angles_xzy_f32, matrix3_from_euler_angles_xzy_f64};
matrix3_from_euler_angles_yzx :: proc{matrix3_from_euler_angles_yzx_f16, matrix3_from_euler_angles_yzx_f32, matrix3_from_euler_angles_yzx_f64};
matrix3_from_euler_angles_zyx :: proc{matrix3_from_euler_angles_zyx_f16, matrix3_from_euler_angles_zyx_f32, matrix3_from_euler_angles_zyx_f64};
matrix3_from_euler_angles_zxy :: proc{matrix3_from_euler_angles_zxy_f16, matrix3_from_euler_angles_zxy_f32, matrix3_from_euler_angles_zxy_f64};
matrix3_from_yaw_pitch_roll :: proc{matrix3_from_yaw_pitch_roll_f16, matrix3_from_yaw_pitch_roll_f32, matrix3_from_yaw_pitch_roll_f64};
euler_angles_from_matrix3 :: proc{euler_angles_from_matrix3_f16, euler_angles_from_matrix3_f32, euler_angles_from_matrix3_f64};
euler_angles_xyz_from_matrix3 :: proc{euler_angles_xyz_from_matrix3_f16, euler_angles_xyz_from_matrix3_f32, euler_angles_xyz_from_matrix3_f64};
euler_angles_yxz_from_matrix3 :: proc{euler_angles_yxz_from_matrix3_f16, euler_angles_yxz_from_matrix3_f32, euler_angles_yxz_from_matrix3_f64};
euler_angles_xzx_from_matrix3 :: proc{euler_angles_xzx_from_matrix3_f16, euler_angles_xzx_from_matrix3_f32, euler_angles_xzx_from_matrix3_f64};
euler_angles_xyx_from_matrix3 :: proc{euler_angles_xyx_from_matrix3_f16, euler_angles_xyx_from_matrix3_f32, euler_angles_xyx_from_matrix3_f64};
euler_angles_yxy_from_matrix3 :: proc{euler_angles_yxy_from_matrix3_f16, euler_angles_yxy_from_matrix3_f32, euler_angles_yxy_from_matrix3_f64};
euler_angles_yzy_from_matrix3 :: proc{euler_angles_yzy_from_matrix3_f16, euler_angles_yzy_from_matrix3_f32, euler_angles_yzy_from_matrix3_f64};
euler_angles_zyz_from_matrix3 :: proc{euler_angles_zyz_from_matrix3_f16, euler_angles_zyz_from_matrix3_f32, euler_angles_zyz_from_matrix3_f64};
euler_angles_zxz_from_matrix3 :: proc{euler_angles_zxz_from_matrix3_f16, euler_angles_zxz_from_matrix3_f32, euler_angles_zxz_from_matrix3_f64};
euler_angles_xzy_from_matrix3 :: proc{euler_angles_xzy_from_matrix3_f16, euler_angles_xzy_from_matrix3_f32, euler_angles_xzy_from_matrix3_f64};
euler_angles_yzx_from_matrix3 :: proc{euler_angles_yzx_from_matrix3_f16, euler_angles_yzx_from_matrix3_f32, euler_angles_yzx_from_matrix3_f64};
euler_angles_zyx_from_matrix3 :: proc{euler_angles_zyx_from_matrix3_f16, euler_angles_zyx_from_matrix3_f32, euler_angles_zyx_from_matrix3_f64};
euler_angles_zxy_from_matrix3 :: proc{euler_angles_zxy_from_matrix3_f16, euler_angles_zxy_from_matrix3_f32, euler_angles_zxy_from_matrix3_f64};
matrix4_from_euler_angles :: proc{matrix4_from_euler_angles_f16, matrix4_from_euler_angles_f32, matrix4_from_euler_angles_f64};
matrix4_from_euler_angle_x :: proc{matrix4_from_euler_angle_x_f16, matrix4_from_euler_angle_x_f32, matrix4_from_euler_angle_x_f64};
matrix4_from_euler_angle_y :: proc{matrix4_from_euler_angle_y_f16, matrix4_from_euler_angle_y_f32, matrix4_from_euler_angle_y_f64};
matrix4_from_euler_angle_z :: proc{matrix4_from_euler_angle_z_f16, matrix4_from_euler_angle_z_f32, matrix4_from_euler_angle_z_f64};
matrix4_from_derived_euler_angle_x :: proc{matrix4_from_derived_euler_angle_x_f16, matrix4_from_derived_euler_angle_x_f32, matrix4_from_derived_euler_angle_x_f64};
matrix4_from_derived_euler_angle_y :: proc{matrix4_from_derived_euler_angle_y_f16, matrix4_from_derived_euler_angle_y_f32, matrix4_from_derived_euler_angle_y_f64};
matrix4_from_derived_euler_angle_z :: proc{matrix4_from_derived_euler_angle_z_f16, matrix4_from_derived_euler_angle_z_f32, matrix4_from_derived_euler_angle_z_f64};
matrix4_from_euler_angles_xy :: proc{matrix4_from_euler_angles_xy_f16, matrix4_from_euler_angles_xy_f32, matrix4_from_euler_angles_xy_f64};
matrix4_from_euler_angles_yx :: proc{matrix4_from_euler_angles_yx_f16, matrix4_from_euler_angles_yx_f32, matrix4_from_euler_angles_yx_f64};
matrix4_from_euler_angles_xz :: proc{matrix4_from_euler_angles_xz_f16, matrix4_from_euler_angles_xz_f32, matrix4_from_euler_angles_xz_f64};
matrix4_from_euler_angles_zx :: proc{matrix4_from_euler_angles_zx_f16, matrix4_from_euler_angles_zx_f32, matrix4_from_euler_angles_zx_f64};
matrix4_from_euler_angles_yz :: proc{matrix4_from_euler_angles_yz_f16, matrix4_from_euler_angles_yz_f32, matrix4_from_euler_angles_yz_f64};
matrix4_from_euler_angles_zy :: proc{matrix4_from_euler_angles_zy_f16, matrix4_from_euler_angles_zy_f32, matrix4_from_euler_angles_zy_f64};
matrix4_from_euler_angles_xyz :: proc{matrix4_from_euler_angles_xyz_f16, matrix4_from_euler_angles_xyz_f32, matrix4_from_euler_angles_xyz_f64};
matrix4_from_euler_angles_yxz :: proc{matrix4_from_euler_angles_yxz_f16, matrix4_from_euler_angles_yxz_f32, matrix4_from_euler_angles_yxz_f64};
matrix4_from_euler_angles_xzx :: proc{matrix4_from_euler_angles_xzx_f16, matrix4_from_euler_angles_xzx_f32, matrix4_from_euler_angles_xzx_f64};
matrix4_from_euler_angles_xyx :: proc{matrix4_from_euler_angles_xyx_f16, matrix4_from_euler_angles_xyx_f32, matrix4_from_euler_angles_xyx_f64};
matrix4_from_euler_angles_yxy :: proc{matrix4_from_euler_angles_yxy_f16, matrix4_from_euler_angles_yxy_f32, matrix4_from_euler_angles_yxy_f64};
matrix4_from_euler_angles_yzy :: proc{matrix4_from_euler_angles_yzy_f16, matrix4_from_euler_angles_yzy_f32, matrix4_from_euler_angles_yzy_f64};
matrix4_from_euler_angles_zyz :: proc{matrix4_from_euler_angles_zyz_f16, matrix4_from_euler_angles_zyz_f32, matrix4_from_euler_angles_zyz_f64};
matrix4_from_euler_angles_zxz :: proc{matrix4_from_euler_angles_zxz_f16, matrix4_from_euler_angles_zxz_f32, matrix4_from_euler_angles_zxz_f64};
matrix4_from_euler_angles_xzy :: proc{matrix4_from_euler_angles_xzy_f16, matrix4_from_euler_angles_xzy_f32, matrix4_from_euler_angles_xzy_f64};
matrix4_from_euler_angles_yzx :: proc{matrix4_from_euler_angles_yzx_f16, matrix4_from_euler_angles_yzx_f32, matrix4_from_euler_angles_yzx_f64};
matrix4_from_euler_angles_zyx :: proc{matrix4_from_euler_angles_zyx_f16, matrix4_from_euler_angles_zyx_f32, matrix4_from_euler_angles_zyx_f64};
matrix4_from_euler_angles_zxy :: proc{matrix4_from_euler_angles_zxy_f16, matrix4_from_euler_angles_zxy_f32, matrix4_from_euler_angles_zxy_f64};
matrix4_from_yaw_pitch_roll :: proc{matrix4_from_yaw_pitch_roll_f16, matrix4_from_yaw_pitch_roll_f32, matrix4_from_yaw_pitch_roll_f64};
euler_angles_from_matrix4 :: proc{euler_angles_from_matrix4_f16, euler_angles_from_matrix4_f32, euler_angles_from_matrix4_f64};
euler_angles_xyz_from_matrix4 :: proc{euler_angles_xyz_from_matrix4_f16, euler_angles_xyz_from_matrix4_f32, euler_angles_xyz_from_matrix4_f64};
euler_angles_yxz_from_matrix4 :: proc{euler_angles_yxz_from_matrix4_f16, euler_angles_yxz_from_matrix4_f32, euler_angles_yxz_from_matrix4_f64};
euler_angles_xzx_from_matrix4 :: proc{euler_angles_xzx_from_matrix4_f16, euler_angles_xzx_from_matrix4_f32, euler_angles_xzx_from_matrix4_f64};
euler_angles_xyx_from_matrix4 :: proc{euler_angles_xyx_from_matrix4_f16, euler_angles_xyx_from_matrix4_f32, euler_angles_xyx_from_matrix4_f64};
euler_angles_yxy_from_matrix4 :: proc{euler_angles_yxy_from_matrix4_f16, euler_angles_yxy_from_matrix4_f32, euler_angles_yxy_from_matrix4_f64};
euler_angles_yzy_from_matrix4 :: proc{euler_angles_yzy_from_matrix4_f16, euler_angles_yzy_from_matrix4_f32, euler_angles_yzy_from_matrix4_f64};
euler_angles_zyz_from_matrix4 :: proc{euler_angles_zyz_from_matrix4_f16, euler_angles_zyz_from_matrix4_f32, euler_angles_zyz_from_matrix4_f64};
euler_angles_zxz_from_matrix4 :: proc{euler_angles_zxz_from_matrix4_f16, euler_angles_zxz_from_matrix4_f32, euler_angles_zxz_from_matrix4_f64};
euler_angles_xzy_from_matrix4 :: proc{euler_angles_xzy_from_matrix4_f16, euler_angles_xzy_from_matrix4_f32, euler_angles_xzy_from_matrix4_f64};
euler_angles_yzx_from_matrix4 :: proc{euler_angles_yzx_from_matrix4_f16, euler_angles_yzx_from_matrix4_f32, euler_angles_yzx_from_matrix4_f64};
euler_angles_zyx_from_matrix4 :: proc{euler_angles_zyx_from_matrix4_f16, euler_angles_zyx_from_matrix4_f32, euler_angles_zyx_from_matrix4_f64};
euler_angles_zxy_from_matrix4 :: proc{euler_angles_zxy_from_matrix4_f16, euler_angles_zxy_from_matrix4_f32, euler_angles_zxy_from_matrix4_f64};
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+222
View File
@@ -0,0 +1,222 @@
package linalg
Scalar_Components :: enum u8 {
x = 0,
r = 0,
}
Vector2_Components :: enum u8 {
x = 0,
y = 1,
r = 0,
g = 1,
}
Vector3_Components :: enum u8 {
x = 0,
y = 1,
z = 2,
r = 0,
g = 1,
b = 2,
}
Vector4_Components :: enum u8 {
x = 0,
y = 1,
z = 2,
w = 3,
r = 0,
g = 1,
b = 2,
a = 3,
}
scalar_f32_swizzle1 :: proc(f: f32, c0: Scalar_Components) -> f32 {
return f;
}
scalar_f32_swizzle2 :: proc(f: f32, c0, c1: Scalar_Components) -> Vector2f32 {
return {f, f};
}
scalar_f32_swizzle3 :: proc(f: f32, c0, c1, c2: Scalar_Components) -> Vector3f32 {
return {f, f, f};
}
scalar_f32_swizzle4 :: proc(f: f32, c0, c1, c2, c3: Scalar_Components) -> Vector4f32 {
return {f, f, f, f};
}
vector2f32_swizzle1 :: proc(v: Vector2f32, c0: Vector2_Components) -> f32 {
return v[c0];
}
vector2f32_swizzle2 :: proc(v: Vector2f32, c0, c1: Vector2_Components) -> Vector2f32 {
return {v[c0], v[c1]};
}
vector2f32_swizzle3 :: proc(v: Vector2f32, c0, c1, c2: Vector2_Components) -> Vector3f32 {
return {v[c0], v[c1], v[c2]};
}
vector2f32_swizzle4 :: proc(v: Vector2f32, c0, c1, c2, c3: Vector2_Components) -> Vector4f32 {
return {v[c0], v[c1], v[c2], v[c3]};
}
vector3f32_swizzle1 :: proc(v: Vector3f32, c0: Vector3_Components) -> f32 {
return v[c0];
}
vector3f32_swizzle2 :: proc(v: Vector3f32, c0, c1: Vector3_Components) -> Vector2f32 {
return {v[c0], v[c1]};
}
vector3f32_swizzle3 :: proc(v: Vector3f32, c0, c1, c2: Vector3_Components) -> Vector3f32 {
return {v[c0], v[c1], v[c2]};
}
vector3f32_swizzle4 :: proc(v: Vector3f32, c0, c1, c2, c3: Vector3_Components) -> Vector4f32 {
return {v[c0], v[c1], v[c2], v[c3]};
}
vector4f32_swizzle1 :: proc(v: Vector4f32, c0: Vector4_Components) -> f32 {
return v[c0];
}
vector4f32_swizzle2 :: proc(v: Vector4f32, c0, c1: Vector4_Components) -> Vector2f32 {
return {v[c0], v[c1]};
}
vector4f32_swizzle3 :: proc(v: Vector4f32, c0, c1, c2: Vector4_Components) -> Vector3f32 {
return {v[c0], v[c1], v[c2]};
}
vector4f32_swizzle4 :: proc(v: Vector4f32, c0, c1, c2, c3: Vector4_Components) -> Vector4f32 {
return {v[c0], v[c1], v[c2], v[c3]};
}
scalar_f64_swizzle1 :: proc(f: f64, c0: Scalar_Components) -> f64 {
return f;
}
scalar_f64_swizzle2 :: proc(f: f64, c0, c1: Scalar_Components) -> Vector2f64 {
return {f, f};
}
scalar_f64_swizzle3 :: proc(f: f64, c0, c1, c2: Scalar_Components) -> Vector3f64 {
return {f, f, f};
}
scalar_f64_swizzle4 :: proc(f: f64, c0, c1, c2, c3: Scalar_Components) -> Vector4f64 {
return {f, f, f, f};
}
vector2f64_swizzle1 :: proc(v: Vector2f64, c0: Vector2_Components) -> f64 {
return v[c0];
}
vector2f64_swizzle2 :: proc(v: Vector2f64, c0, c1: Vector2_Components) -> Vector2f64 {
return {v[c0], v[c1]};
}
vector2f64_swizzle3 :: proc(v: Vector2f64, c0, c1, c2: Vector2_Components) -> Vector3f64 {
return {v[c0], v[c1], v[c2]};
}
vector2f64_swizzle4 :: proc(v: Vector2f64, c0, c1, c2, c3: Vector2_Components) -> Vector4f64 {
return {v[c0], v[c1], v[c2], v[c3]};
}
vector3f64_swizzle1 :: proc(v: Vector3f64, c0: Vector3_Components) -> f64 {
return v[c0];
}
vector3f64_swizzle2 :: proc(v: Vector3f64, c0, c1: Vector3_Components) -> Vector2f64 {
return {v[c0], v[c1]};
}
vector3f64_swizzle3 :: proc(v: Vector3f64, c0, c1, c2: Vector3_Components) -> Vector3f64 {
return {v[c0], v[c1], v[c2]};
}
vector3f64_swizzle4 :: proc(v: Vector3f64, c0, c1, c2, c3: Vector3_Components) -> Vector4f64 {
return {v[c0], v[c1], v[c2], v[c3]};
}
vector4f64_swizzle1 :: proc(v: Vector4f64, c0: Vector4_Components) -> f64 {
return v[c0];
}
vector4f64_swizzle2 :: proc(v: Vector4f64, c0, c1: Vector4_Components) -> Vector2f64 {
return {v[c0], v[c1]};
}
vector4f64_swizzle3 :: proc(v: Vector4f64, c0, c1, c2: Vector4_Components) -> Vector3f64 {
return {v[c0], v[c1], v[c2]};
}
vector4f64_swizzle4 :: proc(v: Vector4f64, c0, c1, c2, c3: Vector4_Components) -> Vector4f64 {
return {v[c0], v[c1], v[c2], v[c3]};
}
scalar_swizzle :: proc{
scalar_f32_swizzle1,
scalar_f32_swizzle2,
scalar_f32_swizzle3,
scalar_f32_swizzle4,
scalar_f64_swizzle1,
scalar_f64_swizzle2,
scalar_f64_swizzle3,
scalar_f64_swizzle4,
};
vector2_swizzle :: proc{
vector2f32_swizzle1,
vector2f32_swizzle2,
vector2f32_swizzle3,
vector2f32_swizzle4,
vector2f64_swizzle1,
vector2f64_swizzle2,
vector2f64_swizzle3,
vector2f64_swizzle4,
};
vector3_swizzle :: proc{
vector3f32_swizzle1,
vector3f32_swizzle2,
vector3f32_swizzle3,
vector3f32_swizzle4,
vector3f64_swizzle1,
vector3f64_swizzle2,
vector3f64_swizzle3,
vector3f64_swizzle4,
};
vector4_swizzle :: proc{
vector4f32_swizzle1,
vector4f32_swizzle2,
vector4f32_swizzle3,
vector4f32_swizzle4,
vector4f64_swizzle1,
vector4f64_swizzle2,
vector4f64_swizzle3,
vector4f64_swizzle4,
};
swizzle :: proc{
scalar_f32_swizzle1,
scalar_f32_swizzle2,
scalar_f32_swizzle3,
scalar_f32_swizzle4,
scalar_f64_swizzle1,
scalar_f64_swizzle2,
scalar_f64_swizzle3,
scalar_f64_swizzle4,
vector2f32_swizzle1,
vector2f32_swizzle2,
vector2f32_swizzle3,
vector2f32_swizzle4,
vector2f64_swizzle1,
vector2f64_swizzle2,
vector2f64_swizzle3,
vector2f64_swizzle4,
vector3f32_swizzle1,
vector3f32_swizzle2,
vector3f32_swizzle3,
vector3f32_swizzle4,
vector3f64_swizzle1,
vector3f64_swizzle2,
vector3f64_swizzle3,
vector3f64_swizzle4,
vector4f32_swizzle1,
vector4f32_swizzle2,
vector4f32_swizzle3,
vector4f32_swizzle4,
vector4f64_swizzle1,
vector4f64_swizzle2,
vector4f64_swizzle3,
vector4f64_swizzle4,
};
+1027
View File
File diff suppressed because it is too large Load Diff
+152
View File
@@ -0,0 +1,152 @@
package rand
import "core:math"
//
// Normal distribution
//
// "The Ziggurat Method for Generating Random Variables"
// Authors: George Marsaglia, Wai Wan Tsang
// Submitted: 2000-04-15. Published: 2000-10-02.
// https://www.jstatsoft.org/index.php/jss/article/view/v005i08/ziggurat.pdf [pdf]
// https://www.jstatsoft.org/article/view/v005i08 [web page]
//
// norm_float64 returns a normally distributed f64 in the range -max(f64) through +max(f64) inclusive,
// with a standard normal distribution with a mean of 0 and standard deviation of 1.
//
// sample = norm_float64() * std_dev + mean
//
norm_float64 :: proc(r: ^Rand = nil) -> f64 {
rn :: 3.442619855899;
@(static)
kn := [128]u32{
0x76ad2212, 0x00000000, 0x600f1b53, 0x6ce447a6, 0x725b46a2,
0x7560051d, 0x774921eb, 0x789a25bd, 0x799045c3, 0x7a4bce5d,
0x7adf629f, 0x7b5682a6, 0x7bb8a8c6, 0x7c0ae722, 0x7c50cce7,
0x7c8cec5b, 0x7cc12cd6, 0x7ceefed2, 0x7d177e0b, 0x7d3b8883,
0x7d5bce6c, 0x7d78dd64, 0x7d932886, 0x7dab0e57, 0x7dc0dd30,
0x7dd4d688, 0x7de73185, 0x7df81cea, 0x7e07c0a3, 0x7e163efa,
0x7e23b587, 0x7e303dfd, 0x7e3beec2, 0x7e46db77, 0x7e51155d,
0x7e5aabb3, 0x7e63abf7, 0x7e6c222c, 0x7e741906, 0x7e7b9a18,
0x7e82adfa, 0x7e895c63, 0x7e8fac4b, 0x7e95a3fb, 0x7e9b4924,
0x7ea0a0ef, 0x7ea5b00d, 0x7eaa7ac3, 0x7eaf04f3, 0x7eb3522a,
0x7eb765a5, 0x7ebb4259, 0x7ebeeafd, 0x7ec2620a, 0x7ec5a9c4,
0x7ec8c441, 0x7ecbb365, 0x7ece78ed, 0x7ed11671, 0x7ed38d62,
0x7ed5df12, 0x7ed80cb4, 0x7eda175c, 0x7edc0005, 0x7eddc78e,
0x7edf6ebf, 0x7ee0f647, 0x7ee25ebe, 0x7ee3a8a9, 0x7ee4d473,
0x7ee5e276, 0x7ee6d2f5, 0x7ee7a620, 0x7ee85c10, 0x7ee8f4cd,
0x7ee97047, 0x7ee9ce59, 0x7eea0eca, 0x7eea3147, 0x7eea3568,
0x7eea1aab, 0x7ee9e071, 0x7ee98602, 0x7ee90a88, 0x7ee86d08,
0x7ee7ac6a, 0x7ee6c769, 0x7ee5bc9c, 0x7ee48a67, 0x7ee32efc,
0x7ee1a857, 0x7edff42f, 0x7ede0ffa, 0x7edbf8d9, 0x7ed9ab94,
0x7ed7248d, 0x7ed45fae, 0x7ed1585c, 0x7ece095f, 0x7eca6ccb,
0x7ec67be2, 0x7ec22eee, 0x7ebd7d1a, 0x7eb85c35, 0x7eb2c075,
0x7eac9c20, 0x7ea5df27, 0x7e9e769f, 0x7e964c16, 0x7e8d44ba,
0x7e834033, 0x7e781728, 0x7e6b9933, 0x7e5d8a1a, 0x7e4d9ded,
0x7e3b737a, 0x7e268c2f, 0x7e0e3ff5, 0x7df1aa5d, 0x7dcf8c72,
0x7da61a1e, 0x7d72a0fb, 0x7d30e097, 0x7cd9b4ab, 0x7c600f1a,
0x7ba90bdc, 0x7a722176, 0x77d664e5,
};
@(static)
wn := [128]f32{
1.7290405e-09, 1.2680929e-10, 1.6897518e-10, 1.9862688e-10,
2.2232431e-10, 2.4244937e-10, 2.601613e-10, 2.7611988e-10,
2.9073963e-10, 3.042997e-10, 3.1699796e-10, 3.289802e-10,
3.4035738e-10, 3.5121603e-10, 3.616251e-10, 3.7164058e-10,
3.8130857e-10, 3.9066758e-10, 3.9975012e-10, 4.08584e-10,
4.1719309e-10, 4.2559822e-10, 4.338176e-10, 4.418672e-10,
4.497613e-10, 4.5751258e-10, 4.651324e-10, 4.7263105e-10,
4.8001775e-10, 4.87301e-10, 4.944885e-10, 5.015873e-10,
5.0860405e-10, 5.155446e-10, 5.2241467e-10, 5.2921934e-10,
5.359635e-10, 5.426517e-10, 5.4928817e-10, 5.5587696e-10,
5.624219e-10, 5.6892646e-10, 5.753941e-10, 5.818282e-10,
5.882317e-10, 5.946077e-10, 6.00959e-10, 6.072884e-10,
6.135985e-10, 6.19892e-10, 6.2617134e-10, 6.3243905e-10,
6.386974e-10, 6.449488e-10, 6.511956e-10, 6.5744005e-10,
6.6368433e-10, 6.699307e-10, 6.7618144e-10, 6.824387e-10,
6.8870465e-10, 6.949815e-10, 7.012715e-10, 7.075768e-10,
7.1389966e-10, 7.202424e-10, 7.266073e-10, 7.329966e-10,
7.394128e-10, 7.4585826e-10, 7.5233547e-10, 7.58847e-10,
7.653954e-10, 7.719835e-10, 7.7861395e-10, 7.852897e-10,
7.920138e-10, 7.987892e-10, 8.0561924e-10, 8.125073e-10,
8.194569e-10, 8.2647167e-10, 8.3355556e-10, 8.407127e-10,
8.479473e-10, 8.55264e-10, 8.6266755e-10, 8.7016316e-10,
8.777562e-10, 8.8545243e-10, 8.932582e-10, 9.0117996e-10,
9.09225e-10, 9.174008e-10, 9.2571584e-10, 9.341788e-10,
9.427997e-10, 9.515889e-10, 9.605579e-10, 9.697193e-10,
9.790869e-10, 9.88676e-10, 9.985036e-10, 1.0085882e-09,
1.0189509e-09, 1.0296151e-09, 1.0406069e-09, 1.0519566e-09,
1.063698e-09, 1.0758702e-09, 1.0885183e-09, 1.1016947e-09,
1.1154611e-09, 1.1298902e-09, 1.1450696e-09, 1.1611052e-09,
1.1781276e-09, 1.1962995e-09, 1.2158287e-09, 1.2369856e-09,
1.2601323e-09, 1.2857697e-09, 1.3146202e-09, 1.347784e-09,
1.3870636e-09, 1.4357403e-09, 1.5008659e-09, 1.6030948e-09,
};
@(static)
fn := [128]f32{
1.00000000, 0.9635997, 0.9362827, 0.9130436, 0.89228165,
0.87324303, 0.8555006, 0.8387836, 0.8229072, 0.8077383,
0.793177, 0.7791461, 0.7655842, 0.7524416, 0.73967725,
0.7272569, 0.7151515, 0.7033361, 0.69178915, 0.68049186,
0.6694277, 0.658582, 0.6479418, 0.63749546, 0.6272325,
0.6171434, 0.6072195, 0.5974532, 0.58783704, 0.5783647,
0.56903, 0.5598274, 0.5507518, 0.54179835, 0.5329627,
0.52424055, 0.5156282, 0.50712204, 0.49871865, 0.49041483,
0.48220766, 0.4740943, 0.46607214, 0.4581387, 0.45029163,
0.44252872, 0.43484783, 0.427247, 0.41972435, 0.41227803,
0.40490642, 0.39760786, 0.3903808, 0.3832238, 0.37613547,
0.36911446, 0.3621595, 0.35526937, 0.34844297, 0.34167916,
0.33497685, 0.3283351, 0.3217529, 0.3152294, 0.30876362,
0.30235484, 0.29600215, 0.28970486, 0.2834622, 0.2772735,
0.27113807, 0.2650553, 0.25902456, 0.2530453, 0.24711695,
0.241239, 0.23541094, 0.22963232, 0.2239027, 0.21822165,
0.21258877, 0.20700371, 0.20146611, 0.19597565, 0.19053204,
0.18513499, 0.17978427, 0.17447963, 0.1692209, 0.16400786,
0.15884037, 0.15371831, 0.14864157, 0.14361008, 0.13862377,
0.13368265, 0.12878671, 0.12393598, 0.119130544, 0.11437051,
0.10965602, 0.104987256, 0.10036444, 0.095787846, 0.0912578,
0.08677467, 0.0823389, 0.077950984, 0.073611505, 0.06932112,
0.06508058, 0.06089077, 0.056752663, 0.0526674, 0.048636295,
0.044660863, 0.040742867, 0.03688439, 0.033087887, 0.029356318,
0.025693292, 0.022103304, 0.018592102, 0.015167298, 0.011839478,
0.008624485, 0.005548995, 0.0026696292,
};
r := r;
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;
}
for {
j := i32(uint32(r));
i := j & 0x7f;
x := f64(j) * f64(wn[i]);
if u32(abs(j)) < kn[i] {
// 99% of the time this will be hit
return x;
}
if i == 0 {
for {
x = -math.ln(float64(r)) * (1.0/ rn);
y := -math.ln(float64(r));
if y+y >= x*x {
break;
}
}
return j > 0 ? rn + x : -rn - x;
}
if fn[i]+f32(float64(r))*(fn[i-1]-fn[i]) < f32(math.exp(-0.5*x*x)) {
return x;
}
}
return 0; // NOTE(bill): Will never be hit but this is here for sanity's sake
}
+166
View File
@@ -0,0 +1,166 @@
package rand
Rand :: struct {
state: u64,
inc: u64,
}
@(private, static)
_GLOBAL_SEED_DATA := 1234567890;
@(private, static)
global_rand := create(u64(uintptr(&_GLOBAL_SEED_DATA)));
set_global_seed :: proc(seed: u64) {
init(&global_rand, seed);
}
create :: proc(seed: u64) -> Rand {
r: Rand;
init(&r, seed);
return r;
}
init :: proc(r: ^Rand, seed: u64) {
r.state = 0;
r.inc = (seed << 1) | 1;
_random(r);
r.state += seed;
_random(r);
}
_random :: proc(r: ^Rand) -> u32 {
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;
}
old_state := r.state;
r.state = old_state * 6364136223846793005 + (r.inc|1);
xor_shifted := u32(((old_state>>18) ~ old_state) >> 27);
rot := u32(old_state >> 59);
return (xor_shifted >> rot) | (xor_shifted << ((-rot) & 31));
}
uint32 :: proc(r: ^Rand = nil) -> u32 { return _random(r); }
uint64 :: proc(r: ^Rand = nil) -> u64 {
a := u64(_random(r));
b := u64(_random(r));
return (a<<32) | b;
}
uint128 :: proc(r: ^Rand = nil) -> u128 {
a := u128(_random(r));
b := u128(_random(r));
c := u128(_random(r));
d := u128(_random(r));
return (a<<96) | (b<<64) | (c<<32) | d;
}
int31 :: proc(r: ^Rand = nil) -> i32 { return i32(uint32(r) << 1 >> 1); }
int63 :: proc(r: ^Rand = nil) -> i64 { return i64(uint64(r) << 1 >> 1); }
int127 :: proc(r: ^Rand = nil) -> i128 { return i128(uint128(r) << 1 >> 1); }
int31_max :: proc(n: i32, r: ^Rand = nil) -> i32 {
if n <= 0 {
panic("Invalid argument to int31_max");
}
if n&(n-1) == 0 {
return int31(r) & (n-1);
}
max := i32((1<<31) - 1 - (1<<31)&u32(n));
v := int31(r);
for v > max {
v = int31(r);
}
return v % n;
}
int63_max :: proc(n: i64, r: ^Rand = nil) -> i64 {
if n <= 0 {
panic("Invalid argument to int63_max");
}
if n&(n-1) == 0 {
return int63(r) & (n-1);
}
max := i64((1<<63) - 1 - (1<<63)&u64(n));
v := int63(r);
for v > max {
v = int63(r);
}
return v % n;
}
int127_max :: proc(n: i128, r: ^Rand = nil) -> i128 {
if n <= 0 {
panic("Invalid argument to int63_max");
}
if n&(n-1) == 0 {
return int127(r) & (n-1);
}
max := i128((1<<63) - 1 - (1<<63)&u128(n));
v := int127(r);
for v > max {
v = int127(r);
}
return v % n;
}
int_max :: proc(n: int, r: ^Rand = nil) -> int {
if n <= 0 {
panic("Invalid argument to int_max");
}
when size_of(int) == 4 {
return int(int31_max(i32(n), r));
} else {
return int(int63_max(i64(n), r));
}
}
float64 :: proc(r: ^Rand = nil) -> f64 { return f64(int63_max(1<<53, r)) / (1 << 53); }
float32 :: proc(r: ^Rand = nil) -> f32 { return f32(float64(r)); }
float64_range :: proc(lo, hi: f64, r: ^Rand = nil) -> f64 { return (hi-lo)*float64(r) + lo; }
float32_range :: proc(lo, hi: f32, r: ^Rand = nil) -> f32 { return (hi-lo)*float32(r) + lo; }
read :: proc(p: []byte, r: ^Rand = nil) -> (n: int) {
pos := i8(0);
val := i64(0);
for n = 0; n < len(p); n += 1 {
if pos == 0 {
val = int63(r);
pos = 7;
}
p[n] = byte(val);
val >>= 8;
pos -= 1;
}
return;
}
// perm returns a slice of n ints in a pseudo-random permutation of integers in the range [0, n)
perm :: proc(n: int, r: ^Rand = nil) -> []int {
m := make([]int, n);
for i := 0; i < n; i += 1 {
j := int_max(i+1, r);
m[i] = m[j];
m[j] = i;
}
return m;
}
shuffle :: proc(array: $T/[]$E, r: ^Rand = nil) {
n := i64(len(array));
if n < 2 {
return;
}
for i := i64(0); i < n; i += 1 {
j := int63_max(n, r);
array[i], array[j] = array[j], array[i];
}
}
-322
View File
@@ -1,322 +0,0 @@
import "core:raw.odin"
foreign __llvm_core {
@(link_name = "llvm.bswap.i16") swap :: proc(b: u16) -> u16 ---;
@(link_name = "llvm.bswap.i32") swap :: proc(b: u32) -> u32 ---;
@(link_name = "llvm.bswap.i64") swap :: proc(b: u64) -> u64 ---;
}
set :: proc "contextless" (data: rawptr, value: i32, len: int) -> rawptr {
return __mem_set(data, value, len);
}
zero :: proc "contextless" (data: rawptr, len: int) -> rawptr {
return __mem_zero(data, len);
}
copy :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr {
return __mem_copy(dst, src, len);
}
copy_non_overlapping :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr {
return __mem_copy_non_overlapping(dst, src, len);
}
compare :: proc "contextless" (a, b: []u8) -> int {
return __mem_compare(&a[0], &b[0], min(len(a), len(b)));
}
slice_ptr :: proc "contextless" (ptr: ^$T, len: int) -> []T {
assert(len >= 0);
slice := raw.Slice{data = ptr, len = len, cap = len};
return transmute([]T)slice;
}
slice_ptr :: proc "contextless" (ptr: ^$T, len, cap: int) -> []T {
assert(0 <= len && len <= cap);
slice := raw.Slice{data = ptr, len = len, cap = cap};
return transmute([]T)slice;
}
slice_to_bytes :: proc "contextless" (slice: $E/[]$T) -> []u8 {
s := transmute(raw.Slice)slice;
s.len *= size_of(T);
s.cap *= size_of(T);
return transmute([]u8)s;
}
ptr_to_bytes :: proc "contextless" (ptr: ^$T, len := 1) -> []u8 {
assert(len >= 0);
return transmute([]u8)raw.Slice{ptr, len*size_of(T), len*size_of(T)};
}
ptr_to_bytes :: proc "contextless" (ptr: ^$T, len, cap: int) -> []u8 {
assert(0 <= len && len <= cap);
return transmute([]u8)raw.Slice{ptr, len*size_of(T), cap*size_of(T)};
}
kilobytes :: inline proc "contextless" (x: int) -> int do return (x) * 1024;
megabytes :: inline proc "contextless" (x: int) -> int do return kilobytes(x) * 1024;
gigabytes :: inline proc "contextless" (x: int) -> int do return megabytes(x) * 1024;
terabytes :: inline proc "contextless" (x: int) -> int do return gigabytes(x) * 1024;
is_power_of_two :: proc(x: uintptr) -> bool {
if x <= 0 do return false;
return (x & (x-1)) == 0;
}
align_forward :: proc(ptr: rawptr, align: uintptr) -> rawptr {
assert(is_power_of_two(align));
a := uintptr(align);
p := uintptr(ptr);
modulo := p & (a-1);
if modulo != 0 do p += a - modulo;
return rawptr(p);
}
AllocationHeader :: struct {size: int};
allocation_header_fill :: proc(header: ^AllocationHeader, data: rawptr, size: int) {
header.size = size;
ptr := cast(^uint)(header+1);
n := cast(^uint)data - ptr;
for i in 0..n {
(ptr+i)^ = ~uint(0);
}
}
allocation_header :: proc(data: rawptr) -> ^AllocationHeader {
if data == nil do return nil;
p := cast(^uint)data;
for (p-1)^ == ~uint(0) do p = (p-1);
return cast(^AllocationHeader)(p-1);
}
// Custom allocators
Arena :: struct {
backing: Allocator,
memory: []u8,
temp_count: int,
}
ArenaTempMemory :: struct {
arena: ^Arena,
original_count: int,
}
init_arena_from_memory :: proc(using a: ^Arena, data: []u8) {
backing = Allocator{};
memory = data[..0];
temp_count = 0;
}
init_arena_from_context :: proc(using a: ^Arena, size: int) {
backing = context.allocator;
memory = make([]u8, 0, size);
temp_count = 0;
}
context_from_allocator :: proc(a: Allocator) -> Context {
c := context;
c.allocator = a;
return c;
}
destroy_arena :: proc(using a: ^Arena) {
if backing.procedure != nil {
context <- context_from_allocator(backing) {
free(memory);
memory = nil;
}
}
}
arena_allocator :: proc(arena: ^Arena) -> Allocator {
return Allocator{
procedure = arena_allocator_proc,
data = arena,
};
}
arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
size, alignment: int,
old_memory: rawptr, old_size: int, flags: u64, location := #caller_location) -> rawptr {
using Allocator_Mode;
arena := cast(^Arena)allocator_data;
switch mode {
case Alloc:
total_size := size + alignment;
if len(arena.memory) + total_size > cap(arena.memory) {
return nil;
}
#no_bounds_check end := &arena.memory[len(arena.memory)];
ptr := align_forward(end, uintptr(alignment));
(^raw.Slice)(&arena.memory).len += total_size;
return zero(ptr, size);
case Free:
// NOTE(bill): Free all at once
// Use ArenaTempMemory if you want to free a block
case FreeAll:
(^raw.Slice)(&arena.memory).len = 0;
case Resize:
return default_resize_align(old_memory, old_size, size, alignment);
}
return nil;
}
begin_arena_temp_memory :: proc(a: ^Arena) -> ArenaTempMemory {
tmp: ArenaTempMemory;
tmp.arena = a;
tmp.original_count = len(a.memory);
a.temp_count += 1;
return tmp;
}
end_arena_temp_memory :: proc(using tmp: ArenaTempMemory) {
assert(len(arena.memory) >= original_count);
assert(arena.temp_count > 0);
arena.memory = arena.memory[..original_count];
arena.temp_count -= 1;
}
align_of_type_info :: proc(type_info: ^Type_Info) -> int {
prev_pow2 :: proc(n: i64) -> i64 {
if n <= 0 do return 0;
n |= n >> 1;
n |= n >> 2;
n |= n >> 4;
n |= n >> 8;
n |= n >> 16;
n |= n >> 32;
return n - (n >> 1);
}
WORD_SIZE :: size_of(int);
MAX_ALIGN :: size_of([vector 64]f64); // TODO(bill): Should these constants be builtin constants?
switch info in type_info.variant {
case Type_Info_Named:
return align_of_type_info(info.base);
case Type_Info_Integer:
return type_info.align;
case Type_Info_Rune:
return type_info.align;
case Type_Info_Float:
return type_info.align;
case Type_Info_String:
return WORD_SIZE;
case Type_Info_Boolean:
return 1;
case Type_Info_Any:
return WORD_SIZE;
case Type_Info_Pointer:
return WORD_SIZE;
case Type_Info_Procedure:
return WORD_SIZE;
case Type_Info_Array:
return align_of_type_info(info.elem);
case Type_Info_Dynamic_Array:
return WORD_SIZE;
case Type_Info_Slice:
return WORD_SIZE;
case Type_Info_Vector:
size := size_of_type_info(info.elem);
count := int(max(prev_pow2(i64(info.count)), 1));
total := size * count;
return clamp(total, 1, MAX_ALIGN);
case Type_Info_Tuple:
return type_info.align;
case Type_Info_Struct:
return type_info.align;
case Type_Info_Union:
return type_info.align;
case Type_Info_Enum:
return align_of_type_info(info.base);
case Type_Info_Map:
return align_of_type_info(info.generated_struct);
}
return 0;
}
align_formula :: proc(size, align: int) -> int {
result := size + align-1;
return result - result%align;
}
size_of_type_info :: proc(type_info: ^Type_Info) -> int {
WORD_SIZE :: size_of(int);
switch info in type_info.variant {
case Type_Info_Named:
return size_of_type_info(info.base);
case Type_Info_Integer:
return type_info.size;
case Type_Info_Rune:
return type_info.size;
case Type_Info_Float:
return type_info.size;
case Type_Info_String:
return 2*WORD_SIZE;
case Type_Info_Boolean:
return 1;
case Type_Info_Any:
return 2*WORD_SIZE;
case Type_Info_Pointer:
return WORD_SIZE;
case Type_Info_Procedure:
return WORD_SIZE;
case Type_Info_Array:
count := info.count;
if count == 0 do return 0;
size := size_of_type_info(info.elem);
align := align_of_type_info(info.elem);
alignment := align_formula(size, align);
return alignment*(count-1) + size;
case Type_Info_Dynamic_Array:
return size_of(rawptr) + 2*size_of(int) + size_of(Allocator);
case Type_Info_Slice:
return 2*WORD_SIZE;
case Type_Info_Vector:
count := info.count;
if count == 0 do return 0;
size := size_of_type_info(info.elem);
align := align_of_type_info(info.elem);
alignment := align_formula(size, align);
return alignment*(count-1) + size;
case Type_Info_Struct:
return type_info.size;
case Type_Info_Union:
return type_info.size;
case Type_Info_Enum:
return size_of_type_info(info.base);
case Type_Info_Map:
return size_of_type_info(info.generated_struct);
}
return 0;
}
+302
View File
@@ -0,0 +1,302 @@
package mem
import "core:runtime"
// NOTE(bill, 2019-12-31): These are defined in `package runtime` as they are used in the `context`. This is to prevent an import definition cycle.
Allocator_Mode :: runtime.Allocator_Mode;
/*
Allocator_Mode :: enum byte {
Alloc,
Free,
Free_All,
Resize,
Query_Features,
}
*/
Allocator_Mode_Set :: runtime.Allocator_Mode_Set;
/*
Allocator_Mode_Set :: distinct bit_set[Allocator_Mode];
*/
Allocator_Query_Info :: runtime.Allocator_Query_Info;
/*
Allocator_Query_Info :: struct {
pointer: Maybe(rawptr),
size: Maybe(int),
alignment: Maybe(int),
}
*/
Allocator_Error :: runtime.Allocator_Error;
/*
Allocator_Error :: enum byte {
None = 0,
Out_Of_Memory = 1,
Invalid_Pointer = 2,
Invalid_Argument = 3,
}
*/
Allocator_Proc :: runtime.Allocator_Proc;
/*
Allocator_Proc :: #type proc(allocator_data: rawptr, mode: Allocator_Mode,
size, alignment: int,
old_memory: rawptr, old_size: int, location: Source_Code_Location = #caller_location) -> ([]byte, Allocator_Error);
*/
Allocator :: runtime.Allocator;
/*
Allocator :: struct {
procedure: Allocator_Proc,
data: rawptr,
}
*/
DEFAULT_ALIGNMENT :: 2*align_of(rawptr);
alloc :: proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> rawptr {
if size == 0 {
return nil;
}
if allocator.procedure == nil {
return nil;
}
data, err := allocator.procedure(allocator.data, Allocator_Mode.Alloc, size, alignment, nil, 0, loc);
_ = err;
return raw_data(data);
}
alloc_bytes :: proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
if size == 0 {
return nil, nil;
}
if allocator.procedure == nil {
return nil, nil;
}
return allocator.procedure(allocator.data, Allocator_Mode.Alloc, size, alignment, nil, 0, loc);
}
free :: proc(ptr: rawptr, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
if ptr == nil {
return nil;
}
if allocator.procedure == nil {
return nil;
}
_, err := allocator.procedure(allocator.data, Allocator_Mode.Free, 0, 0, ptr, 0, loc);
return err;
}
free_bytes :: proc(bytes: []byte, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
if bytes == nil {
return nil;
}
if allocator.procedure == nil {
return nil;
}
_, err := allocator.procedure(allocator.data, Allocator_Mode.Free, 0, 0, raw_data(bytes), len(bytes), loc);
return err;
}
free_all :: proc(allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
if allocator.procedure != nil {
_, err := allocator.procedure(allocator.data, Allocator_Mode.Free_All, 0, 0, nil, 0, loc);
return err;
}
return nil;
}
resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> rawptr {
if allocator.procedure == nil {
return nil;
}
if new_size == 0 {
if ptr != nil {
allocator.procedure(allocator.data, Allocator_Mode.Free, 0, 0, ptr, old_size, loc);
}
return nil;
} else if ptr == nil {
_, err := allocator.procedure(allocator.data, Allocator_Mode.Alloc, new_size, alignment, nil, 0, loc);
_ = err;
return nil;
}
data, err := allocator.procedure(allocator.data, Allocator_Mode.Resize, new_size, alignment, ptr, old_size, loc);
_ = err;
return raw_data(data);
}
resize_bytes :: proc(old_data: []byte, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
if allocator.procedure == nil {
return nil, nil;
}
ptr := raw_data(old_data);
old_size := len(old_data);
if new_size == 0 {
if ptr != nil {
_, err := allocator.procedure(allocator.data, Allocator_Mode.Free, 0, 0, ptr, old_size, loc);
return nil, err;
}
return nil, nil;
} else if ptr == nil {
return allocator.procedure(allocator.data, Allocator_Mode.Alloc, new_size, alignment, nil, 0, loc);
}
return allocator.procedure(allocator.data, Allocator_Mode.Resize, new_size, alignment, ptr, old_size, loc);
}
query_features :: proc(allocator: Allocator, loc := #caller_location) -> (set: Allocator_Mode_Set) {
if allocator.procedure != nil {
allocator.procedure(allocator.data, Allocator_Mode.Query_Features, 0, 0, &set, 0, loc);
return set;
}
return nil;
}
query_info :: proc(pointer: rawptr, allocator: Allocator, loc := #caller_location) -> (props: Allocator_Query_Info) {
props.pointer = pointer;
if allocator.procedure != nil {
allocator.procedure(allocator.data, Allocator_Mode.Query_Info, 0, 0, &props, 0, loc);
}
return;
}
delete_string :: proc(str: string, allocator := context.allocator, loc := #caller_location) {
free(raw_data(str), allocator, loc);
}
delete_cstring :: proc(str: cstring, allocator := context.allocator, loc := #caller_location) {
free((^byte)(str), allocator, loc);
}
delete_dynamic_array :: proc(array: $T/[dynamic]$E, loc := #caller_location) {
free(raw_data(array), array.allocator, loc);
}
delete_slice :: proc(array: $T/[]$E, allocator := context.allocator, loc := #caller_location) {
free(raw_data(array), allocator, loc);
}
delete_map :: proc(m: $T/map[$K]$V, loc := #caller_location) {
raw := transmute(Raw_Map)m;
delete_slice(raw.hashes, raw.entries.allocator, loc);
free(raw.entries.data, raw.entries.allocator, loc);
}
delete :: proc{
delete_string,
delete_cstring,
delete_dynamic_array,
delete_slice,
delete_map,
};
new :: proc($T: typeid, allocator := context.allocator, loc := #caller_location) -> ^T {
return new_aligned(T, align_of(T), allocator, loc);
}
new_aligned :: proc($T: typeid, alignment: int, allocator := context.allocator, loc := #caller_location) -> ^T {
ptr := (^T)(alloc(size_of(T), alignment, allocator, loc));
if ptr != nil { ptr^ = T{}; }
return ptr;
}
new_clone :: proc(data: $T, allocator := context.allocator, loc := #caller_location) -> ^T {
ptr := (^T)(alloc(size_of(T), align_of(T), allocator, loc));
if ptr != nil { ptr^ = data; }
return ptr;
}
make_slice :: proc($T: typeid/[]$E, auto_cast len: int, allocator := context.allocator, loc := #caller_location) -> T {
return make_aligned(T, len, align_of(E), allocator, loc);
}
make_aligned :: proc($T: typeid/[]$E, auto_cast len: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> T {
runtime.make_slice_error_loc(loc, len);
data := alloc(size_of(E)*len, alignment, allocator, loc);
if data == nil && size_of(E) != 0 {
return nil;
}
zero(data, size_of(E)*len);
s := Raw_Slice{data, len};
return transmute(T)s;
}
make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> T {
return make_dynamic_array_len_cap(T, 0, 16, allocator, loc);
}
make_dynamic_array_len :: proc($T: typeid/[dynamic]$E, auto_cast len: int, allocator := context.allocator, loc := #caller_location) -> T {
return make_dynamic_array_len_cap(T, len, len, allocator, loc);
}
make_dynamic_array_len_cap :: proc($T: typeid/[dynamic]$E, auto_cast len: int, auto_cast cap: int, allocator := context.allocator, loc := #caller_location) -> T {
runtime.make_dynamic_array_error_loc(loc, len, cap);
data := alloc(size_of(E)*cap, align_of(E), allocator, loc);
s := Raw_Dynamic_Array{data, len, cap, allocator};
if data == nil && size_of(E) != 0 {
s.len, s.cap = 0, 0;
}
zero(data, size_of(E)*len);
return transmute(T)s;
}
make_map :: proc($T: typeid/map[$K]$E, auto_cast cap: int = 16, allocator := context.allocator, loc := #caller_location) -> T {
runtime.make_map_expr_error_loc(loc, cap);
context.allocator = allocator;
m: T;
reserve_map(&m, cap);
return m;
}
make :: proc{
make_slice,
make_dynamic_array,
make_dynamic_array_len,
make_dynamic_array_len_cap,
make_map,
};
default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment: int, allocator := context.allocator, loc := #caller_location) -> rawptr {
if old_memory == nil {
return alloc(new_size, alignment, allocator, loc);
}
if new_size == 0 {
free(old_memory, allocator, loc);
return nil;
}
if new_size == old_size {
return old_memory;
}
new_memory := alloc(new_size, alignment, allocator, loc);
if new_memory == nil {
return nil;
}
copy(new_memory, old_memory, min(old_size, new_size));
free(old_memory, allocator, loc);
return new_memory;
}
default_resize_bytes_align :: proc(old_data: []byte, new_size, alignment: int, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
old_memory := raw_data(old_data);
old_size := len(old_data);
if old_memory == nil {
return alloc_bytes(new_size, alignment, allocator, loc);
}
if new_size == 0 {
err := free_bytes(old_data, allocator, loc);
return nil, err;
}
if new_size == old_size {
return old_data, .None;
}
new_memory, err := alloc_bytes(new_size, alignment, allocator, loc);
if new_memory == nil || err != nil {
return nil, err;
}
runtime.copy(new_memory, old_data);
free_bytes(old_data, allocator, loc);
return new_memory, err;
}
File diff suppressed because it is too large Load Diff
+297
View File
@@ -0,0 +1,297 @@
package mem
import "core:runtime"
import "core:intrinsics"
set :: proc(data: rawptr, value: byte, len: int) -> rawptr {
return runtime.memset(data, i32(value), len);
}
zero :: proc(data: rawptr, len: int) -> rawptr {
return set(data, 0, len);
}
zero_item :: proc(item: $P/^$T) {
set(item, 0, size_of(T));
}
zero_slice :: proc(data: $T/[]$E) {
zero(raw_data(data), size_of(E)*len(data));
}
copy :: proc(dst, src: rawptr, len: int) -> rawptr {
return runtime.mem_copy(dst, src, len);
}
copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr {
return runtime.mem_copy_non_overlapping(dst, src, len);
}
compare :: proc(a, b: []byte) -> int {
res := compare_byte_ptrs(raw_data(a), raw_data(b), min(len(a), len(b)));
if res == 0 && len(a) != len(b) {
return len(a) <= len(b) ? -1 : +1;
} else if len(a) == 0 && len(b) == 0 {
return 0;
}
return res;
}
compare_byte_ptrs :: proc(a, b: ^byte, n: int) -> int #no_bounds_check {
switch {
case a == b:
return 0;
case a == nil:
return -1;
case b == nil:
return -1;
case n == 0:
return 0;
}
x := slice_ptr(a, n);
y := slice_ptr(b, n);
SU :: size_of(uintptr);
fast := n/SU + 1;
offset := (fast-1)*SU;
curr_block := 0;
if n < SU {
fast = 0;
}
la := slice_ptr((^uintptr)(a), fast);
lb := slice_ptr((^uintptr)(b), fast);
for /**/; curr_block < fast; curr_block += 1 {
if la[curr_block] ~ lb[curr_block] != 0 {
for pos := curr_block*SU; pos < n; pos += 1 {
if x[pos] ~ y[pos] != 0 {
return (int(x[pos]) - int(y[pos])) < 0 ? -1 : +1;
}
}
}
}
for /**/; offset < n; offset += 1 {
if x[offset] ~ y[offset] != 0 {
return (int(x[offset]) - int(y[offset])) < 0 ? -1 : +1;
}
}
return 0;
}
check_zero :: proc(data: []byte) -> bool {
return check_zero_ptr(raw_data(data), len(data));
}
check_zero_ptr :: proc(ptr: rawptr, len: int) -> bool {
switch {
case len <= 0:
return true;
case ptr == nil:
return true;
}
start := uintptr(ptr);
start_aligned := align_forward_uintptr(start, align_of(uintptr));
end := start + uintptr(len);
end_aligned := align_backward_uintptr(end, align_of(uintptr));
for b in start..<start_aligned {
if (^byte)(b)^ != 0 {
return false;
}
}
for b := start_aligned; b < end_aligned; b += size_of(uintptr) {
if (^uintptr)(b)^ != 0 {
return false;
}
}
for b in end_aligned..<end {
if (^byte)(b)^ != 0 {
return false;
}
}
return true;
}
simple_equal :: proc(a, b: $T) -> bool where intrinsics.type_is_simple_compare(T) {
a, b := a, b;
return compare_byte_ptrs((^byte)(&a), (^byte)(&b), size_of(T)) == 0;
}
compare_ptrs :: proc(a, b: rawptr, n: int) -> int {
return compare_byte_ptrs((^byte)(a), (^byte)(b), n);
}
ptr_offset :: proc(ptr: $P/^$T, n: int) -> P {
new := int(uintptr(ptr)) + size_of(T)*n;
return P(uintptr(new));
}
ptr_sub :: proc(a, b: $P/^$T) -> int {
return (int(uintptr(a)) - int(uintptr(b)))/size_of(T);
}
slice_ptr :: proc(ptr: ^$T, len: int) -> []T {
assert(len >= 0);
return transmute([]T)Raw_Slice{data = ptr, len = len};
}
byte_slice :: #force_inline proc "contextless" (data: rawptr, len: int) -> []byte {
return transmute([]u8)Raw_Slice{data=data, len=max(len, 0)};
}
slice_ptr_to_bytes :: proc(data: rawptr, len: int) -> []byte {
return transmute([]u8)Raw_Slice{data=data, len=max(len, 0)};
}
slice_to_bytes :: proc(slice: $E/[]$T) -> []byte {
s := transmute(Raw_Slice)slice;
s.len *= size_of(T);
return transmute([]byte)s;
}
slice_data_cast :: proc($T: typeid/[]$A, slice: $S/[]$B) -> T {
when size_of(A) == 0 || size_of(B) == 0 {
return nil;
} else {
s := transmute(Raw_Slice)slice;
s.len = (len(slice) * size_of(B)) / size_of(A);
return transmute(T)s;
}
}
slice_to_components :: proc(slice: $E/[]$T) -> (data: ^T, len: int) {
s := transmute(Raw_Slice)slice;
return s.data, s.len;
}
buffer_from_slice :: proc(backing: $T/[]$E) -> [dynamic]E {
return transmute([dynamic]E)Raw_Dynamic_Array{
data = raw_data(backing),
len = 0,
cap = len(backing),
allocator = nil_allocator(),
};
}
ptr_to_bytes :: proc(ptr: ^$T, len := 1) -> []byte {
assert(len >= 0);
return transmute([]byte)Raw_Slice{ptr, len*size_of(T)};
}
any_to_bytes :: proc(val: any) -> []byte {
ti := type_info_of(val.id);
size := ti != nil ? ti.size : 0;
return transmute([]byte)Raw_Slice{val.data, size};
}
kilobytes :: proc(x: int) -> int { return (x) * 1024; }
megabytes :: proc(x: int) -> int { return kilobytes(x) * 1024; }
gigabytes :: proc(x: int) -> int { return megabytes(x) * 1024; }
terabytes :: proc(x: int) -> int { return gigabytes(x) * 1024; }
is_power_of_two :: proc(x: uintptr) -> bool {
if x <= 0 {
return false;
}
return (x & (x-1)) == 0;
}
align_forward :: proc(ptr: rawptr, align: uintptr) -> rawptr {
return rawptr(align_forward_uintptr(uintptr(ptr), align));
}
align_forward_uintptr :: proc(ptr, align: uintptr) -> uintptr {
assert(is_power_of_two(align));
p := ptr;
modulo := p & (align-1);
if modulo != 0 {
p += align - modulo;
}
return p;
}
align_forward_int :: proc(ptr, align: int) -> int {
return int(align_forward_uintptr(uintptr(ptr), uintptr(align)));
}
align_forward_uint :: proc(ptr, align: uint) -> uint {
return uint(align_forward_uintptr(uintptr(ptr), uintptr(align)));
}
align_backward :: proc(ptr: rawptr, align: uintptr) -> rawptr {
return rawptr(align_backward_uintptr(uintptr(ptr), align));
}
align_backward_uintptr :: proc(ptr, align: uintptr) -> uintptr {
assert(is_power_of_two(align));
return align_forward_uintptr(ptr - align + 1, align);
}
align_backward_int :: proc(ptr, align: int) -> int {
return int(align_backward_uintptr(uintptr(ptr), uintptr(align)));
}
align_backward_uint :: proc(ptr, align: uint) -> uint {
return uint(align_backward_uintptr(uintptr(ptr), uintptr(align)));
}
context_from_allocator :: proc(a: Allocator) -> type_of(context) {
context.allocator = a;
return context;
}
Fixed_Byte_Buffer :: distinct [dynamic]byte;
make_fixed_byte_buffer :: proc(backing: []byte) -> Fixed_Byte_Buffer {
s := transmute(Raw_Slice)backing;
d: Raw_Dynamic_Array;
d.data = s.data;
d.len = 0;
d.cap = s.len;
d.allocator = nil_allocator();
return transmute(Fixed_Byte_Buffer)d;
}
align_formula :: proc(size, align: int) -> int {
result := size + align-1;
return result - result%align;
}
calc_padding_with_header :: proc(ptr: uintptr, align: uintptr, header_size: int) -> int {
p, a := ptr, align;
modulo := p & (a-1);
padding := uintptr(0);
if modulo != 0 {
padding = a - modulo;
}
needed_space := uintptr(header_size);
if padding < needed_space {
needed_space -= padding;
if needed_space & (a-1) > 0 {
padding += align * (1+(needed_space/align));
} else {
padding += align * (needed_space/align);
}
}
return int(padding);
}
clone_slice :: proc(slice: $T/[]$E, allocator := context.allocator, loc := #caller_location) -> T {
new_slice := make(T, len(slice), allocator, loc);
runtime.copy(new_slice, slice);
return new_slice;
}
+60
View File
@@ -0,0 +1,60 @@
package mem
Raw_Any :: struct {
data: rawptr,
id: typeid,
}
Raw_String :: struct {
data: ^byte,
len: int,
}
Raw_Cstring :: struct {
data: ^byte,
}
Raw_Slice :: struct {
data: rawptr,
len: int,
}
Raw_Dynamic_Array :: struct {
data: rawptr,
len: int,
cap: int,
allocator: Allocator,
}
Raw_Map :: struct {
hashes: []int,
entries: Raw_Dynamic_Array,
}
Raw_Complex64 :: struct {real, imag: f32};
Raw_Complex128 :: struct {real, imag: f64};
Raw_Quaternion128 :: struct {imag, jmag, kmag: f32, real: f32};
Raw_Quaternion256 :: struct {imag, jmag, kmag: f64, real: f64};
Raw_Quaternion128_Vector_Scalar :: struct {vector: [3]f32, scalar: f32};
Raw_Quaternion256_Vector_Scalar :: struct {vector: [3]f64, scalar: f64};
make_any :: proc(data: rawptr, id: typeid) -> any {
return transmute(any)Raw_Any{data, id};
}
raw_array_data :: proc(a: $P/^($T/[$N]$E)) -> ^E {
return (^E)(a);
}
raw_string_data :: proc(s: $T/string) -> ^byte {
return (transmute(Raw_String)s).data;
}
raw_slice_data :: proc(a: $T/[]$E) -> ^E {
return cast(^E)(transmute(Raw_Slice)a).data;
}
raw_dynamic_array_data :: proc(a: $T/[dynamic]$E) -> ^E {
return cast(^E)(transmute(Raw_Dynamic_Array)a).data;
}
raw_data :: proc{raw_array_data, raw_string_data, raw_slice_data, raw_dynamic_array_data};
+733
View File
@@ -0,0 +1,733 @@
package odin_ast
import "core:odin/tokenizer"
Proc_Tag :: enum {
Bounds_Check,
No_Bounds_Check,
Optional_Ok,
Optional_Second,
}
Proc_Tags :: distinct bit_set[Proc_Tag; u32];
Proc_Inlining :: enum u32 {
None = 0,
Inline = 1,
No_Inline = 2,
}
Proc_Calling_Convention :: enum i32 {
Invalid = 0,
Odin,
Contextless,
C_Decl,
Std_Call,
Fast_Call,
None,
Foreign_Block_Default = -1,
}
Node_State_Flag :: enum {
Bounds_Check,
No_Bounds_Check,
}
Node_State_Flags :: distinct bit_set[Node_State_Flag];
Node :: struct {
pos: tokenizer.Pos,
end: tokenizer.Pos,
state_flags: Node_State_Flags,
derived: any,
}
Comment_Group :: struct {
using node: Node,
list: []tokenizer.Token,
}
Package_Kind :: enum {
Normal,
Runtime,
Init,
}
Package :: struct {
using node: Node,
kind: Package_Kind,
id: int,
name: string,
fullpath: string,
files: map[string]^File,
user_data: rawptr,
}
File :: struct {
using node: Node,
id: int,
pkg: ^Package,
fullpath: string,
src: []byte,
docs: ^Comment_Group,
pkg_decl: ^Package_Decl,
pkg_token: tokenizer.Token,
pkg_name: string,
decls: [dynamic]^Stmt,
imports: [dynamic]^Import_Decl,
directive_count: int,
comments: [dynamic]^Comment_Group,
syntax_warning_count: int,
syntax_error_count: int,
}
// Base Types
Expr :: struct {
using expr_base: Node,
}
Stmt :: struct {
using stmt_base: Node,
}
Decl :: struct {
using decl_base: Stmt,
}
// Expressions
Bad_Expr :: struct {
using node: Expr,
}
Ident :: struct {
using node: Expr,
name: string,
}
Implicit :: struct {
using node: Expr,
tok: tokenizer.Token,
}
Undef :: struct {
using node: Expr,
tok: tokenizer.Token_Kind,
}
Basic_Lit :: struct {
using node: Expr,
tok: tokenizer.Token,
}
Basic_Directive :: struct {
using node: Expr,
tok: tokenizer.Token,
name: string,
}
Ellipsis :: struct {
using node: Expr,
tok: tokenizer.Token_Kind,
expr: ^Expr,
}
Proc_Lit :: struct {
using node: Expr,
type: ^Proc_Type,
body: ^Stmt,
tags: Proc_Tags,
inlining: Proc_Inlining,
where_token: tokenizer.Token,
where_clauses: []^Expr,
}
Comp_Lit :: struct {
using node: Expr,
type: ^Expr,
open: tokenizer.Pos,
elems: []^Expr,
close: tokenizer.Pos,
}
Tag_Expr :: struct {
using node: Expr,
op: tokenizer.Token,
name: string,
expr: ^Expr,
}
Unary_Expr :: struct {
using node: Expr,
op: tokenizer.Token,
expr: ^Expr,
}
Binary_Expr :: struct {
using node: Expr,
left: ^Expr,
op: tokenizer.Token,
right: ^Expr,
}
Paren_Expr :: struct {
using node: Expr,
open: tokenizer.Pos,
expr: ^Expr,
close: tokenizer.Pos,
}
Selector_Expr :: struct {
using node: Expr,
expr: ^Expr,
op: tokenizer.Token,
field: ^Ident,
}
Implicit_Selector_Expr :: struct {
using node: Expr,
field: ^Ident,
}
Selector_Call_Expr :: struct {
using node: Expr,
expr: ^Expr,
call: ^Call_Expr,
modified_call: bool,
}
Index_Expr :: struct {
using node: Expr,
expr: ^Expr,
open: tokenizer.Pos,
index: ^Expr,
close: tokenizer.Pos,
}
Deref_Expr :: struct {
using node: Expr,
expr: ^Expr,
op: tokenizer.Token,
}
Slice_Expr :: struct {
using node: Expr,
expr: ^Expr,
open: tokenizer.Pos,
low: ^Expr,
interval: tokenizer.Token,
high: ^Expr,
close: tokenizer.Pos,
}
Call_Expr :: struct {
using node: Expr,
inlining: Proc_Inlining,
expr: ^Expr,
open: tokenizer.Pos,
args: []^Expr,
ellipsis: tokenizer.Token,
close: tokenizer.Pos,
}
Field_Value :: struct {
using node: Expr,
field: ^Expr,
sep: tokenizer.Pos,
value: ^Expr,
}
Ternary_Expr :: struct {
using node: Expr,
cond: ^Expr,
op1: tokenizer.Token,
x: ^Expr,
op2: tokenizer.Token,
y: ^Expr,
}
Ternary_If_Expr :: struct {
using node: Expr,
x: ^Expr,
op1: tokenizer.Token,
cond: ^Expr,
op2: tokenizer.Token,
y: ^Expr,
}
Ternary_When_Expr :: struct {
using node: Expr,
x: ^Expr,
op1: tokenizer.Token,
cond: ^Expr,
op2: tokenizer.Token,
y: ^Expr,
}
Type_Assertion :: struct {
using node: Expr,
expr: ^Expr,
dot: tokenizer.Pos,
open: tokenizer.Pos,
type: ^Expr,
close: tokenizer.Pos,
}
Type_Cast :: struct {
using node: Expr,
tok: tokenizer.Token,
open: tokenizer.Pos,
type: ^Expr,
close: tokenizer.Pos,
expr: ^Expr,
}
Auto_Cast :: struct {
using node: Expr,
op: tokenizer.Token,
expr: ^Expr,
}
Inline_Asm_Dialect :: enum u8 {
Default = 0,
ATT = 1,
Intel = 2,
}
Inline_Asm_Expr :: struct {
using node: Expr,
tok: tokenizer.Token,
param_types: []^Expr,
return_type: ^Expr,
has_side_effects: bool,
is_align_stack: bool,
dialect: Inline_Asm_Dialect,
open: tokenizer.Pos,
constraints_string: ^Expr,
asm_string: ^Expr,
close: tokenizer.Pos,
}
// Statements
Bad_Stmt :: struct {
using node: Stmt,
}
Empty_Stmt :: struct {
using node: Stmt,
semicolon: tokenizer.Pos, // Position of the following ';'
}
Expr_Stmt :: struct {
using node: Stmt,
expr: ^Expr,
}
Tag_Stmt :: struct {
using node: Stmt,
op: tokenizer.Token,
name: string,
stmt: ^Stmt,
}
Assign_Stmt :: struct {
using node: Stmt,
lhs: []^Expr,
op: tokenizer.Token,
rhs: []^Expr,
}
Block_Stmt :: struct {
using node: Stmt,
label: ^Expr,
open: tokenizer.Pos,
stmts: []^Stmt,
close: tokenizer.Pos,
uses_do: bool,
}
If_Stmt :: struct {
using node: Stmt,
label: ^Expr,
if_pos: tokenizer.Pos,
init: ^Stmt,
cond: ^Expr,
body: ^Stmt,
else_pos: tokenizer.Pos,
else_stmt: ^Stmt,
}
When_Stmt :: struct {
using node: Stmt,
when_pos: tokenizer.Pos,
cond: ^Expr,
body: ^Stmt,
else_stmt: ^Stmt,
}
Return_Stmt :: struct {
using node: Stmt,
results: []^Expr,
}
Defer_Stmt :: struct {
using node: Stmt,
stmt: ^Stmt,
}
For_Stmt :: struct {
using node: Stmt,
label: ^Expr,
for_pos: tokenizer.Pos,
init: ^Stmt,
cond: ^Expr,
post: ^Stmt,
body: ^Stmt,
}
Range_Stmt :: struct {
using node: Stmt,
label: ^Expr,
for_pos: tokenizer.Pos,
vals: []^Expr,
in_pos: tokenizer.Pos,
expr: ^Expr,
body: ^Stmt,
}
Inline_Range_Stmt :: struct {
using node: Stmt,
label: ^Expr,
inline_pos: tokenizer.Pos,
for_pos: tokenizer.Pos,
val0: ^Expr,
val1: ^Expr,
in_pos: tokenizer.Pos,
expr: ^Expr,
body: ^Stmt,
}
Case_Clause :: struct {
using node: Stmt,
case_pos: tokenizer.Pos,
list: []^Expr,
terminator: tokenizer.Token,
body: []^Stmt,
}
Switch_Stmt :: struct {
using node: Stmt,
label: ^Expr,
switch_pos: tokenizer.Pos,
init: ^Stmt,
cond: ^Expr,
body: ^Stmt,
partial: bool,
}
Type_Switch_Stmt :: struct {
using node: Stmt,
label: ^Expr,
switch_pos: tokenizer.Pos,
tag: ^Stmt,
expr: ^Expr,
body: ^Stmt,
partial: bool,
}
Branch_Stmt :: struct {
using node: Stmt,
tok: tokenizer.Token,
label: ^Ident,
}
Using_Stmt :: struct {
using node: Stmt,
list: []^Expr,
}
// Declarations
Bad_Decl :: struct {
using node: Decl,
}
Value_Decl :: struct {
using node: Decl,
docs: ^Comment_Group,
attributes: [dynamic]^Attribute, // dynamic as parsing will add to them lazily
names: []^Expr,
type: ^Expr,
values: []^Expr,
comment: ^Comment_Group,
is_using: bool,
is_mutable: bool,
}
Package_Decl :: struct {
using node: Decl,
docs: ^Comment_Group,
token: tokenizer.Token,
name: string,
comment: ^Comment_Group,
}
Import_Decl :: struct {
using node: Decl,
docs: ^Comment_Group,
is_using: bool,
import_tok: tokenizer.Token,
name: tokenizer.Token,
relpath: tokenizer.Token,
fullpath: string,
comment: ^Comment_Group,
}
Foreign_Block_Decl :: struct {
using node: Decl,
docs: ^Comment_Group,
attributes: [dynamic]^Attribute, // dynamic as parsing will add to them lazily
tok: tokenizer.Token,
foreign_library: ^Expr,
body: ^Stmt,
}
Foreign_Import_Decl :: struct {
using node: Decl,
docs: ^Comment_Group,
attributes: [dynamic]^Attribute, // dynamic as parsing will add to them lazily
foreign_tok: tokenizer.Token,
import_tok: tokenizer.Token,
name: ^Ident,
collection_name: string,
fullpaths: []string,
comment: ^Comment_Group,
}
// Other things
unparen_expr :: proc(expr: ^Expr) -> (val: ^Expr) {
val = expr;
if expr == nil {
return;
}
for {
e, ok := val.derived.(Paren_Expr);
if !ok || e.expr == nil {
break;
}
val = e.expr;
}
return;
}
Field_Flag :: enum {
Ellipsis,
Using,
No_Alias,
C_Vararg,
Auto_Cast,
In,
Results,
Tags,
Default_Parameters,
Typeid_Token,
}
Field_Flags :: distinct bit_set[Field_Flag];
Field_Flags_Struct :: Field_Flags{
.Using,
.Tags,
};
Field_Flags_Record_Poly_Params :: Field_Flags{
.Typeid_Token,
.Default_Parameters,
};
Field_Flags_Signature :: Field_Flags{
.Ellipsis,
.Using,
.No_Alias,
.C_Vararg,
.Auto_Cast,
.Default_Parameters,
};
Field_Flags_Signature_Params :: Field_Flags_Signature | {Field_Flag.Typeid_Token};
Field_Flags_Signature_Results :: Field_Flags_Signature;
Proc_Group :: struct {
using node: Expr,
tok: tokenizer.Token,
open: tokenizer.Pos,
args: []^Expr,
close: tokenizer.Pos,
}
Attribute :: struct {
using node: Node,
tok: tokenizer.Token_Kind,
open: tokenizer.Pos,
elems: []^Expr,
close: tokenizer.Pos,
}
Field :: struct {
using node: Node,
docs: ^Comment_Group,
names: []^Expr, // Could be polymorphic
type: ^Expr,
default_value: ^Expr,
tag: tokenizer.Token,
flags: Field_Flags,
comment: ^Comment_Group,
}
Field_List :: struct {
using node: Node,
open: tokenizer.Pos,
list: []^Field,
close: tokenizer.Pos,
}
// Types
Typeid_Type :: struct {
using node: Expr,
tok: tokenizer.Token_Kind,
specialization: ^Expr,
}
Helper_Type :: struct {
using node: Expr,
tok: tokenizer.Token_Kind,
type: ^Expr,
}
Distinct_Type :: struct {
using node: Expr,
tok: tokenizer.Token_Kind,
type: ^Expr,
}
Poly_Type :: struct {
using node: Expr,
dollar: tokenizer.Pos,
type: ^Ident,
specialization: ^Expr,
}
Proc_Type :: struct {
using node: Expr,
tok: tokenizer.Token,
calling_convention: Proc_Calling_Convention,
params: ^Field_List,
arrow: tokenizer.Pos,
results: ^Field_List,
tags: Proc_Tags,
generic: bool,
diverging: bool,
}
Pointer_Type :: struct {
using node: Expr,
pointer: tokenizer.Pos,
elem: ^Expr,
}
Array_Type :: struct {
using node: Expr,
open: tokenizer.Pos,
tag: ^Expr,
len: ^Expr, // Ellipsis node for [?]T arrray types, nil for slice types
close: tokenizer.Pos,
elem: ^Expr,
}
Dynamic_Array_Type :: struct {
using node: Expr,
tag: ^Expr,
open: tokenizer.Pos,
dynamic_pos: tokenizer.Pos,
close: tokenizer.Pos,
elem: ^Expr,
}
Struct_Type :: struct {
using node: Expr,
tok_pos: tokenizer.Pos,
poly_params: ^Field_List,
align: ^Expr,
where_token: tokenizer.Token,
where_clauses: []^Expr,
is_packed: bool,
is_raw_union: bool,
fields: ^Field_List,
name_count: int,
}
Union_Type :: struct {
using node: Expr,
tok_pos: tokenizer.Pos,
poly_params: ^Field_List,
align: ^Expr,
is_maybe: bool,
where_token: tokenizer.Token,
where_clauses: []^Expr,
variants: []^Expr,
}
Enum_Type :: struct {
using node: Expr,
tok_pos: tokenizer.Pos,
base_type: ^Expr,
open: tokenizer.Pos,
fields: []^Expr,
close: tokenizer.Pos,
is_using: bool,
}
Bit_Set_Type :: struct {
using node: Expr,
tok_pos: tokenizer.Pos,
open: tokenizer.Pos,
elem: ^Expr,
underlying: ^Expr,
close: tokenizer.Pos,
}
Map_Type :: struct {
using node: Expr,
tok_pos: tokenizer.Pos,
key: ^Expr,
value: ^Expr,
}
Relative_Type :: struct {
using node: Expr,
tag: ^Expr,
type: ^Expr,
}
+281
View File
@@ -0,0 +1,281 @@
package odin_ast
import "core:mem"
import "core:fmt"
import "core:odin/tokenizer"
new :: proc($T: typeid, pos, end: tokenizer.Pos) -> ^T {
n := mem.new(T);
n.pos = pos;
n.end = end;
n.derived = n^;
base: ^Node = n; // dummy check
_ = base; // "Use" type to make -vet happy
return n;
}
clone :: proc{
clone_node,
clone_expr,
clone_stmt,
clone_decl,
clone_array,
clone_dynamic_array,
};
clone_array :: proc(array: $A/[]^$T) -> A {
if len(array) == 0 {
return nil;
}
res := make(A, len(array));
for elem, i in array {
res[i] = auto_cast clone(elem);
}
return res;
}
clone_dynamic_array :: proc(array: $A/[dynamic]^$T) -> A {
if len(array) == 0 {
return nil;
}
res := make(A, len(array));
for elem, i in array {
res[i] = auto_cast clone(elem);
}
return res;
}
clone_expr :: proc(node: ^Expr) -> ^Expr {
return cast(^Expr)clone_node(node);
}
clone_stmt :: proc(node: ^Stmt) -> ^Stmt {
return cast(^Stmt)clone_node(node);
}
clone_decl :: proc(node: ^Decl) -> ^Decl {
return cast(^Decl)clone_node(node);
}
clone_node :: proc(node: ^Node) -> ^Node {
if node == nil {
return nil;
}
size := size_of(Node);
align := align_of(Node);
ti := type_info_of(node.derived.id);
if ti != nil {
size = ti.size;
align = ti.align;
}
switch in node.derived {
case Package, File:
panic("Cannot clone this node type");
}
res := cast(^Node)mem.alloc(size, align);
src: rawptr = node;
if node.derived != nil {
src = node.derived.data;
}
mem.copy(res, src, size);
res.derived.data = rawptr(res);
res.derived.id = node.derived.id;
switch r in &res.derived {
case Bad_Expr:
case Ident:
case Implicit:
case Undef:
case Basic_Lit:
case Ellipsis:
r.expr = clone(r.expr);
case Proc_Lit:
r.type = auto_cast clone(r.type);
r.body = clone(r.body);
case Comp_Lit:
r.type = clone(r.type);
r.elems = clone(r.elems);
case Tag_Expr:
r.expr = clone(r.expr);
case Unary_Expr:
r.expr = clone(r.expr);
case Binary_Expr:
r.left = clone(r.left);
r.right = clone(r.right);
case Paren_Expr:
r.expr = clone(r.expr);
case Selector_Expr:
r.expr = clone(r.expr);
r.field = auto_cast clone(r.field);
case Implicit_Selector_Expr:
r.field = auto_cast clone(r.field);
case Selector_Call_Expr:
r.expr = clone(r.expr);
r.call = auto_cast clone(r.call);
case Index_Expr:
r.expr = clone(r.expr);
r.index = clone(r.index);
case Deref_Expr:
r.expr = clone(r.expr);
case Slice_Expr:
r.expr = clone(r.expr);
r.low = clone(r.low);
r.high = clone(r.high);
case Call_Expr:
r.expr = clone(r.expr);
r.args = clone(r.args);
case Field_Value:
r.field = clone(r.field);
r.value = clone(r.value);
case Ternary_Expr:
r.cond = clone(r.cond);
r.x = clone(r.x);
r.y = clone(r.y);
case Ternary_If_Expr:
r.x = clone(r.x);
r.cond = clone(r.cond);
r.y = clone(r.y);
case Ternary_When_Expr:
r.x = clone(r.x);
r.cond = clone(r.cond);
r.y = clone(r.y);
case Type_Assertion:
r.expr = clone(r.expr);
r.type = clone(r.type);
case Type_Cast:
r.type = clone(r.type);
r.expr = clone(r.expr);
case Auto_Cast:
r.expr = clone(r.expr);
case Inline_Asm_Expr:
r.param_types = clone(r.param_types);
r.return_type = clone(r.return_type);
r.constraints_string = clone(r.constraints_string);
r.asm_string = clone(r.asm_string);
case Bad_Stmt:
// empty
case Empty_Stmt:
// empty
case Expr_Stmt:
r.expr = clone(r.expr);
case Tag_Stmt:
r.stmt = clone(r.stmt);
case Assign_Stmt:
r.lhs = clone(r.lhs);
r.rhs = clone(r.rhs);
case Block_Stmt:
r.label = auto_cast clone(r.label);
r.stmts = clone(r.stmts);
case If_Stmt:
r.label = auto_cast clone(r.label);
r.init = clone(r.init);
r.cond = clone(r.cond);
r.body = clone(r.body);
r.else_stmt = clone(r.else_stmt);
case When_Stmt:
r.cond = clone(r.cond);
r.body = clone(r.body);
r.else_stmt = clone(r.else_stmt);
case Return_Stmt:
r.results = clone(r.results);
case Defer_Stmt:
r.stmt = clone(r.stmt);
case For_Stmt:
r.label = auto_cast clone(r.label);
r.init = clone(r.init);
r.cond = clone(r.cond);
r.post = clone(r.post);
r.body = clone(r.body);
case Range_Stmt:
r.label = auto_cast clone(r.label);
r.vals = clone(r.vals);
r.expr = clone(r.expr);
r.body = clone(r.body);
case Case_Clause:
r.list = clone(r.list);
r.body = clone(r.body);
case Switch_Stmt:
r.label = auto_cast clone(r.label);
r.init = clone(r.init);
r.cond = clone(r.cond);
r.body = clone(r.body);
case Type_Switch_Stmt:
r.label = auto_cast clone(r.label);
r.tag = clone(r.tag);
r.expr = clone(r.expr);
r.body = clone(r.body);
case Branch_Stmt:
r.label = auto_cast clone(r.label);
case Using_Stmt:
r.list = clone(r.list);
case Bad_Decl:
case Value_Decl:
r.attributes = clone(r.attributes);
r.names = clone(r.names);
r.type = clone(r.type);
r.values = clone(r.values);
case Package_Decl:
case Import_Decl:
case Foreign_Block_Decl:
r.attributes = clone(r.attributes);
r.foreign_library = clone(r.foreign_library);
r.body = clone(r.body);
case Foreign_Import_Decl:
r.name = auto_cast clone(r.name);
case Proc_Group:
r.args = clone(r.args);
case Attribute:
r.elems = clone(r.elems);
case Field:
r.names = clone(r.names);
r.type = clone(r.type);
r.default_value = clone(r.default_value);
case Field_List:
r.list = clone(r.list);
case Typeid_Type:
r.specialization = clone(r.specialization);
case Helper_Type:
r.type = clone(r.type);
case Distinct_Type:
r.type = clone(r.type);
case Poly_Type:
r.type = auto_cast clone(r.type);
r.specialization = clone(r.specialization);
case Proc_Type:
r.params = auto_cast clone(r.params);
r.results = auto_cast clone(r.results);
case Pointer_Type:
r.elem = clone(r.elem);
case Array_Type:
r.len = clone(r.len);
r.elem = clone(r.elem);
case Dynamic_Array_Type:
r.elem = clone(r.elem);
case Struct_Type:
r.poly_params = auto_cast clone(r.poly_params);
r.align = clone(r.align);
r.fields = auto_cast clone(r.fields);
case Union_Type:
r.poly_params = auto_cast clone(r.poly_params);
r.align = clone(r.align);
r.variants = clone(r.variants);
case Enum_Type:
r.base_type = clone(r.base_type);
r.fields = clone(r.fields);
case Bit_Set_Type:
r.elem = clone(r.elem);
r.underlying = clone(r.underlying);
case Map_Type:
r.key = clone(r.key);
r.value = clone(r.value);
case:
fmt.panicf("Unhandled node kind: %T", r);
}
return res;
}
+405
View File
@@ -0,0 +1,405 @@
package odin_ast
import "core:fmt"
// A Visitor's visit procedure is invoked for each node encountered by walk
// If the result visitor is not nil, walk visits each of the children of node with the new visitor,
// followed by a call of v.visit(v, nil)
Visitor :: struct {
visit: proc(visitor: ^Visitor, node: ^Node) -> ^Visitor,
data: rawptr,
}
// inspect traverses an AST in depth-first order
// It starts by calling f(node), and node must be non-nil
// If f returns true, inspect invokes f recursively for each of the non-nil children of node,
// followed by a call of f(nil)
inspect :: proc(node: ^Node, f: proc(^Node) -> bool) {
v := &Visitor{
visit = proc(v: ^Visitor, node: ^Node) -> ^Visitor {
f := (proc(^Node) -> bool)(v.data);
if f(node) {
return v;
}
return nil;
},
data = rawptr(f),
};
walk(v, node);
}
// walk traverses an AST in depth-first order: It starts by calling v.visit(v, node), and node must not be nil
// If the visitor returned by v.visit(v, node) is not nil, walk is invoked recursively with the new visitor for
// each of the non-nil children of node, followed by a call of the new visit procedure
walk :: proc(v: ^Visitor, node: ^Node) {
walk_expr_list :: proc(v: ^Visitor, list: []^Expr) {
for x in list {
walk(v, x);
}
}
walk_stmt_list :: proc(v: ^Visitor, list: []^Stmt) {
for x in list {
walk(v, x);
}
}
walk_attribute_list :: proc(v: ^Visitor, list: []^Attribute) {
for x in list {
walk(v, x);
}
}
v := v;
if v = v->visit(node); v == nil {
return;
}
switch n in &node.derived {
case File:
if n.docs != nil {
walk(v, n.docs);
}
walk_stmt_list(v, n.decls[:]);
case Package:
for _, f in n.files {
walk(v, f);
}
case Comment_Group:
// empty
case Bad_Expr:
case Ident:
case Implicit:
case Undef:
case Basic_Lit:
case Basic_Directive:
case Ellipsis:
if n.expr != nil {
walk(v, n.expr);
}
case Proc_Lit:
walk(v, n.type);
walk(v, n.body);
walk_expr_list(v, n.where_clauses);
case Comp_Lit:
if n.type != nil {
walk(v, n.type);
}
walk_expr_list(v, n.elems);
case Tag_Expr:
walk(v, n.expr);
case Unary_Expr:
walk(v, n.expr);
case Binary_Expr:
walk(v, n.left);
walk(v, n.right);
case Paren_Expr:
walk(v, n.expr);
case Selector_Expr:
walk(v, n.expr);
walk(v, n.field);
case Implicit_Selector_Expr:
walk(v, n.field);
case Selector_Call_Expr:
walk(v, n.expr);
walk(v, n.call);
case Index_Expr:
walk(v, n.expr);
walk(v, n.index);
case Deref_Expr:
walk(v, n.expr);
case Slice_Expr:
walk(v, n.expr);
if n.low != nil {
walk(v, n.low);
}
if n.high != nil {
walk(v, n.high);
}
case Call_Expr:
walk(v, n.expr);
walk_expr_list(v, n.args);
case Field_Value:
walk(v, n.field);
walk(v, n.value);
case Ternary_Expr:
walk(v, n.cond);
walk(v, n.x);
walk(v, n.y);
case Ternary_If_Expr:
walk(v, n.x);
walk(v, n.cond);
walk(v, n.y);
case Ternary_When_Expr:
walk(v, n.x);
walk(v, n.cond);
walk(v, n.y);
case Type_Assertion:
walk(v, n.expr);
if n.type != nil {
walk(v, n.type);
}
case Type_Cast:
walk(v, n.type);
walk(v, n.expr);
case Auto_Cast:
walk(v, n.expr);
case Inline_Asm_Expr:
walk_expr_list(v, n.param_types);
walk(v, n.return_type);
walk(v, n.constraints_string);
walk(v, n.asm_string);
case Bad_Stmt:
case Empty_Stmt:
case Expr_Stmt:
walk(v, n.expr);
case Tag_Stmt:
walk(v, n.stmt);
case Assign_Stmt:
walk_expr_list(v, n.lhs);
walk_expr_list(v, n.rhs);
case Block_Stmt:
if n.label != nil {
walk(v, n.label);
}
walk_stmt_list(v, n.stmts);
case If_Stmt:
if n.label != nil {
walk(v, n.label);
}
if n.init != nil {
walk(v, n.init);
}
walk(v, n.cond);
walk(v, n.body);
if n.else_stmt != nil {
walk(v, n.else_stmt);
}
case When_Stmt:
walk(v, n.cond);
walk(v, n.body);
if n.else_stmt != nil {
walk(v, n.else_stmt);
}
case Return_Stmt:
walk_expr_list(v, n.results);
case Defer_Stmt:
walk(v, n.stmt);
case For_Stmt:
if n.label != nil {
walk(v, n.label);
}
if n.init != nil {
walk(v, n.init);
}
if n.cond != nil {
walk(v, n.cond);
}
if n.post != nil {
walk(v, n.post);
}
walk(v, n.body);
case Range_Stmt:
if n.label != nil {
walk(v, n.label);
}
for val in n.vals {
if val != nil {
walk(v, val);
}
}
walk(v, n.expr);
walk(v, n.body);
case Inline_Range_Stmt:
if n.label != nil {
walk(v, n.label);
}
if n.val0 != nil {
walk(v, n.val0);
}
if n.val1 != nil {
walk(v, n.val1);
}
walk(v, n.expr);
walk(v, n.body);
case Case_Clause:
walk_expr_list(v, n.list);
walk_stmt_list(v, n.body);
case Switch_Stmt:
if n.label != nil {
walk(v, n.label);
}
if n.init != nil {
walk(v, n.init);
}
if n.cond != nil {
walk(v, n.cond);
}
walk(v, n.body);
case Type_Switch_Stmt:
if n.label != nil {
walk(v, n.label);
}
if n.tag != nil {
walk(v, n.tag);
}
if n.expr != nil {
walk(v, n.expr);
}
walk(v, n.body);
case Branch_Stmt:
if n.label != nil {
walk(v, n.label);
}
case Using_Stmt:
walk_expr_list(v, n.list);
case Bad_Decl:
case Value_Decl:
if n.docs != nil {
walk(v, n.docs);
}
walk_attribute_list(v, n.attributes[:]);
walk_expr_list(v, n.names);
if n.type != nil {
walk(v, n.type);
}
walk_expr_list(v, n.values);
if n.comment != nil {
walk(v, n.comment);
}
case Package_Decl:
if n.docs != nil {
walk(v, n.docs);
}
if n.comment != nil {
walk(v, n.comment);
}
case Import_Decl:
if n.docs != nil {
walk(v, n.docs);
}
if n.comment != nil {
walk(v, n.comment);
}
case Foreign_Block_Decl:
if n.docs != nil {
walk(v, n.docs);
}
walk_attribute_list(v, n.attributes[:]);
if n.foreign_library != nil {
walk(v, n.foreign_library);
}
walk(v, n.body);
case Foreign_Import_Decl:
if n.docs != nil {
walk(v, n.docs);
}
walk_attribute_list(v, n.attributes[:]);
walk(v, n.name);
if n.comment != nil {
walk(v, n.comment);
}
case Proc_Group:
walk_expr_list(v, n.args);
case Attribute:
walk_expr_list(v, n.elems);
case Field:
if n.docs != nil {
walk(v, n.docs);
}
walk_expr_list(v, n.names);
if n.type != nil {
walk(v, n.type);
}
if n.default_value != nil {
walk(v, n.default_value);
}
if n.comment != nil {
walk(v, n.comment);
}
case Field_List:
for x in n.list {
walk(v, x);
}
case Typeid_Type:
if n.specialization != nil {
walk(v, n.specialization);
}
case Helper_Type:
walk(v, n.type);
case Distinct_Type:
walk(v, n.type);
case Poly_Type:
walk(v, n.type);
if n.specialization != nil {
walk(v, n.specialization);
}
case Proc_Type:
walk(v, n.params);
walk(v, n.results);
case Pointer_Type:
walk(v, n.elem);
case Array_Type:
if n.tag != nil {
walk(v, n.tag);
}
if n.len != nil {
walk(v, n.len);
}
walk(v, n.elem);
case Dynamic_Array_Type:
if n.tag != nil {
walk(v, n.tag);
}
walk(v, n.elem);
case Struct_Type:
if n.poly_params != nil {
walk(v, n.poly_params);
}
if n.align != nil {
walk(v, n.align);
}
walk_expr_list(v, n.where_clauses);
walk(v, n.fields);
case Union_Type:
if n.poly_params != nil {
walk(v, n.poly_params);
}
if n.align != nil {
walk(v, n.align);
}
walk_expr_list(v, n.where_clauses);
walk_expr_list(v, n.variants);
case Enum_Type:
if n.base_type != nil {
walk(v, n.base_type);
}
walk_expr_list(v, n.fields);
case Bit_Set_Type:
walk(v, n.elem);
if n.underlying != nil {
walk(v, n.underlying);
}
case Map_Type:
walk(v, n.key);
walk(v, n.value);
case Relative_Type:
walk(v, n.tag);
walk(v, n.type);
case:
fmt.panicf("ast.walk: unexpected node type %T", n);
}
v->visit(nil);
}
+256
View File
@@ -0,0 +1,256 @@
package odin_doc_format
import "core:mem"
Array :: struct($T: typeid) {
offset: u32le,
length: u32le,
}
String :: distinct Array(byte);
Version_Type_Major :: 0;
Version_Type_Minor :: 1;
Version_Type_Patch :: 0;
Version_Type :: struct {
major, minor, patch: u8,
_: u8,
};
Version_Type_Default :: Version_Type{
major=Version_Type_Major,
minor=Version_Type_Minor,
patch=Version_Type_Patch,
};
Magic_String :: "odindoc\x00";
Header_Base :: struct {
magic: [8]byte,
_: u32le,
version: Version_Type,
total_size: u32le,
header_size: u32le,
hash: u32le,
}
Header :: struct {
using base: Header_Base,
// NOTE: These arrays reserve the zero element as a sentinel value
files: Array(File),
pkgs: Array(Pkg),
entities: Array(Entity),
types: Array(Type),
}
File_Index :: distinct u32le;
Pkg_Index :: distinct u32le;
Entity_Index :: distinct u32le;
Type_Index :: distinct u32le;
Position :: struct {
file: File_Index,
line: u32le,
column: u32le,
offset: u32le,
};
File :: struct {
pkg: Pkg_Index,
name: String,
}
Pkg_Flag :: enum u32le {
Builtin = 0,
Runtime = 1,
Init = 2,
}
Pkg_Flags :: distinct bit_set[Pkg_Flag; u32le];
Pkg :: struct {
fullpath: String,
name: String,
flags: Pkg_Flags,
docs: String,
files: Array(File_Index),
entities: Array(Entity_Index),
}
Entity_Kind :: enum u32le {
Invalid = 0,
Constant = 1,
Variable = 2,
Type_Name = 3,
Procedure = 4,
Proc_Group = 5,
Import_Name = 6,
Library_Name = 7,
}
Entity_Flag :: enum u32le {
Foreign = 0,
Export = 1,
Param_Using = 2,
Param_Const = 3,
Param_Auto_Cast = 4,
Param_Ellipsis = 5,
Param_CVararg = 6,
Param_No_Alias = 7,
Type_Alias = 8,
Var_Thread_Local = 9,
}
Entity_Flags :: distinct bit_set[Entity_Flag; u32le];
Entity :: struct {
kind: Entity_Kind,
flags: Entity_Flags,
pos: Position,
name: String,
type: Type_Index,
init_string: String,
_: u32le,
comment: String,
docs: String,
foreign_library: Entity_Index,
link_name: String,
attributes: Array(Attribute),
grouped_entities: Array(Entity_Index), // Procedure Groups
where_clauses: Array(String), // Procedures
}
Attribute :: struct {
name: String,
value: String,
}
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,
}
Type_Elems_Cap :: 4;
Type :: struct {
kind: Type_Kind,
flags: u32le, // Type_Kind specific
name: String,
custom_align: String,
// Used by some types
elem_count_len: u32le,
elem_counts: [Type_Elems_Cap]i64le,
// Each of these is esed by some types, not all
calling_convention: String, // Procedures
types: Array(Type_Index),
entities: Array(Entity_Index),
polymorphic_params: Type_Index, // Struct, Union
where_clauses: Array(String), // Struct, Union
}
Type_Flags_Basic :: distinct bit_set[Type_Flag_Basic; u32le];
Type_Flag_Basic :: enum u32le {
Untyped = 1,
}
Type_Flags_Struct :: distinct bit_set[Type_Flag_Struct; u32le];
Type_Flag_Struct :: enum u32le {
Polymorphic = 0,
Packed = 1,
Raw_Union = 2,
}
Type_Flags_Union :: distinct bit_set[Type_Flag_Union; u32le];
Type_Flag_Union :: enum u32le {
Polymorphic = 0,
No_Nil = 1,
Maybe = 2,
}
Type_Flags_Proc :: distinct bit_set[Type_Flag_Proc; u32le];
Type_Flag_Proc :: enum u32le {
Polymorphic = 0,
Diverging = 1,
Optional_Ok = 2,
Variadic = 3,
C_Vararg = 4,
}
Type_Flags_Bit_Set :: distinct bit_set[Type_Flag_Bit_Set; u32le];
Type_Flag_Bit_Set :: enum u32le {
Range = 1,
Op_Lt = 2,
Op_Lt_Eq = 3,
Underlying_Type = 4,
}
from_array :: proc(base: ^Header_Base, a: $A/Array($T)) -> []T {
s: mem.Raw_Slice;
s.data = rawptr(uintptr(base) + uintptr(a.offset));
s.len = int(a.length);
return transmute([]T)s;
}
from_string :: proc(base: ^Header_Base, s: String) -> string {
return string(from_array(base, s));
}
Reader_Error :: enum {
None,
Header_Too_Small,
Invalid_Magic,
Data_Too_Small,
Invalid_Version,
}
read_from_bytes :: proc(data: []byte) -> (h: ^Header, err: Reader_Error) {
if len(data) < size_of(Header_Base) {
err = .Header_Too_Small;
return;
}
header_base := (^Header_Base)(raw_data(data));
if header_base.magic != Magic_String {
err = .Invalid_Magic;
return;
}
if len(data) < int(header_base.total_size) {
err = .Data_Too_Small;
return;
}
if header_base.version != Version_Type_Default {
err = .Invalid_Version;
return;
}
h = (^Header)(header_base);
return;
}

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