Compare commits

...

116 Commits

Author SHA1 Message Date
gingerBill 73beed0477 Merge pull request #1921 from Hyp-X/master
Update user32.odin
2022-08-02 12:15:44 +01:00
gingerBill e0ecdd4b24 Simplify logic of append of zero sized elements 2022-08-02 11:13:53 +01:00
gingerBill 5168cf03a9 Remove dead #maybe code 2022-08-01 15:38:50 +01:00
gingerBill b886ae6515 Simplify parser logic for field prefixes 2022-08-01 15:32:17 +01:00
gingerBill 277a973b98 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-08-01 15:24:23 +01:00
gingerBill 0ec4d97bfd Correct parser logic for is_token_field_prefix 2022-08-01 15:24:17 +01:00
Hyp-X e6236e5c3e Update user32.odin
Added UnregisterClassW procedure to windows\user32.odin
2022-08-01 15:59:00 +02:00
gingerBill e201280844 Merge pull request #1920 from Hyp-X/master
Update dxgi.odin
2022-08-01 14:40:39 +01:00
gingerBill 8e50a6c61b Merge pull request #1876 from mohd-akram/build-config-opts
Allow passing config options to build script
2022-08-01 14:33:35 +01:00
Hyp-X 7e6f5f89d0 Merge branch 'odin-lang:master' into master 2022-08-01 14:44:57 +02:00
gingerBill 97acc57649 Simplify field prefix handling 2022-08-01 13:17:10 +01:00
gingerBill 83c8c48ed7 Simplify ast parsing for prefixes 2022-08-01 13:07:49 +01:00
Hyp-X 0815b4d59f Update dxgi.odin
Fixed CreateDXGIFactory* last parameter to be ^rawptr instead of rawptr
2022-08-01 14:04:12 +02:00
gingerBill a0135080b3 Merge pull request #1917 from lerno/added_virtuals_macos
Added virtual memory headers for Darwin.
2022-07-30 19:38:37 +01:00
Christoffer Lerno f45e8e5d47 Added virtual memory headers for Darwin. 2022-07-29 20:01:26 +02:00
Jeroen van Rijn 98ba4beede Merge pull request #1916 from wjlroe/glfw-3-3-8-darwin-universal-static-libs
GLFW 3.3.8 Darwin universal and Windows static libs
2022-07-28 16:55:42 +02:00
William Roe a9304f2fef Update Windows GLFW libraries to 3.3.8
This matches the latest libraries committed for macOS/Darwin
2022-07-28 15:38:14 +01:00
William Roe a0697ab057 Fix build on Apple Silicon when linking to GLFW
This also updates the library to GLFW 3.3.8
This includes the lib-universal static library, rather than just the
Intel one (lib-x86_64), so software building with GLFW on Apple Silicon
will work again.
2022-07-28 15:29:30 +01:00
Jeroen van Rijn 2e895c72d3 Merge pull request #1447 from phillvancejr/master
Added vendor glfw support for Mac OS
2022-07-28 16:05:59 +02:00
Jeroen van Rijn 674ebe395f Merge branch 'master' into master 2022-07-28 16:01:18 +02:00
Jeroen van Rijn 96eecaab54 Merge pull request #1915 from JorriFransen/fix-simd_abs
Changed param count from 2 to 1 for simd_abs.
2022-07-28 15:36:16 +02:00
Jorri Fransen b1ae5bc9fe Changed param count from 2 to 1 for simd_abs. 2022-07-28 15:28:26 +02:00
Jeroen van Rijn 7258588ed5 Merge pull request #1914 from wjlroe/fix-json-unmarshal-without-assertions-bug
Fix bug unmarshalling JSON with assertions disabled
2022-07-28 15:03:47 +02:00
William Roe d913155972 Fix bug unmarshalling JSON with assertions disabled
When asserts are disabled, code within the assert isn't run. Having
expect_token within an assert means that the state of the Parser is
mutated when asserts are run, but not when they aren't.

There's already a wrapper procedure for this pattern, which I have
reused here.
2022-07-28 13:56:14 +01:00
pvance 9746e25784 Update stb_image_resize.odin 2022-07-28 04:27:42 -04:00
pvance d26cfd2141 Update bindings.odin 2022-07-28 04:26:22 -04:00
pvance 21f2c06f4b Update stb_image_resize.odin 2022-07-28 04:25:18 -04:00
pvance 727a25f41f Replace ODIN_OS strings with enum values 2022-07-28 04:23:24 -04:00
pvance 3f27cb2309 replace ODIN_OS string with enums 2022-07-28 04:22:00 -04:00
pvance f213622982 replace ODIN_OS string with enums 2022-07-28 04:20:37 -04:00
pvance 4aad835a66 replaced ODIN_OS string values with enums 2022-07-28 04:19:28 -04:00
Jeroen van Rijn 4af8a64580 Merge pull request #1907 from thePHTest/minor-fix
remove leftover print statement
2022-07-26 01:00:38 +02:00
Phil c9c3611b1d remove leftover print statement 2022-07-25 15:46:47 -07:00
gingerBill 220dfd7440 Minor clean up of wasi_api.odin 2022-07-25 17:00:32 +01:00
gingerBill bce8819ed5 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-07-25 12:12:32 +01:00
gingerBill 5f2b220a85 Fix minor issue with a lack of a trailing comma 2022-07-25 12:12:25 +01:00
gingerBill f174c805a9 Merge pull request #1905 from DanielGavin/glob-fix
Change open to be read only when opening directory
2022-07-25 10:43:28 +01:00
Daniel Gavin 25869b7504 Change open to be read only when opening directory 2022-07-25 11:34:03 +02:00
Mikkel Hjortshøj ecd81e8a53 Update stale.yml 2022-07-25 00:14:07 +02:00
gingerBill d7f9f7f170 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-07-24 23:07:41 +01:00
gingerBill 08f5259d77 Replace insert_at with inject_at and assign_at 2022-07-24 23:07:35 +01:00
Mikkel Hjortshøj a9f744cb64 Update stale.yml 2022-07-25 00:07:29 +02:00
Mikkel Hjortshøj b02e42c6dc Update stale.yml 2022-07-25 00:05:36 +02:00
Mikkel Hjortshøj cb0273b5d7 Update stale.yml 2022-07-24 23:58:43 +02:00
Mikkel Hjortshøj 8dbf45a65a Update stale.yml 2022-07-24 23:54:39 +02:00
gingerBill 9f64de9568 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-07-24 22:51:39 +01:00
gingerBill 0ebe9ba487 Fix #1901 2022-07-24 22:51:34 +01:00
Mikkel Hjortshøj efe00e1aa6 Create stale.yml 2022-07-24 23:48:34 +02:00
gingerBill 2bdbce55f9 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-07-24 22:46:07 +01:00
gingerBill 9614ca92f0 Fix #1834 2022-07-24 22:46:00 +01:00
gingerBill d30e59f539 Merge pull request #1844 from Ronaldr1985/fix-odin-on-openbsd
Added missing #includes on OpenBSD
2022-07-24 22:28:25 +01:00
Mikkel Hjortshøj a3afe617c2 Update ci.yml 2022-07-24 23:27:07 +02:00
gingerBill 69daac583e Merge pull request #1898 from DaseinPhaos/patch-1
fix `linalg.angle_from_quaternion`
2022-07-24 22:18:36 +01:00
gingerBill b28d4b753b Temp fix for lb_emit_store 2022-07-24 20:58:50 +01:00
gingerBill e6ab4f4856 Force memset instead of store zeroinitializer when the value is large 2022-07-24 20:22:50 +01:00
gingerBill c8ab1b7ee1 Add #by_ptr procedure attribute to enforce a parameter to be passed by pointer internally 2022-07-24 13:11:48 +01:00
gingerBill 9f10487678 Fix #1493 2022-07-24 12:59:34 +01:00
gingerBill 2542983d70 Fix #1793 2022-07-24 12:54:05 +01:00
gingerBill d492fb3501 Fix and improve x->y() behaviour to minimize duplicate evaluation 2022-07-24 12:39:59 +01:00
Ronald1985 1829aa1638 Undo changes to common.cpp and move the include of sys/wait.h to gb.h 2022-07-22 23:08:46 +01:00
Ronald1985 4cb4173ced Updated shabang in build_odin.sh so it runs on OpenBSD
This change doesn't break compatibility on Linux or Darwin
2022-07-22 23:01:38 +01:00
Luxko 00e704b216 fix linalg.angle_from_quaternion
fixes #1894 .2:
```odin
package laa
import "core:fmt"
import la "core:math/linalg"

main:: proc() {
    angle := f32(0.5)
    quat  := la.quaternion_angle_axis_f32(angle,la.Vector3f32{0,0,1})
    fmt.printf("retreived: %0.8f\n",  la.angle_from_quaternion(quat)) // should be 0.5, but wasn't
}
```
2022-07-23 00:59:45 +08:00
gingerBill 227ee0f705 Merge pull request #1895 from yeongjukang/patch-1
fix parameter for atan2 in procedure math.asin
2022-07-22 11:23:46 +01:00
gingerBill 17f47a7ab0 Merge pull request #1892 from esnunes/vendor-raylib-4.0-macos-arm64
Update `vendor:raylib` to support macos-arm64 (apple silicon)
2022-07-22 11:06:16 +01:00
Yeongju Kang 4e8bc0786d fix parameter for atan2 in procedure asin 2022-07-22 15:48:06 +09:00
gingerBill 3d3ccf061f Merge pull request #1893 from Tetralux/slash-join-slice
[path/slashpath] Change join() to take a slice instead of varargs
2022-07-21 18:59:04 +01:00
Tetralux 3a8adc6721 [path/slashpath] Change join() to take a slice instead of varargs
Achieves parity with filepath.join(), which was similarly changed a while back.
2022-07-21 17:49:31 +00:00
gingerBill e1748a5dd1 Add MAKE_WORD 2022-07-21 17:08:11 +01:00
Eduardo Nunes 59b4c889d3 Update vendor:raylib to support macos-arm64 (apple silicon) 2022-07-20 18:23:09 -03:00
gingerBill b6408d1b3f Merge branch 'master' of https://github.com/odin-lang/Odin 2022-07-19 16:17:45 +01:00
gingerBill 3db3047f47 Minor improvements 2022-07-19 16:17:23 +01:00
gingerBill 7420fbd95b Add custom event handling to wasm 2022-07-19 16:16:51 +01:00
gingerBill 7c990b3833 Merge pull request #1877 from fabiansperber/improve-debug-info
Improve debug info
2022-07-19 00:49:22 +01:00
Fabian Sperber 9c059f1a12 Fix debug info for type switch variable to be only visible in correct switch case
- use correct scopes for type switch
2022-07-19 00:46:28 +02:00
Fabian Sperber fb167d1d0a Fix loop var (init) becoming hidden while stepping on the for-line
- set debug location of jumps between block (similar to clang to the location of 'for')
- extend scope range to include all parts of the for-stmt
2022-07-19 00:46:27 +02:00
Fabian Sperber 0992239d86 Embed natvis in windows debug build for easier viewing of strings and Arrays 2022-07-19 00:46:27 +02:00
gingerBill 9eb3da0474 Remove import cycle on FreeBSD 2022-07-18 15:20:28 +01:00
gingerBill e91f8feedf Keep -vet happy 2022-07-18 15:12:54 +01:00
gingerBill 22a0c3fce1 Disallow proc() do stmt and only allow proc() { stmt } 2022-07-18 15:09:04 +01:00
gingerBill 6c7e5748a8 Integrate numerous debug fixes from #1877 2022-07-18 12:49:29 +01:00
gingerBill 0b0c6da8b0 Merge pull request #1873 from weshardee/master
fix -build-mode:shared on MacOS
2022-07-18 12:42:53 +01:00
gingerBill 78826071c0 Fix #1836 2022-07-16 23:14:09 +01:00
gingerBill e61b73d7ad Fix #1869 2022-07-16 22:30:57 +01:00
gingerBill f886632bf1 Fix #1880 2022-07-16 22:18:07 +01:00
gingerBill eafa5098aa Fix #1883 2022-07-16 18:03:43 +01:00
gingerBill 0571b80d37 Fix printing of bit_set types 2022-07-16 17:56:38 +01:00
gingerBill 80c10644dd Remove assert 2022-07-16 17:39:13 +01:00
gingerBill 041625381c Fix #1888 2022-07-16 17:36:03 +01:00
gingerBill 48f56d728b Merge branch 'master' of https://github.com/odin-lang/Odin 2022-07-16 16:12:24 +01:00
gingerBill 872d391cfb Mock up for the ability to enforce our own runtime.memset if necessary 2022-07-16 16:12:16 +01:00
Jeroen van Rijn 3e6ec65dd9 Fix murmur64a's tail handling.
Also, split up the murmur64 proc into murmur64a and murmur64b as they're distinct hashes with their own output.
2022-07-15 13:02:07 +02:00
gingerBill 157c87b2a2 Fix typo 2022-07-15 00:34:26 +01:00
gingerBill d3081bd889 Add buffer_read_ptr and buffer_write_ptr 2022-07-14 15:26:50 +01:00
gingerBill 2ae5bf4395 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-07-14 11:56:13 +01:00
gingerBill f28547cae1 Fix libc.putchar 2022-07-14 11:56:05 +01:00
Jeroen van Rijn 5332705e31 [hash] Give crc-64 a 64-bit seed. 2022-07-14 11:07:52 +02:00
gingerBill bfb082cda4 Merge pull request #1881 from odin-lang/strings-builder-cleanup
Rename strings.Builder procedures to be consistent with the rest of the core library
2022-07-13 16:09:19 +01:00
gingerBill 37d04198ab Add improved error message when doing ^x instead of &x for addressable variables 2022-07-11 12:31:01 +01:00
gingerBill ae9d540c1c Correct naming in tests 2022-07-11 11:55:49 +01:00
gingerBill c90b7c38f1 Rename strings.Builder procedures to be consistent with the rest of the core library 2022-07-11 11:50:08 +01:00
gingerBill 9e376fbda7 Update README.md 2022-07-10 00:52:59 +01:00
Wes Hardee 00739bf06d Merge branch 'odin-lang:master' into master 2022-07-09 18:09:21 -05:00
gingerBill e8148055ad Fix compilation on non-windows platforms 2022-07-09 23:55:02 +01:00
gingerBill dd0a20ab45 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-07-09 23:53:24 +01:00
gingerBill babbc304b8 Fix wasm compilation in windows 2022-07-09 23:53:18 +01:00
Mohamed Akram a8b44f33bd Allow passing config options to build script 2022-07-08 16:14:54 +04:00
gingerBill bd48561688 Merge pull request #1865 from thePHTest/ogl_bindless
Add OpenGL bindless textures ARB api to vendor
2022-07-05 20:03:15 +01:00
Wes Hardee 23842a8950 fix -build-mode:shared on MacOS 2022-06-30 12:40:32 -05:00
Phil 0a8e6169d7 remove unneeded semicolons 2022-06-28 11:36:50 -07:00
Phil b89bb87759 Add OpenGL bindless textures ARB api to vendor 2022-06-27 14:50:24 -07:00
Ronald1985 89222a0ab2 Added missing #includes on OpenBSD 2022-06-14 09:55:06 +01:00
phillvancejr a315e7c962 Reverted experimental changes that were meant for a branch, in sync with master 2022-02-04 13:45:36 -05:00
phillvancejr 42364f2fce sync with main 2022-02-04 13:16:40 -05:00
phillvancejr 8f600798ef stb_image 2022-02-04 13:03:20 -05:00
phillvancejr f28c268d97 move libgflw3.a to lib/darwin 2022-01-24 10:03:38 -05:00
phillvancejr f1cff20249 moved mac os glfw static lib to lib/darwin subdirectory 2022-01-24 10:02:56 -05:00
90 changed files with 1387 additions and 896 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
name: CI
on: [push, pull_request]
on: [push, pull_request, workflow_dispatch]
jobs:
build_linux:
+43
View File
@@ -0,0 +1,43 @@
name: "Close Stale Issues & PRs"
on:
workflow_dispatch:
schedule:
- cron: "0 21 * * *"
permissions:
issues: write
pull-requests: write
jobs:
stale:
runs-on: ubuntu-latest
steps:
- name: Close Stale Issues
uses: actions/stale@v4.1.0
with:
# stale-issue-message: |
# Hello!
#
# I am marking this issue as stale as it has not received any engagement from the community or maintainers 120 days. That does not imply that the issue has no merit! If you feel strongly about this issue
# - open a PR referencing and resolving the issue;
# - leave a comment on it and discuss ideas how you could contribute towards resolving it;
# - leave a comment and describe in detail why this issue is critical for your use case;
# - open a new issue with updated details and a plan on resolving the issue.
#
# The motivation for this automation is to help prioritize issues in the backlog and not ignore, reject, or belittle anyone..
#
# stale-pr-message: |
# Hello!
#
# I am marking this PR as stale as it has not received any engagement from the community or maintainers 120 days. That does not imply that the issue has no merit! If you feel strongly about this issue
# - leave a comment on it and discuss ideas how you could contribute towards resolving it;
# - leave a comment and describe in detail why this issue is critical for your use case;
#
# The motivation for this automation is to help prioritize issues in the backlog and not ignore, reject, or belittle anyone..
days-before-stale: 120
days-before-close: 30
exempt-draft-pr: true
ascending: true
operations-per-run: 1000
exempt-issue-labels: "ignore"
+1 -1
View File
@@ -58,7 +58,7 @@ set libs= ^
set linker_flags= -incremental:no -opt:ref -subsystem:console
if %release_mode% EQU 0 ( rem Debug
set linker_flags=%linker_flags% -debug
set linker_flags=%linker_flags% -debug /NATVIS:src\odin_compiler.natvis
) else ( rem Release
set linker_flags=%linker_flags% -debug
)
+34 -22
View File
@@ -1,12 +1,20 @@
#!/bin/bash
#!/usr/bin/env bash
set -eu
GIT_SHA=$(git rev-parse --short HEAD)
: ${CXX=clang++}
: ${CPPFLAGS=}
: ${CXXFLAGS=}
: ${LDFLAGS=}
: ${ODIN_VERSION=dev-$(date +"%Y-%m")}
CPPFLAGS="$CPPFLAGS -DODIN_VERSION_RAW=\"$ODIN_VERSION\""
CXXFLAGS="$CXXFLAGS -std=c++14"
LDFLAGS="$LDFLAGS -pthread -lm -lstdc++"
GIT_SHA=$(git rev-parse --short HEAD || :)
if [ "$GIT_SHA" ]; then CPPFLAGS="$CPPFLAGS -DGIT_SHA=\"$GIT_SHA\""; fi
DISABLED_WARNINGS="-Wno-switch -Wno-macro-redefined -Wno-unused-value"
LDFLAGS="-pthread -lm -lstdc++"
CFLAGS="-std=c++14 -DGIT_SHA=\"$GIT_SHA\""
CFLAGS="$CFLAGS -DODIN_VERSION_RAW=\"dev-$(date +"%Y-%m")\""
CC=clang
OS=$(uname)
panic() {
@@ -18,7 +26,7 @@ version() { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }';
config_darwin() {
ARCH=$(uname -m)
LLVM_CONFIG=llvm-config
: ${LLVM_CONFIG=llvm-config}
# allow for arm only llvm's with version 13
if [ ARCH == arm64 ]; then
@@ -37,34 +45,38 @@ config_darwin() {
fi
LDFLAGS="$LDFLAGS -liconv -ldl"
CFLAGS="$CFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
LDFLAGS="$LDFLAGS -lLLVM-C"
}
config_freebsd() {
LLVM_CONFIG=/usr/local/bin/llvm-config11
: ${LLVM_CONFIG=/usr/local/bin/llvm-config11}
CFLAGS="$CFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)"
}
config_openbsd() {
LLVM_CONFIG=/usr/local/bin/llvm-config
: ${LLVM_CONFIG=/usr/local/bin/llvm-config}
LDFLAGS="$LDFLAGS -liconv"
CFLAGS="$CFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)"
}
config_linux() {
if which llvm-config > /dev/null 2>&1; then
LLVM_CONFIG=llvm-config
elif which llvm-config-11 > /dev/null 2>&1; then
LLVM_CONFIG=llvm-config-11
elif which llvm-config-11-64 > /dev/null 2>&1; then
LLVM_CONFIG=llvm-config-11-64
else
panic "Unable to find LLVM-config"
: ${LLVM_CONFIG=}
if [ ! "$LLVM_CONFIG" ]; then
if which llvm-config > /dev/null 2>&1; then
LLVM_CONFIG=llvm-config
elif which llvm-config-11 > /dev/null 2>&1; then
LLVM_CONFIG=llvm-config-11
elif which llvm-config-11-64 > /dev/null 2>&1; then
LLVM_CONFIG=llvm-config-11-64
else
panic "Unable to find LLVM-config"
fi
fi
MIN_LLVM_VERSION=("11.0.0")
@@ -74,7 +86,7 @@ config_linux() {
fi
LDFLAGS="$LDFLAGS -ldl"
CFLAGS="$CFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)"
}
@@ -97,7 +109,7 @@ build_odin() {
esac
set -x
$CC src/main.cpp src/libtommath.cpp $DISABLED_WARNINGS $CFLAGS $EXTRAFLAGS $LDFLAGS -o odin
$CXX src/main.cpp src/libtommath.cpp $DISABLED_WARNINGS $CPPFLAGS $CXXFLAGS $EXTRAFLAGS $LDFLAGS -o odin
set +x
}
+8
View File
@@ -161,6 +161,10 @@ buffer_write :: proc(b: ^Buffer, p: []byte) -> (n: int, err: io.Error) {
return copy(b.buf[m:], p), nil
}
buffer_write_ptr :: proc(b: ^Buffer, ptr: rawptr, size: int) -> (n: int, err: io.Error) {
return buffer_write(b, ([^]byte)(ptr)[:size])
}
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))
@@ -229,6 +233,10 @@ buffer_read :: proc(b: ^Buffer, p: []byte) -> (n: int, err: io.Error) {
return
}
buffer_read_ptr :: proc(b: ^Buffer, ptr: rawptr, size: int) -> (n: int, err: io.Error) {
return buffer_read(b, ([^]byte)(ptr)[:size])
}
buffer_read_at :: proc(b: ^Buffer, p: []byte, offset: int) -> (n: int, err: io.Error) {
b.last_read = .Invalid
+1 -1
View File
@@ -519,7 +519,7 @@ join_adjacent_string_literals :: proc(cpp: ^Preprocessor, initial_tok: ^Token) {
quote_string :: proc(s: string) -> []byte {
b := strings.make_builder(0, len(s)+2)
b := strings.builder_make(0, len(s)+2)
io.write_quoted_string(strings.to_writer(&b), s, '"')
return b.buf[:]
}
+1 -1
View File
@@ -196,7 +196,7 @@ foreign libc {
getc :: proc(stream: ^FILE) -> int ---
getchar :: proc() -> int ---
putc :: proc(c: int, stream: ^FILE) -> int ---
putchar :: proc() -> int ---
putchar :: proc(c: int) -> int ---
puts :: proc(s: cstring) -> int ---
ungetc :: proc(c: int, stream: ^FILE) -> int ---
fread :: proc(ptr: rawptr, size: size_t, nmemb: size_t, stream: ^FILE) -> size_t ---
+4 -4
View File
@@ -25,8 +25,8 @@ import "core:strings"
MAX_RUNE_CODEPOINT :: int(unicode.MAX_RUNE)
write_rune :: strings.write_rune_builder
write_string :: strings.write_string_builder
write_rune :: strings.write_rune
write_string :: strings.write_string
Error :: enum u8 {
None = 0,
@@ -94,8 +94,8 @@ decode_xml :: proc(input: string, options := XML_Decode_Options{}, allocator :=
l := len(input)
if l == 0 { return "", .None }
builder := strings.make_builder()
defer strings.destroy_builder(&builder)
builder := strings.builder_make()
defer strings.builder_destroy(&builder)
t := Tokenizer{src=input}
in_data := false
@@ -8,7 +8,7 @@ import "core:time"
doc_print :: proc(doc: ^xml.Document) {
buf: strings.Builder
defer strings.destroy_builder(&buf)
defer strings.builder_destroy(&buf)
w := strings.to_writer(&buf)
xml.print(w, doc)
+2 -2
View File
@@ -18,9 +18,9 @@ Marshal_Error :: union #shared_nil {
}
marshal :: proc(v: any, allocator := context.allocator) -> (data: []byte, err: Marshal_Error) {
b := strings.make_builder(allocator)
b := strings.builder_make(allocator)
defer if err != nil {
strings.destroy_builder(&b)
strings.builder_destroy(&b)
}
marshal_to_builder(&b, v) or_return
+2 -2
View File
@@ -325,7 +325,7 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm
UNSUPPORTED_TYPE := Unsupported_Type_Error{v.id, p.curr_token}
if end_token == .Close_Brace {
assert(expect_token(p, .Open_Brace) == nil)
unmarshal_expect_token(p, .Open_Brace)
}
v := v
@@ -473,7 +473,7 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm
}
if end_token == .Close_Brace {
assert(expect_token(p, .Close_Brace) == nil)
unmarshal_expect_token(p, .Close_Brace)
}
return
}
+1 -1
View File
@@ -84,7 +84,7 @@ example :: proc() {
doc_hash :: proc(doc: ^xml.Document, print := false) -> (crc32: u32) {
buf: strings.Builder
defer strings.destroy_builder(&buf)
defer strings.builder_destroy(&buf)
w := strings.to_writer(&buf)
xml.print(w, doc)
+8 -8
View File
@@ -77,7 +77,7 @@ register_user_formatter :: proc(id: typeid, formatter: User_Formatter) -> Regist
// They must be freed accordingly
aprint :: proc(args: ..any, sep := " ") -> string {
str: strings.Builder
strings.init_builder(&str)
strings.builder_init(&str)
sbprint(buf=&str, args=args, sep=sep)
return strings.to_string(str)
}
@@ -85,7 +85,7 @@ aprint :: proc(args: ..any, sep := " ") -> string {
// They must be freed accordingly
aprintln :: proc(args: ..any, sep := " ") -> string {
str: strings.Builder
strings.init_builder(&str)
strings.builder_init(&str)
sbprintln(buf=&str, args=args, sep=sep)
return strings.to_string(str)
}
@@ -93,7 +93,7 @@ aprintln :: proc(args: ..any, sep := " ") -> string {
// They must be freed accordingly
aprintf :: proc(fmt: string, args: ..any) -> string {
str: strings.Builder
strings.init_builder(&str)
strings.builder_init(&str)
sbprintf(&str, fmt, ..args)
return strings.to_string(str)
}
@@ -102,21 +102,21 @@ aprintf :: proc(fmt: string, args: ..any) -> string {
// tprint procedure return a string that was allocated with the current context's temporary allocator
tprint :: proc(args: ..any, sep := " ") -> string {
str: strings.Builder
strings.init_builder(&str, context.temp_allocator)
strings.builder_init(&str, context.temp_allocator)
sbprint(buf=&str, args=args, sep=sep)
return strings.to_string(str)
}
// tprintln procedure return a string that was allocated with the current context's temporary allocator
tprintln :: proc(args: ..any, sep := " ") -> string {
str: strings.Builder
strings.init_builder(&str, context.temp_allocator)
strings.builder_init(&str, context.temp_allocator)
sbprintln(buf=&str, args=args, sep=sep)
return strings.to_string(str)
}
// tprintf procedure return a string that was allocated with the current context's temporary allocator
tprintf :: proc(fmt: string, args: ..any) -> string {
str: strings.Builder
strings.init_builder(&str, context.temp_allocator)
strings.builder_init(&str, context.temp_allocator)
sbprintf(&str, fmt, ..args)
return strings.to_string(str)
}
@@ -776,7 +776,7 @@ fmt_rune :: proc(fi: ^Info, r: rune, verb: rune) {
case 'c', 'r', 'v':
io.write_rune(fi.writer, r, &fi.n)
case 'q':
fi.n += strings.write_quoted_rune(fi.writer, r)
fi.n += io.write_quoted_rune(fi.writer, r)
case:
fmt_int(fi, u64(r), false, 32, verb)
}
@@ -1014,7 +1014,7 @@ fmt_pointer :: proc(fi: ^Info, p: rawptr, verb: rune) {
u := u64(uintptr(p))
switch verb {
case 'p', 'v':
if !fi.hash || verb == 'v' {
if !fi.hash && verb == 'v' {
io.write_string(fi.writer, "0x", &fi.n)
}
_fmt_int(fi, u, 16, false, 8*size_of(rawptr), __DIGITS_UPPER)
+2 -2
View File
@@ -1,8 +1,8 @@
package hash
@(optimization_mode="speed")
crc64_ecma_182 :: proc(data: []byte, seed := u32(0)) -> u64 #no_bounds_check {
result := u64(seed)
crc64_ecma_182 :: proc(data: []byte, seed := u64(0)) -> (result: u64) #no_bounds_check {
result = seed
#no_bounds_check for b in data {
result = result<<8 ~ _crc64_table_ecma_182[((result>>56) ~ u64(b)) & 0xff]
}
+101 -95
View File
@@ -172,108 +172,114 @@ murmur32 :: proc(data: []byte, seed := u32(0)) -> u32 {
return h1
}
// See https://github.com/aappleby/smhasher/blob/master/src/MurmurHash2.cpp#L96
@(optimization_mode="speed")
murmur64 :: proc(data: []byte, seed := u64(0x9747b28c)) -> u64 {
when size_of(int) == 8 {
m :: 0xc6a4a7935bd1e995
r :: 47
murmur64a :: proc(data: []byte, seed := u64(0x9747b28c)) -> u64 {
m :: 0xc6a4a7935bd1e995
r :: 47
h: u64 = seed ~ (u64(len(data)) * m)
data64 := mem.slice_ptr(cast(^u64)raw_data(data), len(data)/size_of(u64))
h: u64 = seed ~ (u64(len(data)) * m)
data64 := mem.slice_data_cast([]u64, data)
for _, i in data64 {
k := data64[i]
for _, i in data64 {
k := data64[i]
k *= m
k ~= k>>r
k *= m
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 ~= k
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)
}
offset := len(data64) * size_of(u64)
switch len(data)&7 {
case 7: h ~= u64(data[offset + 6]) << 48; fallthrough
case 6: h ~= u64(data[offset + 5]) << 40; fallthrough
case 5: h ~= u64(data[offset + 4]) << 32; fallthrough
case 4: h ~= u64(data[offset + 3]) << 24; fallthrough
case 3: h ~= u64(data[offset + 2]) << 16; fallthrough
case 2: h ~= u64(data[offset + 1]) << 8; fallthrough
case 1:
h ~= u64(data[offset + 0])
h *= m
}
h ~= h>>r
h *= m
h ~= h>>r
return h
}
// See https://github.com/aappleby/smhasher/blob/master/src/MurmurHash2.cpp#L140
@(optimization_mode="speed")
murmur64b :: proc(data: []byte, seed := u64(0x9747b28c)) -> u64 {
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)
}
@(optimization_mode="speed")
+2 -2
View File
@@ -130,7 +130,7 @@ save_to_buffer :: proc(img: ^Image, custom_info: Info = {}, allocator := context
// we will write to a string builder
data: strings.Builder
strings.init_builder(&data)
strings.builder_init(&data)
// all PNM headers start with the format
fmt.sbprintf(&data, "%s\n", header.format)
@@ -409,7 +409,7 @@ _parse_header_pam :: proc(data: []byte, allocator := context.allocator) -> (head
// string buffer for the tupltype
tupltype: strings.Builder
strings.init_builder(&tupltype, context.temp_allocator); defer strings.destroy_builder(&tupltype)
strings.builder_init(&tupltype, context.temp_allocator); defer strings.builder_destroy(&tupltype)
fmt.sbprint(&tupltype, "")
// PAM uses actual lines, so we can iterate easily
+24
View File
@@ -247,6 +247,30 @@ write_quoted_string :: proc(w: Writer, str: string, quote: byte = '"', n_written
return
}
// writer append a quoted rune into the byte buffer, return the written size
write_quoted_rune :: proc(w: Writer, r: rune) -> (n: int) {
_write_byte :: #force_inline proc(w: Writer, c: byte) -> int {
err := write_byte(w, c)
return 1 if err == nil else 0
}
quote := byte('\'')
n += _write_byte(w, quote)
buf, width := utf8.encode_rune(r)
if width == 1 && r == utf8.RUNE_ERROR {
n += _write_byte(w, '\\')
n += _write_byte(w, 'x')
n += _write_byte(w, DIGITS_LOWER[buf[0]>>4])
n += _write_byte(w, DIGITS_LOWER[buf[0]&0xf])
} else {
i, _ := write_escaped_rune(w, r, quote)
n += i
}
n += _write_byte(w, quote)
return
}
Tee_Reader :: struct {
+3 -3
View File
@@ -476,21 +476,21 @@ quaternion_angle_axis :: proc{
angle_from_quaternion_f16 :: proc(q: Quaternionf16) -> f16 {
if abs(q.w) > math.SQRT_THREE*0.5 {
return math.asin(q.x*q.x + q.y*q.y + q.z*q.z) * 2
return math.asin(math.sqrt(q.x*q.x + q.y*q.y + q.z*q.z)) * 2
}
return math.acos(q.w) * 2
}
angle_from_quaternion_f32 :: proc(q: Quaternionf32) -> f32 {
if abs(q.w) > math.SQRT_THREE*0.5 {
return math.asin(q.x*q.x + q.y*q.y + q.z*q.z) * 2
return math.asin(math.sqrt(q.x*q.x + q.y*q.y + q.z*q.z)) * 2
}
return math.acos(q.w) * 2
}
angle_from_quaternion_f64 :: proc(q: Quaternionf64) -> f64 {
if abs(q.w) > math.SQRT_THREE*0.5 {
return math.asin(q.x*q.x + q.y*q.y + q.z*q.z) * 2
return math.asin(math.sqrt(q.x*q.x + q.y*q.y + q.z*q.z)) * 2
}
return math.acos(q.w) * 2
+1 -1
View File
@@ -1357,7 +1357,7 @@ atan :: proc "contextless" (x: $T) -> T where intrinsics.type_is_float(T) {
}
asin :: proc "contextless" (x: $T) -> T where intrinsics.type_is_float(T) {
return atan2(x, 1 + sqrt(1 - x*x))
return atan2(x, sqrt(1 - x*x))
}
acos :: proc "contextless" (x: $T) -> T where intrinsics.type_is_float(T) {
+148
View File
@@ -0,0 +1,148 @@
//+build darwin
//+private
package mem_virtual
foreign import libc "System.framework"
import "core:c"
PROT_NONE :: 0x0 /* [MC2] no permissions */
PROT_READ :: 0x1 /* [MC2] pages can be read */
PROT_WRITE :: 0x2 /* [MC2] pages can be written */
PROT_EXEC :: 0x4 /* [MC2] pages can be executed */
// Sharing options
MAP_SHARED :: 0x1 /* [MF|SHM] share changes */
MAP_PRIVATE :: 0x2 /* [MF|SHM] changes are private */
// Other flags
MAP_FIXED :: 0x0010 /* [MF|SHM] interpret addr exactly */
MAP_RENAME :: 0x0020 /* Sun: rename private pages to file */
MAP_NORESERVE :: 0x0040 /* Sun: don't reserve needed swap area */
MAP_RESERVED0080 :: 0x0080 /* previously unimplemented MAP_INHERIT */
MAP_NOEXTEND :: 0x0100 /* for MAP_FILE, don't change file size */
MAP_HASSEMAPHORE :: 0x0200 /* region may contain semaphores */
MAP_NOCACHE :: 0x0400 /* don't cache pages for this mapping */
MAP_JIT :: 0x0800 /* Allocate a region that will be used for JIT purposes */
// Mapping type
MAP_FILE :: 0x0000 /* map from file (default) */
MAP_ANONYMOUS :: 0x1000 /* allocated from memory, swap space */
/*
* The MAP_RESILIENT_* flags can be used when the caller wants to map some
* possibly unreliable memory and be able to access it safely, possibly
* getting the wrong contents rather than raising any exception.
* For safety reasons, such mappings have to be read-only (PROT_READ access
* only).
*
* MAP_RESILIENT_CODESIGN:
* accessing this mapping will not generate code-signing violations,
* even if the contents are tainted.
* MAP_RESILIENT_MEDIA:
* accessing this mapping will not generate an exception if the contents
* are not available (unreachable removable or remote media, access beyond
* end-of-file, ...). Missing contents will be replaced with zeroes.
*/
MAP_RESILIENT_CODESIGN :: 0x2000 /* no code-signing failures */
MAP_RESILIENT_MEDIA :: 0x4000 /* no backing-store failures */
MAP_32BIT :: 0x8000 /* Return virtual addresses <4G only */
// Flags used to support translated processes.
MAP_TRANSLATED_ALLOW_EXECUTE :: 0x20000 /* allow execute in translated processes */
MAP_UNIX03 :: 0x40000 /* UNIX03 compliance */
// Process memory locking
MCL_CURRENT :: 0x0001 /* [ML] Lock only current memory */
MCL_FUTURE :: 0x0002 /* [ML] Lock all future memory as well */
MADV_NORMAL :: 0 /* [MC1] no further special treatment */
MADV_RANDOM :: 1 /* [MC1] expect random page refs */
MADV_SEQUENTIAL :: 2 /* [MC1] expect sequential page refs */
MADV_WILLNEED :: 3 /* [MC1] will need these pages */
MADV_DONTNEED :: 4 /* [MC1] dont need these pages */
MADV_FREE :: 5 /* pages unneeded, discard contents */
MADV_ZERO_WIRED_PAGES :: 6 /* zero the wired pages that have not been unwired before the entry is deleted */
MADV_FREE_REUSABLE :: 7 /* pages can be reused (by anyone) */
MADV_FREE_REUSE :: 8 /* caller wants to reuse those pages */
MADV_CAN_REUSE :: 9
MADV_PAGEOUT :: 10 /* page out now (internal only) */
// msync() flags
MS_ASYNC :: 0x0001 /* [MF|SIO] return immediately */
MS_INVALIDATE :: 0x0002 /* [MF|SIO] invalidate all cached data */
MS_SYNC :: 0x0010 /* [MF|SIO] msync synchronously */
MS_KILLPAGES :: 0x0004 /* invalidate pages, leave mapped */
MS_DEACTIVATE :: 0x0008 /* deactivate pages, leave mapped */
// Return bits from mincore
MINCORE_INCORE :: 0x1 /* Page is incore */
MINCORE_REFERENCED :: 0x2 /* Page has been referenced by us */
MINCORE_MODIFIED :: 0x4 /* Page has been modified by us */
MINCORE_REFERENCED_OTHER :: 0x8 /* Page has been referenced */
MINCORE_MODIFIED_OTHER :: 0x10 /* Page has been modified */
MINCORE_PAGED_OUT :: 0x20 /* Page has been paged out */
MINCORE_COPIED :: 0x40 /* Page has been copied */
MINCORE_ANONYMOUS :: 0x80 /* Page belongs to an anonymous object */
// Allocation failure result
MAP_FAILED : rawptr = rawptr(~uintptr(0))
foreign libc {
@(link_name="mlockall") _mlockall :: proc(flags: c.int) -> c.int ---
@(link_name="munlockall") _munlockall :: proc() -> c.int ---
@(link_name="mlock") _mlock :: proc(addr: rawptr, len: c.size_t) -> c.int ---
@(link_name="mmap") _mmap :: proc(addr: rawptr, len: c.size_t, prot: c.int, flags: c.int, fd: c.int, offset: int) -> rawptr ---
@(link_name="mprotect") _mprotect :: proc(addr: rawptr, len: c.size_t, prot: c.int) -> c.int ---
@(link_name="msync") _msync :: proc(addr: rawptr, len: c.size_t) -> c.int ---
@(link_name="munlock") _munlock :: proc(addr: rawptr, len: c.size_t) -> c.int ---
@(link_name="munmap") _munmap :: proc(addr: rawptr, len: c.size_t) -> c.int ---
@(link_name="shm_open") _shm_open :: proc(name: cstring, oflag: c.int, #c_vararg args: ..any) -> c.int ---
@(link_name="shm_unlink") _shm_unlink :: proc(name: cstring) -> c.int ---
@(link_name="posix_madvise") _posix_madvise :: proc(addr: rawptr, len: c.size_t, advice: c.int) -> c.int ---
@(link_name="madvise") _madvise :: proc(addr: rawptr, len: c.size_t, advice: c.int) -> c.int ---
@(link_name="mincore") _mincore :: proc(addr: rawptr, len: c.size_t, vec: cstring) -> c.int ---
@(link_name="minherit") _minherit :: proc(addr: rawptr, len: c.size_t, inherit: c.int) -> c.int ---
}
_reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) {
result := _mmap(nil, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
if result == MAP_FAILED {
return nil, .Out_Of_Memory
}
return ([^]byte)(uintptr(result))[:size], nil
}
_commit :: proc "contextless" (data: rawptr, size: uint) -> Allocator_Error {
result := _mprotect(data, size, PROT_READ|PROT_WRITE)
if result != 0 {
return .Out_Of_Memory
}
return nil
}
_decommit :: proc "contextless" (data: rawptr, size: uint) {
_mprotect(data, size, PROT_NONE)
_madvise(data, size, MADV_FREE)
}
_release :: proc "contextless" (data: rawptr, size: uint) {
_munmap(data, size)
}
_protect :: proc "contextless" (data: rawptr, size: uint, flags: Protect_Flags) -> bool {
pflags: c.int
pflags = PROT_NONE
if .Read in flags { pflags |= PROT_READ }
if .Write in flags { pflags |= PROT_WRITE }
if .Execute in flags { pflags |= PROT_EXEC }
err := _mprotect(data, size, pflags)
return err != 0
}
_platform_memory_init :: proc() {
DEFAULT_PAGE_SIZE = 4096
// is power of two
assert(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0)
}
+36 -1
View File
@@ -552,13 +552,20 @@ unparen_expr :: proc(expr: ^Expr) -> (val: ^Expr) {
return
}
Field_Flags :: distinct bit_set[Field_Flag]
Field_Flag :: enum {
Invalid,
Unknown,
Ellipsis,
Using,
No_Alias,
C_Vararg,
Auto_Cast,
Any_Int,
Subtype,
By_Ptr,
Results,
Tags,
@@ -566,11 +573,38 @@ Field_Flag :: enum {
Typeid_Token,
}
Field_Flags :: distinct bit_set[Field_Flag]
field_flag_strings := [Field_Flag]string{
.Invalid = "",
.Unknown = "",
.Ellipsis = "..",
.Using = "using",
.No_Alias = "#no_alias",
.C_Vararg = "#c_vararg",
.Auto_Cast = "auto_cast",
.Any_Int = "#any_int",
.Subtype = "#subtype",
.By_Ptr = "#by_ptr",
.Results = "results",
.Tags = "field tag",
.Default_Parameters = "default parameters",
.Typeid_Token = "typeid",
}
field_hash_flag_strings := []struct{key: string, flag: Field_Flag}{
{"no_alias", .No_Alias},
{"c_vararg", .C_Vararg},
{"any_int", .Any_Int},
{"subtype", .Subtype},
{"by_ptr", .By_Ptr},
}
Field_Flags_Struct :: Field_Flags{
.Using,
.Tags,
.Subtype,
}
Field_Flags_Record_Poly_Params :: Field_Flags{
.Typeid_Token,
@@ -583,6 +617,7 @@ Field_Flags_Signature :: Field_Flags{
.C_Vararg,
.Auto_Cast,
.Any_Int,
.By_Ptr,
.Default_Parameters,
}
+24 -71
View File
@@ -1611,20 +1611,6 @@ new_ast_field :: proc(names: []^ast.Expr, type: ^ast.Expr, default_value: ^ast.E
return field
}
Field_Prefix :: enum {
Invalid,
Unknown,
Using,
No_Alias,
C_Vararg,
Auto_Cast,
Any_Int,
}
Field_Prefixes :: distinct bit_set[Field_Prefix]
Expr_And_Flags :: struct {
expr: ^ast.Expr,
flags: ast.Field_Flags,
@@ -1666,7 +1652,7 @@ convert_to_ident_list :: proc(p: ^Parser, list: []Expr_And_Flags, ignore_flags,
return idents[:]
}
is_token_field_prefix :: proc(p: ^Parser) -> Field_Prefix {
is_token_field_prefix :: proc(p: ^Parser) -> ast.Field_Flag {
#partial switch p.curr_tok.kind {
case .EOF:
return .Invalid
@@ -1677,17 +1663,15 @@ is_token_field_prefix :: proc(p: ^Parser) -> Field_Prefix {
advance_token(p)
return .Auto_Cast
case .Hash:
tok: tokenizer.Token
advance_token(p)
defer advance_token(p)
#partial switch p.curr_tok.kind {
case .Ident:
switch p.curr_tok.text {
case "no_alias":
return .No_Alias
case "c_vararg":
return .C_Vararg
case "any_int":
return .Any_Int
tok = p.curr_tok
advance_token(p)
if tok.kind == .Ident {
for kf in ast.field_hash_flag_strings {
if kf.key == tok.text {
return kf.flag
}
}
}
return .Unknown
@@ -1695,8 +1679,8 @@ is_token_field_prefix :: proc(p: ^Parser) -> Field_Prefix {
return .Invalid
}
parse_field_prefixes :: proc(p: ^Parser) -> ast.Field_Flags {
counts: [len(Field_Prefix)]int
parse_field_prefixes :: proc(p: ^Parser) -> (flags: ast.Field_Flags) {
counts: [len(ast.Field_Flag)]int
for {
kind := is_token_field_prefix(p)
@@ -1712,31 +1696,17 @@ parse_field_prefixes :: proc(p: ^Parser) -> ast.Field_Flags {
counts[kind] += 1
}
flags: ast.Field_Flags
for kind in Field_Prefix {
for kind in ast.Field_Flag {
count := counts[kind]
switch kind {
case .Invalid, .Unknown: // Ignore
case .Using:
if count > 1 { error(p, p.curr_tok.pos, "multiple 'using' in this field list") }
if count > 0 { flags += {.Using} }
case .No_Alias:
if count > 1 { error(p, p.curr_tok.pos, "multiple '#no_alias' in this field list") }
if count > 0 { flags += {.No_Alias} }
case .C_Vararg:
if count > 1 { error(p, p.curr_tok.pos, "multiple '#c_vararg' in this field list") }
if count > 0 { flags += {.C_Vararg} }
case .Auto_Cast:
if count > 1 { error(p, p.curr_tok.pos, "multiple 'auto_cast' in this field list") }
if count > 0 { flags += {.Auto_Cast} }
case .Any_Int:
if count > 1 { error(p, p.curr_tok.pos, "multiple '#any_int' in this field list") }
if count > 0 { flags += {.Any_Int} }
if kind == .Invalid || kind == .Unknown {
// Ignore
} else {
if count > 1 { error(p, p.curr_tok.pos, "multiple '%s' in this field list", ast.field_flag_strings[kind]) }
if count > 0 { flags += {kind} }
}
}
return flags
return
}
check_field_flag_prefixes :: proc(p: ^Parser, name_count: int, allowed_flags, set_flags: ast.Field_Flags) -> (flags: ast.Field_Flags) {
@@ -1748,19 +1718,13 @@ check_field_flag_prefixes :: proc(p: ^Parser, name_count: int, allowed_flags, se
for flag in ast.Field_Flag {
if flag not_in allowed_flags && flag in flags {
switch flag {
case .Using:
error(p, p.curr_tok.pos, "'using' is not allowed within this field list")
case .No_Alias:
error(p, p.curr_tok.pos, "'#no_alias' is not allowed within this field list")
case .C_Vararg:
error(p, p.curr_tok.pos, "'#c_vararg' is not allowed within this field list")
case .Auto_Cast:
error(p, p.curr_tok.pos, "'auto_cast' is not allowed within this field list")
case .Any_Int:
error(p, p.curr_tok.pos, "'#any_int' is not allowed within this field list")
#partial switch flag {
case .Unknown, .Invalid:
// ignore
case .Tags, .Ellipsis, .Results, .Default_Parameters, .Typeid_Token:
panic("Impossible prefixes")
case:
error(p, p.curr_tok.pos, "'%s' is not allowed within this field list", ast.field_flag_strings[flag])
}
flags -= {flag}
}
@@ -2631,7 +2595,6 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
tok := expect_token(p, .Union)
poly_params: ^ast.Field_List
align: ^ast.Expr
is_maybe: bool
is_no_nil: bool
is_shared_nil: bool
@@ -2656,10 +2619,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
}
align = parse_expr(p, true)
case "maybe":
if is_maybe {
error(p, tag.pos, "duplicate union tag '#%s'", tag.text)
}
is_maybe = true
error(p, tag.pos, "#%s functionality has now been merged with standard 'union' functionality", tag.text)
case "no_nil":
if is_no_nil {
error(p, tag.pos, "duplicate union tag '#%s'", tag.text)
@@ -2676,19 +2636,12 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
}
p.expr_level = prev_level
if is_no_nil && is_maybe {
error(p, p.curr_tok.pos, "#maybe and #no_nil cannot be applied together")
}
if is_no_nil && is_shared_nil {
error(p, p.curr_tok.pos, "#shared_nil and #no_nil cannot be applied together")
}
if is_shared_nil && is_maybe {
error(p, p.curr_tok.pos, "#maybe and #shared_nil cannot be applied together")
}
union_kind := ast.Union_Type_Kind.Normal
switch {
case is_maybe: union_kind = .maybe
case is_no_nil: union_kind = .no_nil
case is_shared_nil: union_kind = .shared_nil
}
+1 -1
View File
@@ -151,7 +151,7 @@ print :: proc(p: ^Printer, file: ^ast.File) -> string {
fix_lines(p)
builder := strings.make_builder(0, 5 * mem.Megabyte, p.allocator)
builder := strings.builder_make(0, 5 * mem.Megabyte, p.allocator)
last_line := 0
+3 -3
View File
@@ -71,7 +71,7 @@ push_comment :: proc(p: ^Printer, comment: tokenizer.Token) -> int {
return 0
} else {
builder := strings.make_builder(context.temp_allocator)
builder := strings.builder_make(context.temp_allocator)
c_len := len(comment.text)
trim_space := true
@@ -90,12 +90,12 @@ push_comment :: proc(p: ^Printer, comment: tokenizer.Token) -> int {
continue
case c == '\r' && comment.text[min(c_len - 1, i + 1)] == '\n':
append(&multilines, strings.to_string(builder))
builder = strings.make_builder(context.temp_allocator)
builder = strings.builder_make(context.temp_allocator)
trim_space = true
i += 1
case c == '\n':
append(&multilines, strings.to_string(builder))
builder = strings.make_builder(context.temp_allocator)
builder = strings.builder_make(context.temp_allocator)
trim_space = true
case c == '/' && comment.text[min(c_len - 1, i + 1)] == '*':
strings.write_string(&builder, "/*")
+5 -3
View File
@@ -1,6 +1,5 @@
package os
import "core:strings"
import "core:mem"
read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Errno) {
@@ -51,10 +50,13 @@ read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []F
continue
}
fullpath := strings.join( []string{ dirpath, filename }, "/", context.temp_allocator)
fullpath := make([]byte, len(dirpath)+1+len(filename))
copy(fullpath, dirpath)
copy(fullpath[len(dirpath):], "/")
copy(fullpath[len(dirpath)+1:], filename)
defer delete(fullpath, context.temp_allocator)
fi_, err = stat(fullpath, allocator)
fi_, err = stat(string(fullpath), allocator)
if err != ERROR_NONE {
for fi__ in dfi {
file_info_delete(fi__, allocator)
+16 -16
View File
@@ -11,24 +11,24 @@ lookup_env :: proc(key: string, allocator := context.allocator) -> (value: strin
return
}
wkey := win32.utf8_to_wstring(key)
b := make([dynamic]u16, 100, context.temp_allocator)
for {
n := win32.GetEnvironmentVariableW(wkey, raw_data(b), u32(len(b)))
if n == 0 {
err := win32.GetLastError()
if err == u32(ERROR_ENVVAR_NOT_FOUND) {
return "", false
}
n := win32.GetEnvironmentVariableW(wkey, nil, 0)
if n == 0 {
err := win32.GetLastError()
if err == u32(ERROR_ENVVAR_NOT_FOUND) {
return "", false
}
if n <= u32(len(b)) {
value, _ = win32.utf16_to_utf8(b[:n], allocator)
found = true
return
}
resize(&b, len(b)*2)
}
b := make([dynamic]u16, n, context.temp_allocator)
n = win32.GetEnvironmentVariableW(wkey, raw_data(b), u32(len(b)))
if n == 0 {
err := win32.GetLastError()
if err == u32(ERROR_ENVVAR_NOT_FOUND) {
return "", false
}
}
value, _ = win32.utf16_to_utf8(b[:n], allocator)
found = true
return
}
+8 -8
View File
@@ -241,13 +241,13 @@ S_ISGID :: 0o2000 // Set group id on execution
S_ISVTX :: 0o1000 // Directory restrcted delete
S_ISLNK :: #force_inline proc(m: mode_t) -> bool do return (m & S_IFMT) == S_IFLNK
S_ISREG :: #force_inline proc(m: mode_t) -> bool do return (m & S_IFMT) == S_IFREG
S_ISDIR :: #force_inline proc(m: mode_t) -> bool do return (m & S_IFMT) == S_IFDIR
S_ISCHR :: #force_inline proc(m: mode_t) -> bool do return (m & S_IFMT) == S_IFCHR
S_ISBLK :: #force_inline proc(m: mode_t) -> bool do return (m & S_IFMT) == S_IFBLK
S_ISFIFO :: #force_inline proc(m: mode_t) -> bool do return (m & S_IFMT) == S_IFIFO
S_ISSOCK :: #force_inline proc(m: mode_t) -> bool do return (m & S_IFMT) == S_IFSOCK
S_ISLNK :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFLNK }
S_ISREG :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFREG }
S_ISDIR :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFDIR }
S_ISCHR :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFCHR }
S_ISBLK :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFBLK }
S_ISFIFO :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFIFO }
S_ISSOCK :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFSOCK }
F_OK :: 0 // Test for file existance
X_OK :: 1 // Test for execute permission
@@ -257,7 +257,7 @@ R_OK :: 4 // Test for read permission
foreign libc {
@(link_name="__error") __errno_location :: proc() -> ^int ---
@(link_name="open") _unix_open :: proc(path: cstring, flags: c.int, mode: c.int) -> Handle ---
@(link_name="open") _unix_open :: proc(path: cstring, flags: c.int, mode: c.int) -> Handle ---
@(link_name="close") _unix_close :: proc(fd: Handle) -> c.int ---
@(link_name="read") _unix_read :: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t ---
@(link_name="write") _unix_write :: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t ---
+1 -1
View File
@@ -271,7 +271,7 @@ _glob :: proc(dir, pattern: string, matches: ^[dynamic]string, allocator := cont
}
d, derr := os.open(dir)
d, derr := os.open(dir, os.O_RDONLY)
if derr != 0 {
return
}
+1 -1
View File
@@ -146,7 +146,7 @@ clean :: proc(path: string, allocator := context.allocator) -> string {
}
// join joins numerous path elements into a single path
join :: proc(elems: ..string, allocator := context.allocator) -> string {
join :: proc(elems: []string, allocator := context.allocator) -> string {
context.allocator = allocator
for elem, i in elems {
if elem != "" {
+2 -2
View File
@@ -573,11 +573,11 @@ write_type_writer :: proc(w: io.Writer, ti: ^Type_Info, n_written: ^int = nil) -
write_type(w, info.elem, &n) or_return
case is_rune(info.elem):
io.write_encoded_rune(w, rune(info.lower), true, &n) or_return
io.write_string(w, "..", &n) or_return
io.write_string(w, "..=", &n) or_return
io.write_encoded_rune(w, rune(info.upper), true, &n) or_return
case:
io.write_i64(w, info.lower, 10, &n) or_return
io.write_string(w, "..", &n) or_return
io.write_string(w, "..=", &n) or_return
io.write_i64(w, info.upper, 10, &n) or_return
}
if info.underlying != nil {
+79 -29
View File
@@ -339,19 +339,22 @@ append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) {
if array == nil {
return
}
if cap(array) < len(array)+1 {
cap := 2 * cap(array) + max(8, 1)
_ = reserve(array, cap, loc)
}
if cap(array)-len(array) > 0 {
a := (^Raw_Dynamic_Array)(array)
when size_of(E) != 0 {
data := ([^]E)(a.data)
assert(condition=data != nil, loc=loc)
data[a.len] = arg
}
when size_of(E) == 0 {
a.len += 1
} else {
if cap(array) < len(array)+1 {
cap := 2 * cap(array) + max(8, 1)
_ = reserve(array, cap, loc)
}
if cap(array)-len(array) > 0 {
a := (^Raw_Dynamic_Array)(array)
when size_of(E) != 0 {
data := ([^]E)(a.data)
assert(condition=data != nil, loc=loc)
data[a.len] = arg
}
a.len += 1
}
}
}
@@ -366,20 +369,23 @@ append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location)
return
}
if cap(array) < len(array)+arg_len {
cap := 2 * cap(array) + max(8, arg_len)
_ = reserve(array, cap, loc)
}
arg_len = min(cap(array)-len(array), arg_len)
if arg_len > 0 {
a := (^Raw_Dynamic_Array)(array)
when size_of(E) != 0 {
data := ([^]E)(a.data)
assert(condition=data != nil, loc=loc)
intrinsics.mem_copy(&data[a.len], raw_data(args), size_of(E) * arg_len)
}
when size_of(E) == 0 {
a.len += arg_len
} else {
if cap(array) < len(array)+arg_len {
cap := 2 * cap(array) + max(8, arg_len)
_ = reserve(array, cap, loc)
}
arg_len = min(cap(array)-len(array), arg_len)
if arg_len > 0 {
a := (^Raw_Dynamic_Array)(array)
when size_of(E) != 0 {
data := ([^]E)(a.data)
assert(condition=data != nil, loc=loc)
intrinsics.mem_copy(&data[a.len], raw_data(args), size_of(E) * arg_len)
}
a.len += arg_len
}
}
}
@@ -413,7 +419,7 @@ append_nothing :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) {
@builtin
insert_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, arg: E, loc := #caller_location) -> (ok: bool) #no_bounds_check {
inject_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, arg: E, loc := #caller_location) -> (ok: bool) #no_bounds_check {
if array == nil {
return
}
@@ -432,7 +438,7 @@ insert_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, arg: E, loc := #calle
}
@builtin
insert_at_elems :: proc(array: ^$T/[dynamic]$E, index: int, args: ..E, loc := #caller_location) -> (ok: bool) #no_bounds_check {
inject_at_elems :: proc(array: ^$T/[dynamic]$E, index: int, args: ..E, loc := #caller_location) -> (ok: bool) #no_bounds_check {
if array == nil {
return
}
@@ -456,7 +462,7 @@ insert_at_elems :: proc(array: ^$T/[dynamic]$E, index: int, args: ..E, loc := #c
}
@builtin
insert_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, index: int, arg: string, loc := #caller_location) -> (ok: bool) #no_bounds_check {
inject_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, index: int, arg: string, loc := #caller_location) -> (ok: bool) #no_bounds_check {
if array == nil {
return
}
@@ -477,7 +483,51 @@ insert_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, index: int, arg: string
return
}
@builtin insert_at :: proc{insert_at_elem, insert_at_elems, insert_at_elem_string}
@builtin inject_at :: proc{inject_at_elem, inject_at_elems, inject_at_elem_string}
@builtin
assign_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, arg: E, loc := #caller_location) -> (ok: bool) #no_bounds_check {
if index < len(array) {
array[index] = arg
ok = true
} else if resize(array, index+1, loc) {
array[index] = arg
ok = true
}
return
}
@builtin
assign_at_elems :: proc(array: ^$T/[dynamic]$E, index: int, args: ..E, loc := #caller_location) -> (ok: bool) #no_bounds_check {
if index+len(args) < len(array) {
copy(array[index:], args)
ok = true
} else if resize(array, index+1+len(args), loc) {
copy(array[index:], args)
ok = true
}
return
}
@builtin
assign_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, index: int, arg: string, loc := #caller_location) -> (ok: bool) #no_bounds_check {
if len(args) == 0 {
ok = true
} else if index+len(args) < len(array) {
copy(array[index:], args)
ok = true
} else if resize(array, index+1+len(args), loc) {
copy(array[index:], args)
ok = true
}
return
}
@builtin assign_at :: proc{assign_at_elem, assign_at_elems, assign_at_elem_string}
+43 -105
View File
@@ -17,50 +17,53 @@ Builder :: struct {
}
// return a builder, default length 0 / cap 16 are done through make
make_builder_none :: proc(allocator := context.allocator) -> Builder {
builder_make_none :: proc(allocator := context.allocator) -> Builder {
return Builder{buf=make([dynamic]byte, allocator)}
}
// return a builder, with a set length `len` and cap 16 byte buffer
make_builder_len :: proc(len: int, allocator := context.allocator) -> Builder {
builder_make_len :: proc(len: int, allocator := context.allocator) -> Builder {
return Builder{buf=make([dynamic]byte, len, allocator)}
}
// return a builder, with a set length `len` byte buffer and a custom `cap`
make_builder_len_cap :: proc(len, cap: int, allocator := context.allocator) -> Builder {
builder_make_len_cap :: proc(len, cap: int, allocator := context.allocator) -> Builder {
return Builder{buf=make([dynamic]byte, len, cap, allocator)}
}
// overload simple `make_builder_*` with or without len / cap parameters
make_builder :: proc{
make_builder_none,
make_builder_len,
make_builder_len_cap,
// overload simple `builder_make_*` with or without len / cap parameters
builder_make :: proc{
builder_make_none,
builder_make_len,
builder_make_len_cap,
}
// initialize a builder, default length 0 / cap 16 are done through make
// replaces the existing `buf`
init_builder_none :: proc(b: ^Builder, allocator := context.allocator) {
builder_init_none :: proc(b: ^Builder, allocator := context.allocator) -> ^Builder {
b.buf = make([dynamic]byte, allocator)
return b
}
// initialize a builder, with a set length `len` and cap 16 byte buffer
// replaces the existing `buf`
init_builder_len :: proc(b: ^Builder, len: int, allocator := context.allocator) {
builder_init_len :: proc(b: ^Builder, len: int, allocator := context.allocator) -> ^Builder {
b.buf = make([dynamic]byte, len, allocator)
return b
}
// initialize a builder, with a set length `len` byte buffer and a custom `cap`
// replaces the existing `buf`
init_builder_len_cap :: proc(b: ^Builder, len, cap: int, allocator := context.allocator) {
builder_init_len_cap :: proc(b: ^Builder, len, cap: int, allocator := context.allocator) -> ^Builder {
b.buf = make([dynamic]byte, len, cap, allocator)
return b
}
// overload simple `init_builder_*` with or without len / ap parameters
init_builder :: proc{
init_builder_none,
init_builder_len,
init_builder_len_cap,
// overload simple `builder_init_*` with or without len / ap parameters
builder_init :: proc{
builder_init_none,
builder_init_len,
builder_init_len_cap,
}
@(private)
@@ -103,18 +106,18 @@ to_writer :: proc(b: ^Builder) -> io.Writer {
}
// delete and clear the builder byte buffer content
destroy_builder :: proc(b: ^Builder) {
builder_destroy :: proc(b: ^Builder) {
delete(b.buf)
clear(&b.buf)
}
// reserve the builfer byte buffer to a specific cap, when it's higher than before
grow_builder :: proc(b: ^Builder, cap: int) {
builder_grow :: proc(b: ^Builder, cap: int) {
reserve(&b.buf, cap)
}
// clear the builder byte buffer content
reset_builder :: proc(b: ^Builder) {
builder_reset :: proc(b: ^Builder) {
clear(&b.buf)
}
@@ -165,7 +168,7 @@ builder_space :: proc(b: Builder) -> int {
/*
appends a byte to the builder, returns the append diff
builder := strings.make_builder()
builder := strings.builder_make()
strings.write_byte(&builder, 'a') // 1
strings.write_byte(&builder, 'b') // 1
strings.write_byte(&builder, 'c') // 1
@@ -181,7 +184,7 @@ write_byte :: proc(b: ^Builder, x: byte) -> (n: int) {
/*
appends a slice of bytes to the builder, returns the append diff
builder := strings.make_builder()
builder := strings.builder_make()
bytes := [?]byte { 'a', 'b', 'c' }
strings.write_bytes(&builder, bytes[:]) // 3
fmt.println(strings.to_string(builder)) // -> abc
@@ -196,77 +199,46 @@ write_bytes :: proc(b: ^Builder, x: []byte) -> (n: int) {
/*
appends a single rune into the builder, returns written rune size and an `io.Error`
builder := strings.make_builder()
strings.write_rune_builder(&builder, 'ä') // 2 None
strings.write_rune_builder(&builder, 'b') // 1 None
strings.write_rune_builder(&builder, 'c') // 1 None
builder := strings.builder_make()
strings.write_rune(&builder, 'ä') // 2 None
strings.write_rune(&builder, 'b') // 1 None
strings.write_rune(&builder, 'c') // 1 None
fmt.println(strings.to_string(builder)) // -> äbc
*/
write_rune_builder :: proc(b: ^Builder, r: rune) -> (int, io.Error) {
write_rune :: proc(b: ^Builder, r: rune) -> (int, io.Error) {
return io.write_rune(to_writer(b), r)
}
/*
appends a quoted rune into the builder, returns written size
builder := strings.make_builder()
builder := strings.builder_make()
strings.write_string(&builder, "abc") // 3
strings.write_quoted_rune_builder(&builder, 'ä') // 4
strings.write_quoted_rune(&builder, 'ä') // 4
strings.write_string(&builder, "abc") // 3
fmt.println(strings.to_string(builder)) // -> abc'ä'abc
*/
write_quoted_rune_builder :: proc(b: ^Builder, r: rune) -> (n: int) {
return write_quoted_rune(to_writer(b), r)
write_quoted_rune :: proc(b: ^Builder, r: rune) -> (n: int) {
return io.write_quoted_rune(to_writer(b), r)
}
@(private)
_write_byte :: proc(w: io.Writer, c: byte) -> int {
err := io.write_byte(w, c)
return 1 if err == nil else 0
}
// writer append a quoted rune into the byte buffer, return the written size
write_quoted_rune :: proc(w: io.Writer, r: rune) -> (n: int) {
quote := byte('\'')
n += _write_byte(w, quote)
buf, width := utf8.encode_rune(r)
if width == 1 && r == utf8.RUNE_ERROR {
n += _write_byte(w, '\\')
n += _write_byte(w, 'x')
n += _write_byte(w, DIGITS_LOWER[buf[0]>>4])
n += _write_byte(w, DIGITS_LOWER[buf[0]&0xf])
} else {
i, _ := io.write_escaped_rune(w, r, quote)
n += i
}
n += _write_byte(w, quote)
return
}
// overload for `write_string_*` variants
write_string :: proc{
write_string_builder,
write_string_writer,
}
/*
appends a string to the builder, return the written byte size
builder := strings.make_builder()
builder := strings.builder_make()
strings.write_string(&builder, "a") // 1
strings.write_string(&builder, "bc") // 2
strings.write_string(&builder, "xyz") // 3
fmt.println(strings.to_string(builder)) // -> abcxyz
*/
write_string_builder :: proc(b: ^Builder, s: string) -> (n: int) {
return write_string_writer(to_writer(b), s)
write_string :: proc(b: ^Builder, s: string) -> (n: int) {
n0 := len(b.buf)
append(&b.buf, s)
n1 := len(b.buf)
return n1-n0
}
// appends a string to the writer
write_string_writer :: proc(w: io.Writer, s: string) -> (n: int) {
n, _ = io.write(w, transmute([]byte)s)
return
}
// pops and returns the last byte in the builder
// returns 0 when the builder is empty
@@ -297,70 +269,36 @@ pop_rune :: proc(b: ^Builder) -> (r: rune, width: int) {
@(private)
DIGITS_LOWER := "0123456789abcdefx"
// overload for `write_quoted_string_*` variants
write_quoted_string :: proc{
write_quoted_string_builder,
write_quoted_string_writer,
}
/*
append a quoted string into the builder, return the written byte size
builder := strings.make_builder()
builder := strings.builder_make()
strings.write_quoted_string(&builder, "a") // 3
strings.write_quoted_string(&builder, "bc", '\'') // 4
strings.write_quoted_string(&builder, "xyz") // 5
fmt.println(strings.to_string(builder)) // -> "a"'bc'xyz"
*/
write_quoted_string_builder :: proc(b: ^Builder, str: string, quote: byte = '"') -> (n: int) {
write_quoted_string :: proc(b: ^Builder, str: string, quote: byte = '"') -> (n: int) {
n, _ = io.write_quoted_string(to_writer(b), str, quote)
return
}
@(deprecated="prefer io.write_quoted_string")
write_quoted_string_writer :: proc(w: io.Writer, str: string, quote: byte = '"') -> (n: int) {
n, _ = io.write_quoted_string(w, str, quote)
return
}
// overload for `write_encoded_rune_*`
write_encoded_rune :: proc{
write_encoded_rune_builder,
write_encoded_rune_writer,
}
// appends a rune to the builder, optional `write_quote` boolean tag, returns the written rune size
write_encoded_rune_builder :: proc(b: ^Builder, r: rune, write_quote := true) -> (n: int) {
write_encoded_rune :: proc(b: ^Builder, r: rune, write_quote := true) -> (n: int) {
n, _ = io.write_encoded_rune(to_writer(b), r, write_quote)
return
}
@(deprecated="prefer io.write_encoded_rune")
write_encoded_rune_writer :: proc(w: io.Writer, r: rune, write_quote := true) -> (n: int) {
n, _ = io.write_encoded_rune(w, r, write_quote)
return
}
// overload for `write_escaped_rune_*`
write_escaped_rune :: proc{
write_escaped_rune_builder,
write_escaped_rune_writer,
}
// appends a rune to the builder, fully written out in case of escaped runes e.g. '\a' will be written as such
// when `r` and `quote` match and `quote` is `\\` - they will be written as two slashes
// `html_safe` flag in case the runes '<', '>', '&' should be encoded as digits e.g. `\u0026`
write_escaped_rune_builder :: proc(b: ^Builder, r: rune, quote: byte, html_safe := false) -> (n: int) {
write_escaped_rune :: proc(b: ^Builder, r: rune, quote: byte, html_safe := false) -> (n: int) {
n, _ = io.write_escaped_rune(to_writer(b), r, quote, html_safe)
return
}
@(deprecated="prefer io.write_escaped_rune")
write_escaped_rune_writer :: proc(w: io.Writer, r: rune, quote: byte, html_safe := false) -> (n: int) {
n, _ = io.write_escaped_rune(w, r, quote, html_safe)
return
}
// writes a u64 value `i` in `base` = 10 into the builder, returns the written amount of characters
write_u64 :: proc(b: ^Builder, i: u64, base: int = 10) -> (n: int) {
buf: [32]byte
+10 -10
View File
@@ -10,7 +10,7 @@ to_valid_utf8 :: proc(s, replacement: string, allocator := context.allocator) ->
}
b: Builder
init_builder(&b, 0, 0, allocator)
builder_init(&b, 0, 0, allocator)
s := s
for c, i in s {
@@ -20,7 +20,7 @@ to_valid_utf8 :: proc(s, replacement: string, allocator := context.allocator) ->
_, w := utf8.decode_rune_in_string(s[i:])
if w == 1 {
grow_builder(&b, len(s) + len(replacement))
builder_grow(&b, len(s) + len(replacement))
write_string(&b, s[:i])
s = s[i:]
break
@@ -67,9 +67,9 @@ to_valid_utf8 :: proc(s, replacement: string, allocator := context.allocator) ->
*/
to_lower :: proc(s: string, allocator := context.allocator) -> string {
b: Builder
init_builder(&b, 0, len(s), allocator)
builder_init(&b, 0, len(s), allocator)
for r in s {
write_rune_builder(&b, unicode.to_lower(r))
write_rune(&b, unicode.to_lower(r))
}
return to_string(b)
}
@@ -83,9 +83,9 @@ to_lower :: proc(s: string, allocator := context.allocator) -> string {
*/
to_upper :: proc(s: string, allocator := context.allocator) -> string {
b: Builder
init_builder(&b, 0, len(s), allocator)
builder_init(&b, 0, len(s), allocator)
for r in s {
write_rune_builder(&b, unicode.to_upper(r))
write_rune(&b, unicode.to_upper(r))
}
return to_string(b)
}
@@ -147,7 +147,7 @@ to_camel_case :: proc(s: string, allocator := context.allocator) -> string {
s := s
s = trim_space(s)
b: Builder
init_builder(&b, 0, len(s), allocator)
builder_init(&b, 0, len(s), allocator)
w := to_writer(&b)
string_case_iterator(w, s, proc(w: io.Writer, prev, curr, next: rune) {
@@ -172,7 +172,7 @@ to_pascal_case :: proc(s: string, allocator := context.allocator) -> string {
s := s
s = trim_space(s)
b: Builder
init_builder(&b, 0, len(s), allocator)
builder_init(&b, 0, len(s), allocator)
w := to_writer(&b)
string_case_iterator(w, s, proc(w: io.Writer, prev, curr, next: rune) {
@@ -203,7 +203,7 @@ to_delimiter_case :: proc(s: string, delimiter: rune, all_upper_case: bool, allo
s := s
s = trim_space(s)
b: Builder
init_builder(&b, 0, len(s), allocator)
builder_init(&b, 0, len(s), allocator)
w := to_writer(&b)
adjust_case := unicode.to_upper if all_upper_case else unicode.to_lower
@@ -272,7 +272,7 @@ to_ada_case :: proc(s: string, allocator := context.allocator) -> string {
s := s
s = trim_space(s)
b: Builder
init_builder(&b, 0, len(s), allocator)
builder_init(&b, 0, len(s), allocator)
w := to_writer(&b)
prev, curr: rune
+8 -8
View File
@@ -1553,7 +1553,7 @@ split_multi_iterate :: proc(using sm: ^Split_Multi) -> (res: string, ok: bool) #
scrub :: proc(s: string, replacement: string, allocator := context.allocator) -> string {
str := s
b: Builder
init_builder(&b, 0, len(s), allocator)
builder_init(&b, 0, len(s), allocator)
has_error := false
cursor := 0
@@ -1622,7 +1622,7 @@ expand_tabs :: proc(s: string, tab_size: int, allocator := context.allocator) ->
}
b: Builder
init_builder(&b, allocator)
builder_init(&b, allocator)
writer := to_writer(&b)
str := s
column: int
@@ -1690,8 +1690,8 @@ centre_justify :: proc(str: string, length: int, pad: string, allocator := conte
pad_len := rune_count(pad)
b: Builder
init_builder(&b, allocator)
grow_builder(&b, len(str) + (remains/pad_len + 1)*len(pad))
builder_init(&b, allocator)
builder_grow(&b, len(str) + (remains/pad_len + 1)*len(pad))
w := to_writer(&b)
@@ -1713,8 +1713,8 @@ left_justify :: proc(str: string, length: int, pad: string, allocator := context
pad_len := rune_count(pad)
b: Builder
init_builder(&b, allocator)
grow_builder(&b, len(str) + (remains/pad_len + 1)*len(pad))
builder_init(&b, allocator)
builder_grow(&b, len(str) + (remains/pad_len + 1)*len(pad))
w := to_writer(&b)
@@ -1735,8 +1735,8 @@ right_justify :: proc(str: string, length: int, pad: string, allocator := contex
pad_len := rune_count(pad)
b: Builder
init_builder(&b, allocator)
grow_builder(&b, len(str) + (remains/pad_len + 1)*len(pad))
builder_init(&b, allocator)
builder_grow(&b, len(str) + (remains/pad_len + 1)*len(pad))
w := to_writer(&b)
+8 -12
View File
@@ -3,24 +3,22 @@
package sync
import "core:c"
import "core:os"
import "core:time"
UMTX_OP_WAIT :: 2
UMTX_OP_WAKE :: 3
ETIMEDOUT :: 60
foreign import libc "system:c"
foreign libc {
_umtx_op :: proc "c" (obj: rawptr, op: c.int, val: c.ulong, uaddr: rawptr, uaddr2: rawptr) -> c.int ---
__error :: proc "c" () -> ^c.int ---
}
_futex_wait :: proc(f: ^Futex, expected: u32) -> bool {
timeout := os.Unix_File_Time{
seconds = 5,
nanoseconds = 0,
}
timeout := [2]i64{14400, 0} // 4 hours
for {
res := _umtx_op(f, UMTX_OP_WAIT, c.ulong(expected), nil, &timeout)
@@ -28,7 +26,7 @@ _futex_wait :: proc(f: ^Futex, expected: u32) -> bool {
return true
}
if os.Errno(os.get_last_error()) == os.ETIMEDOUT {
if __error()^ == ETIMEDOUT {
continue
}
@@ -42,16 +40,14 @@ _futex_wait_with_timeout :: proc(f: ^Futex, expected: u32, duration: time.Durati
return false
}
res := _umtx_op(f, UMTX_OP_WAIT, c.ulong(expected), nil, &os.Unix_File_Time{
seconds = (os.time_t)(duration/1e9),
nanoseconds = (c.long)(duration%1e9),
})
timeout := [2]i64{i64(duration/1e9), i64(duration%1e9)}
res := _umtx_op(f, UMTX_OP_WAIT, c.ulong(expected), nil, &timeout)
if res != -1 {
return true
}
if os.Errno(os.get_last_error()) == os.ETIMEDOUT {
if __error()^ == ETIMEDOUT {
return false
}
+8 -2
View File
@@ -2,8 +2,14 @@
//+private
package sync
import "core:os"
import "core:c"
foreign import dl "system:dl"
foreign dl {
pthread_getthreadid_np :: proc "c" () -> c.int ---
}
_current_thread_id :: proc "contextless" () -> int {
return os.current_thread_id()
return int(pthread_getthreadid_np())
}
+171 -259
View File
@@ -1148,6 +1148,156 @@ foreign wasi {
*/
how: sdflags_t,
) -> errno_t ---
/**
* Return a description of the given preopened file descriptor.
*/
fd_prestat_dir_name :: proc(
fd: fd_t,
/**
* A buffer into which to write the preopened directory name.
*/
path: string,
) -> errno_t ---
/**
* Create a directory.
* Note: This is similar to `mkdirat` in POSIX.
*/
path_create_directory :: proc(
fd: fd_t,
/**
* The path at which to create the directory.
*/
path: string,
) -> errno_t ---
/**
* Adjust the timestamps of a file or directory.
* Note: This is similar to `utimensat` in POSIX.
*/
path_filestat_set_times :: proc(
fd: fd_t,
/**
* Flags determining the method of how the path is resolved.
*/
flags: lookupflags_t,
/**
* The path of the file or directory to operate on.
*/
path: string,
/**
* The desired values of the data access timestamp.
*/
atim: timestamp_t,
/**
* The desired values of the data modification timestamp.
*/
mtim: timestamp_t,
/**
* A bitmask indicating which timestamps to adjust.
*/
fst_flags: fstflags_t,
) -> errno_t ---
/**
* Remove a directory.
* Return `errno::notempty` if the directory is not empty.
* Note: This is similar to `unlinkat(fd, path, AT_REMOVEDIR)` in POSIX.
*/
path_remove_directory :: proc(
fd: fd_t,
/**
* The path to a directory to remove.
*/
path: string,
) -> errno_t ---
/**
* Create a hard link.
* Note: This is similar to `linkat` in POSIX.
*/
path_link :: proc(
old_fd: fd_t,
/**
* Flags determining the method of how the path is resolved.
*/
old_flags: lookupflags_t,
/**
* The source path from which to link.
*/
old_path: string,
/**
* The working directory at which the resolution of the new path starts.
*/
new_fd: fd_t,
/**
* The destination path at which to create the hard link.
*/
new_path: string,
) -> errno_t ---
/**
* Rename a file or directory.
* Note: This is similar to `renameat` in POSIX.
*/
path_rename :: proc(
fd: fd_t,
/**
* The source path of the file or directory to rename.
*/
old_path: string,
/**
* The working directory at which the resolution of the new path starts.
*/
new_fd: fd_t,
/**
* The destination path to which to rename the file or directory.
*/
new_path: string,
) -> errno_t ---
/**
* Create a symbolic link.
* Note: This is similar to `symlinkat` in POSIX.
*/
path_symlink :: proc(
/**
* The contents of the symbolic link.
*/
old_path: string,
fd: fd_t,
/**
* The destination path at which to create the symbolic link.
*/
new_path: string,
) -> errno_t ---
/**
* Unlink a file.
* Return `errno::isdir` if the path refers to a directory.
* Note: This is similar to `unlinkat(fd, path, 0)` in POSIX.
*/
path_unlink_file :: proc(
fd: fd_t,
/**
* The path to a file to unlink.
*/
path: string,
) -> errno_t ---
/**
* Write high-quality random data into a buffer.
* This function blocks when the implementation is unable to immediately
* provide sufficient high-quality random data.
* This function may execute slowly, so when large mounts of random data are
* required, it's advisable to use this function to seed a pseudo-random
* number generator, rather than to provide the random data directly.
*/
random_get :: proc(
/**
* The buffer to fill with random data.
*/
buf: []u8,
) -> errno_t ---
}
/**
@@ -1250,7 +1400,7 @@ fd_pread :: proc "c" (
*/
offset: filesize_t,
) -> (n: size_t, err: errno_t) {
err = wasi_fd_pread(fd, raw_data(iovs), len(iovs), offset, &n)
err = wasi_fd_pread(fd, iovs, offset, &n)
return
}
/**
@@ -1281,7 +1431,7 @@ fd_pwrite :: proc "c" (
*/
offset: filesize_t,
) -> (n: size_t, err: errno_t) {
err = wasi_fd_pwrite(fd, raw_data(iovs), len(iovs), offset, &n)
err = wasi_fd_pwrite(fd, iovs, offset, &n)
return
}
/**
@@ -1297,7 +1447,7 @@ fd_read :: proc "c" (
*/
iovs: []iovec_t,
) -> (n: size_t, err: errno_t) {
err = wasi_fd_read(fd, raw_data(iovs), len(iovs), &n)
err = wasi_fd_read(fd, iovs, &n)
return
}
/**
@@ -1324,7 +1474,7 @@ fd_readdir :: proc "c" (
*/
cookie: dircookie_t,
) -> (n: size_t, err: errno_t) {
err = wasi_fd_readdir(fd, raw_data(buf), len(buf), cookie, &n)
err = wasi_fd_readdir(fd, buf, cookie, &n)
return
}
/**
@@ -1370,7 +1520,7 @@ fd_write :: proc "c" (
*/
iovs: []ciovec_t,
) -> (n: size_t, err: errno_t) {
err = wasi_fd_write(fd, raw_data(iovs), len(iovs), &n)
err = wasi_fd_write(fd, iovs, &n)
return
}
/**
@@ -1390,7 +1540,7 @@ path_filestat_get :: proc "c" (
*/
path: string,
) -> (offset: filestat_t, err: errno_t) {
err = wasi_path_filestat_get(fd, flags, raw_data(path), len(path), &offset)
err = wasi_path_filestat_get(fd, flags, path, &offset)
return
}
/**
@@ -1432,7 +1582,7 @@ path_open :: proc "c" (
fs_rights_inheriting: rights_t,
fdflags: fdflags_t,
) -> (file: fd_t, err: errno_t) {
err = wasi_path_open(fd, dirflags, raw_data(path), len(path), oflags, fs_rights_base, fs_rights_inheriting, fdflags, &file)
err = wasi_path_open(fd, dirflags, path, oflags, fs_rights_base, fs_rights_inheriting, fdflags, &file)
return
}
/**
@@ -1452,7 +1602,7 @@ path_readlink :: proc "c" (
*/
buf: []u8,
) -> (n: size_t, err: errno_t) {
err = wasi_path_readlink(fd, raw_data(path), len(path), raw_data(buf), len(buf), &n)
err = wasi_path_readlink(fd, path, buf, &n)
return
}
/**
@@ -1495,7 +1645,7 @@ sock_recv :: proc "c" (
*/
ri_flags: riflags_t,
) -> (n: size_t, flags: roflags_t, err: errno_t) {
err = wasi_sock_recv(fd, raw_data(ri_data), len(ri_data), ri_flags, &n, &flags)
err = wasi_sock_recv(fd, ri_data, ri_flags, &n, &flags)
return
}
/**
@@ -1516,172 +1666,11 @@ sock_send :: proc "c" (
*/
si_flags: siflags_t,
) -> (n: size_t, err: errno_t) {
err = wasi_sock_send(fd, raw_data(si_data), len(si_data), si_flags, &n)
err = wasi_sock_send(fd, si_data, si_flags, &n)
return
}
/**
* Return a description of the given preopened file descriptor.
*/
fd_prestat_dir_name :: proc(
fd: fd_t,
/**
* A buffer into which to write the preopened directory name.
*/
path: string,
) -> errno_t {
return wasm_fd_prestat_dir_name(fd, raw_data(path), len(path))
}
/**
* Create a directory.
* Note: This is similar to `mkdirat` in POSIX.
*/
path_create_directory :: proc(
fd: fd_t,
/**
* The path at which to create the directory.
*/
path: string,
) -> errno_t {
return wasm_path_create_directory(fd, raw_data(path), len(path))
}
/**
* Adjust the timestamps of a file or directory.
* Note: This is similar to `utimensat` in POSIX.
*/
path_filestat_set_times :: proc(
fd: fd_t,
/**
* Flags determining the method of how the path is resolved.
*/
flags: lookupflags_t,
/**
* The path of the file or directory to operate on.
*/
path: string,
/**
* The desired values of the data access timestamp.
*/
atim: timestamp_t,
/**
* The desired values of the data modification timestamp.
*/
mtim: timestamp_t,
/**
* A bitmask indicating which timestamps to adjust.
*/
fst_flags: fstflags_t,
) -> errno_t {
return wasm_path_filestat_set_times(fd, flags, raw_data(path), len(path), atim, mtim, fst_flags)
}
/**
* Remove a directory.
* Return `errno::notempty` if the directory is not empty.
* Note: This is similar to `unlinkat(fd, path, AT_REMOVEDIR)` in POSIX.
*/
path_remove_directory :: proc(
fd: fd_t,
/**
* The path to a directory to remove.
*/
path: string,
) -> errno_t {
return wasm_path_remove_directory(fd, raw_data(path), len(path))
}
/**
* Create a hard link.
* Note: This is similar to `linkat` in POSIX.
*/
path_link :: proc(
old_fd: fd_t,
/**
* Flags determining the method of how the path is resolved.
*/
old_flags: lookupflags_t,
/**
* The source path from which to link.
*/
old_path: string,
/**
* The working directory at which the resolution of the new path starts.
*/
new_fd: fd_t,
/**
* The destination path at which to create the hard link.
*/
new_path: string,
) -> errno_t {
return wasm_path_link(old_fd, old_flags, raw_data(old_path), len(old_path), new_fd, raw_data(new_path), len(new_path))
}
/**
* Rename a file or directory.
* Note: This is similar to `renameat` in POSIX.
*/
path_rename :: proc(
fd: fd_t,
/**
* The source path of the file or directory to rename.
*/
old_path: string,
/**
* The working directory at which the resolution of the new path starts.
*/
new_fd: fd_t,
/**
* The destination path to which to rename the file or directory.
*/
new_path: string,
) -> errno_t {
return wasm_path_rename(fd, raw_data(old_path), len(old_path), new_fd, raw_data(new_path), len(new_path))
}
/**
* Create a symbolic link.
* Note: This is similar to `symlinkat` in POSIX.
*/
path_symlink :: proc(
/**
* The contents of the symbolic link.
*/
old_path: string,
fd: fd_t,
/**
* The destination path at which to create the symbolic link.
*/
new_path: string,
) -> errno_t {
return wasm_path_symlink(raw_data(old_path), len(old_path), fd, raw_data(new_path), len(new_path))
}
/**
* Unlink a file.
* Return `errno::isdir` if the path refers to a directory.
* Note: This is similar to `unlinkat(fd, path, 0)` in POSIX.
*/
path_unlink_file :: proc(
fd: fd_t,
/**
* The path to a file to unlink.
*/
path: string,
) -> errno_t {
return wasm_path_unlink_file(fd, raw_data(path), len(path))
}
/**
* Write high-quality random data into a buffer.
* This function blocks when the implementation is unable to immediately
* provide sufficient high-quality random data.
* This function may execute slowly, so when large mounts of random data are
* required, it's advisable to use this function to seed a pseudo-random
* number generator, rather than to provide the random data directly.
*/
random_get :: proc(
/**
* The buffer to fill with random data.
*/
buf: []u8,
) -> errno_t {
return wasm_random_get(raw_data(buf), len(buf))
}
@@ -1722,8 +1711,7 @@ foreign wasi {
@(link_name="fd_pread")
wasi_fd_pread :: proc(
fd: fd_t,
iovs: [^]iovec_t,
iovs_len: size_t,
iovs: []iovec_t,
offset: filesize_t,
retptr0: ^size_t,
) -> errno_t ---
@@ -1735,23 +1723,20 @@ foreign wasi {
@(link_name="fd_pwrite")
wasi_fd_pwrite :: proc(
fd: fd_t,
iovs: [^]ciovec_t,
iovs_len: size_t,
iovs: []ciovec_t,
offset: filesize_t,
retptr0: ^size_t,
) -> errno_t ---
@(link_name="fd_read")
wasi_fd_read :: proc(
fd: fd_t,
iovs: [^]iovec_t,
iovs_len: size_t,
iovs: []iovec_t,
retptr0: ^size_t,
) -> errno_t ---
@(link_name="fd_readdir")
wasi_fd_readdir :: proc(
fd: fd_t,
buf: [^]u8,
buf_len: size_t,
buf: []u8,
cookie: dircookie_t,
retptr0: ^size_t,
) -> errno_t ---
@@ -1770,8 +1755,7 @@ foreign wasi {
@(link_name="fd_write")
wasi_fd_write :: proc(
fd: fd_t,
iovs: [^]ciovec_t,
iovs_len: size_t,
iovs: []ciovec_t,
retptr0: ^size_t,
) -> errno_t ---
@(link_name="path_filestat_get")
@@ -1781,16 +1765,14 @@ foreign wasi {
/**
* The path of the file or directory to inspect.
*/
path: [^]u8,
path_len: size_t,
path: string,
retptr0: ^filestat_t,
) -> errno_t ---
@(link_name="path_open")
wasi_path_open :: proc(
fd: fd_t,
dirflags: lookupflags_t,
path: [^]u8,
path_len: size_t,
path: string,
oflags: oflags_t,
fs_rights_base: rights_t,
fs_rights_inheriting: rights_t,
@@ -1800,10 +1782,8 @@ foreign wasi {
@(link_name="path_readlink")
wasi_path_readlink :: proc(
fd: fd_t,
path: [^]u8,
path_len: size_t,
buf: [^]u8,
buf_len: size_t,
path: string,
buf: []u8,
retptr0: ^size_t,
) -> errno_t ---
@(link_name="poll_oneoff")
@@ -1816,8 +1796,7 @@ foreign wasi {
@(link_name="sock_recv")
wasi_sock_recv :: proc(
fd: fd_t,
ri_data: [^]iovec_t,
ri_data_len: size_t,
ri_data: []iovec_t,
ri_flags: riflags_t,
retptr0: ^size_t,
retptr1: ^roflags_t,
@@ -1825,75 +1804,8 @@ foreign wasi {
@(link_name="sock_send")
wasi_sock_send :: proc(
fd: fd_t,
si_data: [^]ciovec_t,
si_data_len: size_t,
si_data: []ciovec_t,
si_flags: siflags_t,
retptr0: ^size_t,
) -> errno_t ---
@(link_name="fd_prestat_dir_name")
wasm_fd_prestat_dir_name :: proc(
fd: fd_t,
path: [^]u8,
path_len: size_t,
) -> errno_t ---
@(link_name="path_create_directory")
wasm_path_create_directory :: proc(
fd: fd_t,
path: [^]u8,
path_len: size_t,
) -> errno_t ---
@(link_name="path_filestat_set_times")
wasm_path_filestat_set_times :: proc(
fd: fd_t,
flags: lookupflags_t,
path: [^]u8,
path_len: size_t,
atim: timestamp_t,
mtim: timestamp_t,
fst_flags: fstflags_t,
) -> errno_t ---
@(link_name="path_remove_directory")
wasm_path_remove_directory :: proc(
fd: fd_t,
path: [^]u8,
path_len: size_t,
) -> errno_t ---
@(link_name="path_link")
wasm_path_link :: proc(
old_fd: fd_t,
old_flags: lookupflags_t,
old_path: [^]u8,
old_path_len: size_t,
new_fd: fd_t,
new_path: [^]u8,
new_path_len: size_t,
) -> errno_t ---
@(link_name="path_rename")
wasm_path_rename :: proc(
fd: fd_t,
old_path: [^]u8,
old_path_len: size_t,
new_fd: fd_t,
new_path: [^]u8,
new_path_len: size_t,
) -> errno_t ---
@(link_name="path_symlink")
wasm_path_symlink :: proc(
old_path: [^]u8,
old_path_len: size_t,
fd: fd_t,
new_path: [^]u8,
new_path_len: size_t,
) -> errno_t ---
@(link_name="path_unlink_file")
wasm_path_unlink_file :: proc(
fd: fd_t,
path: [^]u8,
path_len: size_t,
) -> errno_t ---
@(link_name="random_get")
wasm_random_get :: proc(
buf: [^]u8,
buf_len: size_t,
) -> errno_t ---
}
+1
View File
@@ -18,6 +18,7 @@ foreign user32 {
RegisterClassW :: proc(lpWndClass: ^WNDCLASSW) -> ATOM ---
RegisterClassExW :: proc(^WNDCLASSEXW) -> ATOM ---
UnregisterClassW :: proc(lpClassName: LPCWSTR, hInstance: HINSTANCE) -> BOOL ---
CreateWindowExW :: proc(
dwExStyle: DWORD,
+4
View File
@@ -22,6 +22,10 @@ GET_Y_LPARAM :: #force_inline proc "contextless" (lp: LPARAM) -> c_int {
return cast(c_int)cast(c_short)HIWORD(cast(DWORD)lp)
}
MAKE_WORD :: #force_inline proc "contextless" (x, y: WORD) -> WORD {
return x << 8 | y
}
utf8_to_utf16 :: proc(s: string, allocator := context.temp_allocator) -> []u16 {
if len(s) < 1 {
return nil
+1 -1
View File
@@ -45,4 +45,4 @@ ERROR_NOT_SAME_OBJECT : DWORD : 1656
E_NOTIMPL :: HRESULT(-0x7fff_bfff) // 0x8000_4001
SUCCEEDED :: #force_inline proc(#any_int result: int) -> bool do return result >= 0
SUCCEEDED :: #force_inline proc(#any_int result: int) -> bool { return result >= 0 }
@@ -45,7 +45,7 @@ generate_encoding_entity_table :: proc() {
printf("\"%v\" loaded and parsed.\n", filename)
generated_buf: strings.Builder
defer strings.destroy_builder(&generated_buf)
defer strings.builder_destroy(&generated_buf)
w := strings.to_writer(&generated_buf)
charlist, charlist_ok := xml.find_child_by_ident(doc.root, "charlist")
+2
View File
@@ -1322,6 +1322,7 @@ bool init_build_paths(String init_filename) {
}
#if defined(GB_SYSTEM_WINDOWS)
if (bc->metrics.os == TargetOs_windows) {
if (bc->resource_filepath.len > 0) {
bc->build_paths[BuildPath_RC] = path_from_string(ha, bc->resource_filepath);
bc->build_paths[BuildPath_RES] = path_from_string(ha, bc->resource_filepath);
@@ -1377,6 +1378,7 @@ bool init_build_paths(String init_filename) {
}
}
}
}
#endif
// All the build targets and OSes.
+35 -18
View File
@@ -2959,7 +2959,14 @@ void check_binary_matrix(CheckerContext *c, Token const &op, Operand *x, Operand
goto matrix_error;
}
x->mode = Addressing_Value;
x->type = alloc_type_matrix(xt->Matrix.elem, xt->Matrix.row_count, yt->Matrix.column_count);
if (are_types_identical(xt, yt)) {
if (!is_type_named(x->type) && is_type_named(y->type)) {
// prefer the named type
x->type = y->type;
}
} else {
x->type = alloc_type_matrix(xt->Matrix.elem, xt->Matrix.row_count, yt->Matrix.column_count);
}
goto matrix_success;
} else if (yt->kind == Type_Array) {
if (!are_types_identical(xt->Matrix.elem, yt->Array.elem)) {
@@ -3021,7 +3028,6 @@ void check_binary_matrix(CheckerContext *c, Token const &op, Operand *x, Operand
matrix_success:
x->type = check_matrix_type_hint(x->type, type_hint);
return;
@@ -8404,23 +8410,30 @@ ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *node, Type *
if (is_type_bit_set(type)) {
// NOTE(bill): Encode as an integer
i64 lower = base_type(type)->BitSet.lower;
Type *bt = base_type(type);
BigInt bits = {};
BigInt one = {};
big_int_from_u64(&one, 1);
u64 bits = 0;
for_array(index, cl->elems) {
Ast *elem = cl->elems[index];
GB_ASSERT(elem->kind != Ast_FieldValue);
TypeAndValue tav = elem->tav;
ExactValue i = exact_value_to_integer(tav.value);
if (i.kind != ExactValue_Integer) {
for_array(i, cl->elems) {
Ast *e = cl->elems[i];
GB_ASSERT(e->kind != Ast_FieldValue);
TypeAndValue tav = e->tav;
if (tav.mode != Addressing_Constant) {
continue;
}
i64 val = big_int_to_i64(&i.value_integer);
val -= lower;
u64 bit = u64(1ll<<val);
bits |= bit;
GB_ASSERT(tav.value.kind == ExactValue_Integer);
i64 v = big_int_to_i64(&tav.value.value_integer);
i64 lower = bt->BitSet.lower;
u64 index = cast(u64)(v-lower);
BigInt bit = {};
big_int_from_u64(&bit, index);
big_int_shl(&bit, &one, &bit);
big_int_or(&bits, &bits, &bit);
}
o->value = exact_value_u64(bits);
o->value.kind = ExactValue_Integer;
o->value.value_integer = bits;
} else if (is_type_constant_type(type) && cl->elems.count == 0) {
ExactValue value = exact_value_compound(node);
Type *bt = core_type(type);
@@ -8643,6 +8656,8 @@ ExprKind check_selector_call_expr(CheckerContext *c, Operand *o, Ast *node, Type
Ast *first_arg = x.expr->SelectorExpr.expr;
GB_ASSERT(first_arg != nullptr);
first_arg->state_flags |= StateFlag_SelectorCallExpr;
Type *pt = base_type(x.type);
GB_ASSERT(pt->kind == Type_Proc);
Type *first_type = nullptr;
@@ -8668,6 +8683,7 @@ ExprKind check_selector_call_expr(CheckerContext *c, Operand *o, Ast *node, Type
y.mode = first_arg->tav.mode;
y.type = first_arg->tav.type;
y.value = first_arg->tav.value;
if (check_is_assignable_to(c, &y, first_type)) {
// Do nothing, it's valid
} else {
@@ -9286,7 +9302,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
check_unary_expr(c, o, ue->op, node);
}
o->expr = node;
return kind;
return Expr_Expr;
case_end;
@@ -10034,9 +10050,10 @@ gbString write_expr_to_string(gbString str, Ast *node, bool shorthand) {
str = write_expr_to_string(str, ce->proc, shorthand);
str = gb_string_appendc(str, "(");
for_array(i, ce->args) {
isize idx0 = cast(isize)ce->was_selector;
for (isize i = idx0; i < ce->args.count; i++) {
Ast *arg = ce->args[i];
if (i > 0) {
if (i > idx0) {
str = gb_string_appendc(str, ", ");
}
str = write_expr_to_string(str, arg, shorthand);
+44 -8
View File
@@ -695,11 +695,6 @@ void check_union_type(CheckerContext *ctx, Type *union_type, Ast *node, Array<Op
error(ut->align, "A union with #no_nil must have at least 2 variants");
}
break;
case UnionType_maybe:
if (variants.count != 1) {
error(ut->align, "A union with #maybe must have at 1 variant, got %lld", cast(long long)variants.count);
}
break;
}
if (ut->align != nullptr) {
@@ -1345,7 +1340,9 @@ ParameterValue handle_parameter_value(CheckerContext *ctx, Type *in_type, Type *
param_value.kind = ParameterValue_Constant;
param_value.value = o.value;
} else {
error(expr, "Default parameter must be a constant, %d", o.mode);
gbString s = expr_to_string(o.expr);
error(expr, "Default parameter must be a constant, got %s", s);
gb_string_free(s);
}
}
} else {
@@ -1614,6 +1611,10 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is
error(name, "'#any_int' can only be applied to variable fields");
p->flags &= ~FieldFlag_any_int;
}
if (p->flags&FieldFlag_by_ptr) {
error(name, "'#by_ptr' can only be applied to variable fields");
p->flags &= ~FieldFlag_by_ptr;
}
param = alloc_entity_type_name(scope, name->Ident.token, type, EntityState_Resolved);
param->TypeName.is_type_alias = true;
@@ -1690,10 +1691,17 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is
if (p->flags&FieldFlag_no_alias) {
if (!is_type_pointer(type)) {
error(name, "'#no_alias' can only be applied to fields of pointer type");
error(name, "'#no_alias' can only be applied pointer typed parameters");
p->flags &= ~FieldFlag_no_alias; // Remove the flag
}
}
if (p->flags&FieldFlag_by_ptr) {
if (is_type_internally_pointer_like(type)) {
error(name, "'#by_ptr' can only be applied to non-pointer-like parameters");
p->flags &= ~FieldFlag_by_ptr; // Remove the flag
}
}
if (is_poly_name) {
if (p->flags&FieldFlag_no_alias) {
error(name, "'#no_alias' can only be applied to non constant values");
@@ -1711,6 +1719,10 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is
error(name, "'#const' can only be applied to variable fields");
p->flags &= ~FieldFlag_const;
}
if (p->flags&FieldFlag_by_ptr) {
error(name, "'#by_ptr' can only be applied to variable fields");
p->flags &= ~FieldFlag_by_ptr;
}
if (!is_type_constant_type(type) && !is_type_polymorphic(type)) {
gbString str = type_to_string(type);
@@ -1743,6 +1755,9 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is
if (p->flags&FieldFlag_const) {
param->flags |= EntityFlag_ConstInput;
}
if (p->flags&FieldFlag_by_ptr) {
param->flags |= EntityFlag_ByPtr;
}
param->state = EntityState_Resolved; // NOTE(bill): This should have be resolved whilst determining it
add_entity(ctx, scope, name, param);
@@ -2685,7 +2700,28 @@ bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, Type *named_t
case_end;
case_ast_node(pt, PointerType, e);
*type = alloc_type_pointer(check_type(ctx, pt->type));
CheckerContext c = *ctx;
c.type_path = new_checker_type_path();
defer (destroy_checker_type_path(c.type_path));
Type *elem = t_invalid;
Operand o = {};
check_expr_or_type(&c, &o, pt->type);
if (o.mode != Addressing_Invalid && o.mode != Addressing_Type) {
// NOTE(bill): call check_type_expr again to get a consistent error message
begin_error_block();
elem = check_type_expr(&c, pt->type, nullptr);
if (o.mode == Addressing_Variable) {
gbString s = expr_to_string(pt->type);
error_line("\tSuggestion: ^ is used for pointer types, did you mean '&%s'?\n", s);
gb_string_free(s);
}
end_error_block();
} else {
elem = o.type;
}
*type = alloc_type_pointer(elem);
set_base_type(named_type, *type);
return true;
case_end;
+1 -1
View File
@@ -434,7 +434,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
{STR_LIT("simd_neg"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("simd_abs"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("simd_abs"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("simd_min"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("simd_max"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-1
View File
@@ -98,7 +98,6 @@ enum OdinDocTypeFlag_Struct : u32 {
enum OdinDocTypeFlag_Union : u32 {
OdinDocTypeFlag_Union_polymorphic = 1<<0,
OdinDocTypeFlag_Union_no_nil = 1<<1,
OdinDocTypeFlag_Union_maybe = 1<<2,
OdinDocTypeFlag_Union_shared_nil = 1<<3,
};
+1
View File
@@ -83,6 +83,7 @@ enum EntityFlag : u64 {
EntityFlag_CustomLinkage_LinkOnce = 1ull<<44,
EntityFlag_Require = 1ull<<50,
EntityFlag_ByPtr = 1ull<<51, // enforce parameter is passed by pointer
EntityFlag_Overridden = 1ull<<63,
};
+4
View File
@@ -90,6 +90,10 @@ extern "C" {
#error This operating system is not supported
#endif
#if defined(GB_SYSTEM_OPENBSD)
#include <sys/wait.h>
#endif
#if defined(_MSC_VER)
#define GB_COMPILER_MSVC 1
#elif defined(__GNUC__)
+14 -7
View File
@@ -233,7 +233,7 @@ i64 lb_sizeof(LLVMTypeRef type) {
i64 elem_size = lb_sizeof(elem);
i64 count = LLVMGetVectorSize(type);
i64 size = count * elem_size;
return gb_clamp(next_pow2(size), 1, build_context.max_align);
return next_pow2(size);
}
}
@@ -801,16 +801,23 @@ namespace lbAbiAmd64SysV {
i64 elem_sz = lb_sizeof(elem);
LLVMTypeKind elem_kind = LLVMGetTypeKind(elem);
RegClass reg = RegClass_NoClass;
unsigned elem_width = LLVMGetIntTypeWidth(elem);
switch (elem_kind) {
case LLVMIntegerTypeKind:
case LLVMHalfTypeKind:
switch (LLVMGetIntTypeWidth(elem)) {
case 8: reg = RegClass_SSEInt8;
case 16: reg = RegClass_SSEInt16;
case 32: reg = RegClass_SSEInt32;
case 64: reg = RegClass_SSEInt64;
switch (elem_width) {
case 8: reg = RegClass_SSEInt8; break;
case 16: reg = RegClass_SSEInt16; break;
case 32: reg = RegClass_SSEInt32; break;
case 64: reg = RegClass_SSEInt64; break;
default:
GB_PANIC("Unhandled integer width for vector type");
if (elem_width > 64) {
for (i64 i = 0; i < len; i++) {
classify_with(elem, cls, ix, off + i*elem_sz);
}
break;
}
GB_PANIC("Unhandled integer width for vector type %u", elem_width);
}
break;
case LLVMFloatTypeKind:
+7
View File
@@ -292,6 +292,9 @@ struct lbProcedure {
LLVMMetadataRef debug_info;
lbCopyElisionHint copy_elision_hint;
PtrMap<Ast *, lbValue> selector_values;
PtrMap<Ast *, lbAddr> selector_addr;
};
@@ -479,7 +482,11 @@ LLVMValueRef llvm_basic_shuffle(lbProcedure *p, LLVMValueRef vector, LLVMValueRe
void lb_mem_copy_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbValue len, bool is_volatile=false);
void lb_mem_copy_non_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbValue len, bool is_volatile=false);
LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, LLVMValueRef len, unsigned alignment, bool is_volatile);
i64 lb_max_zero_init_size(void) {
return cast(i64)(4*build_context.word_size);
}
#define LB_STARTUP_RUNTIME_PROC_NAME "__$startup_runtime"
#define LB_STARTUP_TYPE_INFO_PROC_NAME "__$startup_type_info"
+10 -12
View File
@@ -1025,7 +1025,10 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
return lb_const_nil(m, original_type);
}
u64 bits = 0;
BigInt bits = {};
BigInt one = {};
big_int_from_u64(&one, 1);
for_array(i, cl->elems) {
Ast *e = cl->elems[i];
GB_ASSERT(e->kind != Ast_FieldValue);
@@ -1037,18 +1040,13 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
GB_ASSERT(tav.value.kind == ExactValue_Integer);
i64 v = big_int_to_i64(&tav.value.value_integer);
i64 lower = type->BitSet.lower;
bits |= 1ull<<cast(u64)(v-lower);
u64 index = cast(u64)(v-lower);
BigInt bit = {};
big_int_from_u64(&bit, index);
big_int_shl(&bit, &one, &bit);
big_int_or(&bits, &bits, &bit);
}
if (is_type_different_to_arch_endianness(type)) {
i64 size = type_size_of(type);
switch (size) {
case 2: bits = cast(u64)gb_endian_swap16(cast(u16)bits); break;
case 4: bits = cast(u64)gb_endian_swap32(cast(u32)bits); break;
case 8: bits = cast(u64)gb_endian_swap64(cast(u64)bits); break;
}
}
res.value = LLVMConstInt(lb_type(m, original_type), bits, false);
res.value = lb_big_int_to_llvm(m, original_type, &bits);
return res;
} else if (is_type_matrix(type)) {
ast_node(cl, CompoundLit, value.value_compound);
+5 -1
View File
@@ -43,6 +43,10 @@ LLVMMetadataRef lb_debug_location_from_ast(lbProcedure *p, Ast *node) {
GB_ASSERT(node != nullptr);
return lb_debug_location_from_token_pos(p, ast_token(node).pos);
}
LLVMMetadataRef lb_debug_end_location_from_ast(lbProcedure *p, Ast *node) {
GB_ASSERT(node != nullptr);
return lb_debug_location_from_token_pos(p, ast_end_token(node).pos);
}
LLVMMetadataRef lb_debug_type_internal_proc(lbModule *m, Type *type) {
i64 size = type_size_of(type); // Check size
@@ -969,7 +973,7 @@ void lb_add_debug_local_variable(lbProcedure *p, LLVMValueRef ptr, Type *type, T
);
LLVMValueRef storage = ptr;
LLVMBasicBlockRef block = p->decl_block->block;
LLVMBasicBlockRef block = p->curr_block->block;
LLVMMetadataRef llvm_debug_loc = lb_debug_location_from_token_pos(p, token.pos);
LLVMMetadataRef llvm_expr = LLVMDIBuilderCreateExpression(m->debug_builder, nullptr, 0);
lb_set_llvm_metadata(m, ptr, llvm_expr);
+81 -29
View File
@@ -1,3 +1,4 @@
lbValue lb_emit_arith_matrix(lbProcedure *p, TokenKind op, lbValue lhs, lbValue rhs, Type *type, bool component_wise=false);
lbValue lb_emit_logical_binary_expr(lbProcedure *p, TokenKind op, Ast *left, Ast *right, Type *type) {
lbModule *m = p->module;
@@ -265,6 +266,11 @@ lbValue lb_emit_unary_arith(lbProcedure *p, TokenKind op, lbValue x, Type *type)
} else {
res.value = LLVMBuildNeg(p->builder, x.value, "");
}
} else if (is_type_matrix(x.type)) {
lbValue zero = {};
zero.value = LLVMConstNull(lb_type(p->module, type));
zero.type = type;
return lb_emit_arith_matrix(p, Token_Sub, zero, x, type, true);
} else {
GB_PANIC("Unhandled type %s", type_to_string(x.type));
}
@@ -976,7 +982,7 @@ lbValue lb_emit_vector_mul_matrix(lbProcedure *p, lbValue lhs, lbValue rhs, Type
lbValue lb_emit_arith_matrix(lbProcedure *p, TokenKind op, lbValue lhs, lbValue rhs, Type *type, bool component_wise=false) {
lbValue lb_emit_arith_matrix(lbProcedure *p, TokenKind op, lbValue lhs, lbValue rhs, Type *type, bool component_wise) {
GB_ASSERT(is_type_matrix(lhs.type) || is_type_matrix(rhs.type));
@@ -1425,10 +1431,13 @@ lbValue lb_build_binary_expr(lbProcedure *p, Ast *expr) {
Type *it = bit_set_to_int(rt);
left = lb_emit_conv(p, left, it);
if (is_type_different_to_arch_endianness(it)) {
left = lb_emit_byte_swap(p, left, integer_endian_type_to_platform_type(it));
}
lbValue lower = lb_const_value(p->module, it, exact_value_i64(rt->BitSet.lower));
lbValue key = lb_emit_arith(p, Token_Sub, left, lower, it);
lbValue bit = lb_emit_arith(p, Token_Shl, lb_const_int(p->module, it, 1), key, it);
lbValue lower = lb_const_value(p->module, left.type, exact_value_i64(rt->BitSet.lower));
lbValue key = lb_emit_arith(p, Token_Sub, left, lower, left.type);
lbValue bit = lb_emit_arith(p, Token_Shl, lb_const_int(p->module, left.type, 1), key, left.type);
bit = lb_emit_conv(p, bit, it);
lbValue old_value = lb_emit_transmute(p, right, it);
@@ -2993,9 +3002,8 @@ lbValue lb_build_unary_and(lbProcedure *p, Ast *expr) {
return lb_build_addr_ptr(p, ue->expr);
}
lbValue lb_build_expr_internal(lbProcedure *p, Ast *expr);
lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
lbModule *m = p->module;
u16 prev_state_flags = p->state_flags;
defer (p->state_flags = prev_state_flags);
@@ -3022,6 +3030,38 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
p->state_flags = out;
}
// IMPORTANT NOTE(bill):
// Selector Call Expressions (foo->bar(...))
// must only evaluate `foo` once as it gets transformed into
// `foo.bar(foo, ...)`
// And if `foo` is a procedure call or something more complex, storing the value
// once is a very good idea
// If a stored value is found, it must be removed from the cache
if (expr->state_flags & StateFlag_SelectorCallExpr) {
lbValue *pp = map_get(&p->selector_values, expr);
if (pp != nullptr) {
lbValue res = *pp;
map_remove(&p->selector_values, expr);
return res;
}
lbAddr *pa = map_get(&p->selector_addr, expr);
if (pa != nullptr) {
lbAddr res = *pa;
map_remove(&p->selector_addr, expr);
return lb_addr_load(p, res);
}
}
lbValue res = lb_build_expr_internal(p, expr);
if (expr->state_flags & StateFlag_SelectorCallExpr) {
map_set(&p->selector_values, expr, res);
}
return res;
}
lbValue lb_build_expr_internal(lbProcedure *p, Ast *expr) {
lbModule *m = p->module;
expr = unparen_expr(expr);
TokenPos expr_pos = ast_token(expr).pos;
@@ -3040,17 +3080,6 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
return lb_const_value(p->module, type, tv.value);
}
#if 0
LLVMMetadataRef prev_debug_location = nullptr;
if (p->debug_info != nullptr) {
prev_debug_location = LLVMGetCurrentDebugLocation2(p->builder);
LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, expr));
}
defer (if (prev_debug_location != nullptr) {
LLVMSetCurrentDebugLocation2(p->builder, prev_debug_location);
});
#endif
switch (expr->kind) {
case_ast_node(bl, BasicLit, expr);
TokenPos pos = bl->token.pos;
@@ -3119,14 +3148,7 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
case_ast_node(se, SelectorCallExpr, expr);
GB_ASSERT(se->modified_call);
TypeAndValue tav = type_and_value_of_expr(expr);
GB_ASSERT(tav.mode != Addressing_Invalid);
lbValue res = lb_build_call_expr(p, se->call);
ast_node(ce, CallExpr, se->call);
ce->sce_temp_data = gb_alloc_copy(permanent_allocator(), &res, gb_size_of(res));
return res;
return lb_build_call_expr(p, se->call);
case_end;
case_ast_node(te, TernaryIfExpr, expr);
@@ -3142,19 +3164,27 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
lb_start_block(p, then);
Type *type = default_type(type_of_expr(expr));
LLVMTypeRef llvm_type = lb_type(p->module, type);
incoming_values[0] = lb_emit_conv(p, lb_build_expr(p, te->x), type).value;
if (is_type_internally_pointer_like(type)) {
incoming_values[0] = LLVMBuildBitCast(p->builder, incoming_values[0], llvm_type, "");
}
lb_emit_jump(p, done);
lb_start_block(p, else_);
incoming_values[1] = lb_emit_conv(p, lb_build_expr(p, te->y), type).value;
if (is_type_internally_pointer_like(type)) {
incoming_values[1] = LLVMBuildBitCast(p->builder, incoming_values[1], llvm_type, "");
}
lb_emit_jump(p, done);
lb_start_block(p, done);
lbValue res = {};
res.value = LLVMBuildPhi(p->builder, lb_type(p->module, type), "");
res.value = LLVMBuildPhi(p->builder, llvm_type, "");
res.type = type;
GB_ASSERT(p->curr_block->preds.count >= 2);
@@ -3412,9 +3442,34 @@ lbAddr lb_build_array_swizzle_addr(lbProcedure *p, AstCallExpr *ce, TypeAndValue
}
lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr);
lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
expr = unparen_expr(expr);
// IMPORTANT NOTE(bill):
// Selector Call Expressions (foo->bar(...))
// must only evaluate `foo` once as it gets transformed into
// `foo.bar(foo, ...)`
// And if `foo` is a procedure call or something more complex, storing the value
// once is a very good idea
// If a stored value is found, it must be removed from the cache
if (expr->state_flags & StateFlag_SelectorCallExpr) {
lbAddr *pp = map_get(&p->selector_addr, expr);
if (pp != nullptr) {
lbAddr res = *pp;
map_remove(&p->selector_addr, expr);
return res;
}
}
lbAddr addr = lb_build_addr_internal(p, expr);
if (expr->state_flags & StateFlag_SelectorCallExpr) {
map_set(&p->selector_addr, expr, addr);
}
return addr;
}
lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) {
switch (expr->kind) {
case_ast_node(i, Implicit, expr);
lbAddr v = {};
@@ -3556,9 +3611,6 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
case_end;
case_ast_node(se, SelectorCallExpr, expr);
GB_ASSERT(se->modified_call);
TypeAndValue tav = type_and_value_of_expr(expr);
GB_ASSERT(tav.mode != Addressing_Invalid);
lbValue e = lb_build_expr(p, expr);
return lb_addr(lb_address_from_load_or_generate_local(p, e));
case_end;
+23 -9
View File
@@ -855,7 +855,11 @@ void lb_emit_store(lbProcedure *p, lbValue ptr, lbValue value) {
if (LLVMIsNull(value.value)) {
LLVMTypeRef src_t = LLVMGetElementType(LLVMTypeOf(ptr.value));
LLVMBuildStore(p->builder, LLVMConstNull(src_t), ptr.value);
if (lb_sizeof(src_t) <= lb_max_zero_init_size()) {
LLVMBuildStore(p->builder, LLVMConstNull(src_t), ptr.value);
} else {
lb_mem_zero_ptr(p, ptr.value, a, 1);
}
return;
}
if (is_type_boolean(a)) {
@@ -1958,11 +1962,12 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
if (e->flags & EntityFlag_CVarArg) {
continue;
}
Type *e_type = reduce_tuple_to_single_type(e->type);
LLVMTypeRef param_type = nullptr;
if (is_type_boolean(e_type) &&
if (e->flags & EntityFlag_ByPtr) {
param_type = lb_type(m, alloc_type_pointer(e_type));
} else if (is_type_boolean(e_type) &&
type_size_of(e_type) <= 1) {
param_type = LLVMInt1TypeInContext(m->ctx);
} else {
@@ -2369,6 +2374,9 @@ LLVMValueRef lb_find_or_add_entity_string_ptr(lbModule *m, String const &str) {
LLVMValueRef global_data = LLVMAddGlobal(m->mod, LLVMTypeOf(data), name);
LLVMSetInitializer(global_data, data);
LLVMSetLinkage(global_data, LLVMPrivateLinkage);
LLVMSetUnnamedAddress(global_data, LLVMGlobalUnnamedAddr);
LLVMSetAlignment(global_data, 1);
LLVMSetGlobalConstant(global_data, true);
LLVMValueRef ptr = LLVMConstInBoundsGEP(global_data, indices, 2);
string_map_set(&m->const_strings, key, ptr);
@@ -2411,6 +2419,9 @@ lbValue lb_find_or_add_entity_string_byte_slice(lbModule *m, String const &str)
LLVMValueRef global_data = LLVMAddGlobal(m->mod, LLVMTypeOf(data), name);
LLVMSetInitializer(global_data, data);
LLVMSetLinkage(global_data, LLVMPrivateLinkage);
LLVMSetUnnamedAddress(global_data, LLVMGlobalUnnamedAddr);
LLVMSetAlignment(global_data, 1);
LLVMSetGlobalConstant(global_data, true);
LLVMValueRef ptr = nullptr;
if (str.len != 0) {
@@ -2647,6 +2658,7 @@ lbValue lb_generate_global_array(lbModule *m, Type *elem_type, i64 count, String
g.type = alloc_type_pointer(t);
LLVMSetInitializer(g.value, LLVMConstNull(lb_type(m, t)));
LLVMSetLinkage(g.value, LLVMPrivateLinkage);
LLVMSetUnnamedAddress(g.value, LLVMGlobalUnnamedAddr);
string_map_set(&m->members, s, g);
return g;
}
@@ -2729,20 +2741,18 @@ lbAddr lb_add_local(lbProcedure *p, Type *type, Entity *e, bool zero_init, i32 p
if (!zero_init && !force_no_init) {
// If there is any padding of any kind, just zero init regardless of zero_init parameter
LLVMTypeKind kind = LLVMGetTypeKind(llvm_type);
if (kind == LLVMArrayTypeKind) {
kind = LLVMGetTypeKind(lb_type(p->module, core_array_type(type)));
}
if (kind == LLVMStructTypeKind) {
i64 sz = type_size_of(type);
if (type_size_of_struct_pretend_is_packed(type) != sz) {
zero_init = true;
}
} else if (kind == LLVMArrayTypeKind) {
zero_init = true;
}
}
if (zero_init) {
lb_mem_zero_ptr(p, ptr, type, alignment);
}
lbValue val = {};
val.value = ptr;
val.type = alloc_type_pointer(type);
@@ -2752,6 +2762,10 @@ lbAddr lb_add_local(lbProcedure *p, Type *type, Entity *e, bool zero_init, i32 p
lb_add_debug_local_variable(p, ptr, type, e->token);
}
if (zero_init) {
lb_mem_zero_ptr(p, ptr, type, alignment);
}
return lb_addr(val);
}
+43 -18
View File
@@ -113,6 +113,8 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body)
p->branch_blocks.allocator = a;
p->context_stack.allocator = a;
p->scope_stack.allocator = a;
map_init(&p->selector_values, a, 0);
map_init(&p->selector_addr, a, 0);
if (p->is_foreign) {
lb_add_foreign_library_path(p->module, entity->Procedure.foreign_library);
@@ -433,6 +435,40 @@ void lb_start_block(lbProcedure *p, lbBlock *b) {
p->curr_block = b;
}
void lb_set_debug_position_to_procedure_begin(lbProcedure *p) {
if (p->debug_info == nullptr) {
return;
}
TokenPos pos = {};
if (p->body != nullptr) {
pos = ast_token(p->body).pos;
} else if (p->type_expr != nullptr) {
pos = ast_token(p->type_expr).pos;
} else if (p->entity != nullptr) {
pos = p->entity->token.pos;
}
if (pos.file_id != 0) {
LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_token_pos(p, pos));
}
}
void lb_set_debug_position_to_procedure_end(lbProcedure *p) {
if (p->debug_info == nullptr) {
return;
}
TokenPos pos = {};
if (p->body != nullptr) {
pos = ast_end_token(p->body).pos;
} else if (p->type_expr != nullptr) {
pos = ast_end_token(p->type_expr).pos;
} else if (p->entity != nullptr) {
pos = p->entity->token.pos;
}
if (pos.file_id != 0) {
LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_token_pos(p, pos));
}
}
void lb_begin_procedure_body(lbProcedure *p) {
DeclInfo *decl = decl_info_of_entity(p->entity);
if (decl != nullptr) {
@@ -564,29 +600,21 @@ void lb_begin_procedure_body(lbProcedure *p) {
lb_push_context_onto_stack_from_implicit_parameter(p);
}
lb_start_block(p, p->entry_block);
lb_set_debug_position_to_procedure_begin(p);
if (p->debug_info != nullptr) {
TokenPos pos = {};
if (p->body != nullptr) {
pos = ast_token(p->body).pos;
} else if (p->type_expr != nullptr) {
pos = ast_token(p->type_expr).pos;
} else if (p->entity != nullptr) {
pos = p->entity->token.pos;
}
if (pos.file_id != 0) {
LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_token_pos(p, pos));
}
if (p->context_stack.count != 0) {
p->curr_block = p->decl_block;
lb_add_debug_context_variable(p, lb_find_or_generate_context_ptr(p));
}
}
lb_start_block(p, p->entry_block);
}
void lb_end_procedure_body(lbProcedure *p) {
lb_set_debug_position_to_procedure_begin(p);
LLVMPositionBuilderAtEnd(p->builder, p->decl_block->block);
LLVMBuildBr(p->builder, p->entry_block->block);
LLVMPositionBuilderAtEnd(p->builder, p->curr_block->block);
@@ -598,6 +626,7 @@ void lb_end_procedure_body(lbProcedure *p) {
instr = LLVMGetLastInstruction(p->curr_block->block);
if (!lb_is_instr_terminating(instr)) {
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
lb_set_debug_position_to_procedure_end(p);
LLVMBuildRetVoid(p->builder);
}
}
@@ -2832,10 +2861,6 @@ lbValue lb_build_call_expr(lbProcedure *p, Ast *expr) {
expr = unparen_expr(expr);
ast_node(ce, CallExpr, expr);
if (ce->sce_temp_data) {
return *(lbValue *)ce->sce_temp_data;
}
lbValue res = lb_build_call_expr_internal(p, expr);
if (ce->optional_ok_one) { // TODO(bill): Minor hack for #optional_ok procedures
+20 -10
View File
@@ -1210,8 +1210,8 @@ void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope *scope) {
}
lb_emit_jump(p, done);
lb_close_scope(p, lbDeferExit_Default, done);
lb_start_block(p, done);
lb_close_scope(p, lbDeferExit_Default, done);
}
void lb_store_type_case_implicit(lbProcedure *p, Ast *clause, lbValue value) {
@@ -1253,7 +1253,6 @@ void lb_type_case_body(lbProcedure *p, Ast *label, Ast *clause, lbBlock *body, l
ast_node(cc, CaseClause, clause);
lb_push_target_list(p, label, done, nullptr, nullptr);
lb_open_scope(p, body->scope);
lb_build_stmt_list(p, cc->stmts);
lb_close_scope(p, lbDeferExit_Default, body);
lb_pop_target_list(p);
@@ -1263,6 +1262,7 @@ void lb_type_case_body(lbProcedure *p, Ast *label, Ast *clause, lbBlock *body, l
void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss) {
lbModule *m = p->module;
lb_open_scope(p, ss->scope);
ast_node(as, AssignStmt, ss->tag);
GB_ASSERT(as->lhs.count == 1);
@@ -1321,6 +1321,7 @@ void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss) {
for_array(i, body->stmts) {
Ast *clause = body->stmts[i];
ast_node(cc, CaseClause, clause);
lb_open_scope(p, cc->scope);
if (cc->list.count == 0) {
lb_start_block(p, default_block);
lb_store_type_case_implicit(p, clause, parent_value);
@@ -1329,6 +1330,9 @@ void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss) {
}
lbBlock *body = lb_create_block(p, "typeswitch.body");
if (p->debug_info != nullptr) {
LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, clause));
}
Type *case_type = nullptr;
for_array(type_index, cc->list) {
case_type = type_of_expr(cc->list[type_index]);
@@ -1375,6 +1379,7 @@ void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss) {
lb_emit_jump(p, done);
lb_start_block(p, done);
lb_close_scope(p, lbDeferExit_Default, done);
}
@@ -1721,6 +1726,9 @@ void lb_build_for_stmt(lbProcedure *p, Ast *node) {
ast_node(fs, ForStmt, node);
lb_open_scope(p, fs->scope); // Open Scope here
if (p->debug_info != nullptr) {
LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, node));
}
if (fs->init != nullptr) {
#if 1
@@ -1741,11 +1749,14 @@ void lb_build_for_stmt(lbProcedure *p, Ast *node) {
post = lb_create_block(p, "for.post");
}
lb_emit_jump(p, loop);
lb_start_block(p, loop);
if (loop != body) {
// right now the condition (all expressions) will not set it's debug location, so we will do it here
if (p->debug_info != nullptr) {
LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, fs->cond));
}
lb_build_cond(p, fs->cond, body, done);
lb_start_block(p, body);
}
@@ -1753,10 +1764,12 @@ void lb_build_for_stmt(lbProcedure *p, Ast *node) {
lb_push_target_list(p, fs->label, done, post, nullptr);
lb_build_stmt(p, fs->body);
lb_close_scope(p, lbDeferExit_Default, nullptr);
lb_pop_target_list(p);
if (p->debug_info != nullptr) {
LLVMSetCurrentDebugLocation2(p->builder, lb_debug_end_location_from_ast(p, fs->body));
}
lb_emit_jump(p, post);
if (fs->post != nullptr) {
@@ -1766,6 +1779,7 @@ void lb_build_for_stmt(lbProcedure *p, Ast *node) {
}
lb_start_block(p, done);
lb_close_scope(p, lbDeferExit_Default, nullptr);
}
void lb_build_assign_stmt_array(lbProcedure *p, TokenKind op, lbAddr const &lhs, lbValue const &value) {
@@ -1971,14 +1985,9 @@ void lb_build_stmt(lbProcedure *p, Ast *node) {
}
}
LLVMMetadataRef prev_debug_location = nullptr;
if (p->debug_info != nullptr) {
prev_debug_location = LLVMGetCurrentDebugLocation2(p->builder);
LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, node));
}
defer (if (prev_debug_location != nullptr) {
LLVMSetCurrentDebugLocation2(p->builder, prev_debug_location);
});
u16 prev_state_flags = p->state_flags;
defer (p->state_flags = prev_state_flags);
@@ -2073,7 +2082,8 @@ void lb_build_stmt(lbProcedure *p, Ast *node) {
lbAddr lval = {};
if (!is_blank_ident(name)) {
Entity *e = entity_of_node(name);
bool zero_init = true; // Always do it
// bool zero_init = true; // Always do it
bool zero_init = vd->values.count == 0;
lval = lb_add_local(p, e->type, e, zero_init);
}
array_add(&lvals, lval);
+26 -13
View File
@@ -1,3 +1,5 @@
lbValue lb_lookup_runtime_procedure(lbModule *m, String const &name);
bool lb_is_type_aggregate(Type *t) {
t = base_type(t);
switch (t->kind) {
@@ -48,18 +50,19 @@ lbValue lb_correct_endianness(lbProcedure *p, lbValue value) {
return value;
}
void lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, LLVMValueRef len, unsigned alignment, bool is_volatile) {
LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, LLVMValueRef len, unsigned alignment, bool is_volatile) {
bool is_inlinable = false;
i64 const_len = 0;
if (LLVMIsConstant(len)) {
const_len = cast(i64)LLVMConstIntGetSExtValue(len);
// TODO(bill): Determine when it is better to do the `*.inline` versions
if (const_len <= 4*build_context.word_size) {
if (const_len <= lb_max_zero_init_size()) {
is_inlinable = true;
}
}
char const *name = "llvm.memset";
if (is_inlinable) {
name = "llvm.memset.inline";
@@ -69,17 +72,29 @@ void lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, LLVMValueRef len
lb_type(p->module, t_rawptr),
lb_type(p->module, t_int)
};
unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
GB_ASSERT_MSG(id != 0, "Unable to find %s.%s.%s", name, LLVMPrintTypeToString(types[0]), LLVMPrintTypeToString(types[1]));
LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
if (true || is_inlinable) {
unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
GB_ASSERT_MSG(id != 0, "Unable to find %s.%s.%s", name, LLVMPrintTypeToString(types[0]), LLVMPrintTypeToString(types[1]));
LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
LLVMValueRef args[4] = {};
args[0] = LLVMBuildPointerCast(p->builder, ptr, types[0], "");
args[1] = LLVMConstInt(LLVMInt8TypeInContext(p->module->ctx), 0, false);
args[2] = LLVMBuildIntCast2(p->builder, len, types[1], /*signed*/false, "");
args[3] = LLVMConstInt(LLVMInt1TypeInContext(p->module->ctx), is_volatile, false);
LLVMValueRef args[4] = {};
args[0] = LLVMBuildPointerCast(p->builder, ptr, types[0], "");
args[1] = LLVMConstInt(LLVMInt8TypeInContext(p->module->ctx), 0, false);
args[2] = LLVMBuildIntCast2(p->builder, len, types[1], /*signed*/false, "");
args[3] = LLVMConstInt(LLVMInt1TypeInContext(p->module->ctx), is_volatile, false);
return LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
} else {
LLVMValueRef ip = lb_lookup_runtime_procedure(p->module, str_lit("memset")).value;
LLVMValueRef args[3] = {};
args[0] = LLVMBuildPointerCast(p->builder, ptr, types[0], "");
args[1] = LLVMConstInt(LLVMInt32TypeInContext(p->module->ctx), 0, false);
args[2] = LLVMBuildIntCast2(p->builder, len, types[1], /*signed*/false, "");
return LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
}
LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
}
void lb_mem_zero_ptr(lbProcedure *p, LLVMValueRef ptr, Type *type, unsigned alignment) {
@@ -1842,8 +1857,6 @@ void lb_set_wasm_export_attributes(LLVMValueRef value, String export_name) {
}
lbValue lb_lookup_runtime_procedure(lbModule *m, String const &name);
lbAddr lb_handle_objc_find_or_register_selector(lbProcedure *p, String const &name) {
lbAddr *found = string_map_get(&p->module->objc_selectors, name);
+9 -2
View File
@@ -463,8 +463,15 @@ i32 linker_stage(lbGenerator *gen) {
// correctly this way since all the other dependencies provided implicitly
// by the compiler frontend are still needed and most of the command
// line arguments prepared previously are incompatible with ld.
link_settings = gb_string_appendc(link_settings, "-Wl,-init,'_odin_entry_point' ");
link_settings = gb_string_appendc(link_settings, "-Wl,-fini,'_odin_exit_point' ");
if (build_context.metrics.os == TargetOs_darwin) {
link_settings = gb_string_appendc(link_settings, "-Wl,-init,'__odin_entry_point' ");
// NOTE(weshardee): __odin_exit_point should also be added, but -fini
// does not exist on MacOS
} else {
link_settings = gb_string_appendc(link_settings, "-Wl,-init,'_odin_entry_point' ");
link_settings = gb_string_appendc(link_settings, "-Wl,-fini,'_odin_exit_point' ");
}
} else if (build_context.metrics.os != TargetOs_openbsd) {
// OpenBSD defaults to PIE executable. do not pass -no-pie for it.
link_settings = gb_string_appendc(link_settings, "-no-pie ");
+28
View File
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="String">
<DisplayString>{text,[len]s8}</DisplayString>
<StringView>text,[len]s8</StringView>
</Type>
<Type Name="Array&lt;*&gt;">
<DisplayString>{{ size={count} capacity={capacity} }}</DisplayString>
<Expand>
<ArrayItems>
<Size>count</Size>
<ValuePointer>data</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<Type Name="Slice&lt;*&gt;">
<DisplayString>{{ size={count} }}</DisplayString>
<Expand>
<ArrayItems>
<Size>count</Size>
<ValuePointer>data</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<Type Name="lbProcedure">
<DisplayString>Procedure {name}</DisplayString>
</Type>
</AutoVisualizer>
+26 -48
View File
@@ -2324,11 +2324,7 @@ Ast *parse_operand(AstFile *f, bool lhs) {
body = convert_stmt_to_body(f, parse_stmt(f));
f->curr_proc = curr_proc;
if (build_context.disallow_do) {
syntax_error(body, "'do' has been disallowed");
} else if (!ast_on_same_line(type, body)) {
syntax_error(body, "The body of a 'do' must be on the same line as the signature");
}
syntax_error(body, "'do' for procedure bodies is not allowed, prefer {}");
return ast_proc_lit(f, type, body, tags, where_token, where_clauses);
}
@@ -2552,21 +2548,15 @@ Ast *parse_operand(AstFile *f, bool lhs) {
syntax_error(tag, "Invalid union tag '#%.*s'", LIT(tag.string));
}
}
if (no_nil && maybe) {
syntax_error(f->curr_token, "#maybe and #no_nil cannot be applied together");
}
if (no_nil && shared_nil) {
syntax_error(f->curr_token, "#shared_nil and #no_nil cannot be applied together");
}
if (shared_nil && maybe) {
syntax_error(f->curr_token, "#maybe and #shared_nil cannot be applied together");
}
if (maybe) {
union_kind = UnionType_maybe;
syntax_error(f->curr_token, "#maybe functionality has now been merged with standard 'union' functionality");
} else if (no_nil) {
}
if (no_nil) {
union_kind = UnionType_no_nil;
} else if (shared_nil) {
union_kind = UnionType_shared_nil;
@@ -3554,47 +3544,34 @@ Ast *parse_var_type(AstFile *f, bool allow_ellipsis, bool allow_typeid_token) {
}
enum FieldPrefixKind : i32 {
FieldPrefix_Unknown = -1,
FieldPrefix_Invalid = 0,
FieldPrefix_using, // implies #subtype
FieldPrefix_const,
FieldPrefix_no_alias,
FieldPrefix_c_vararg,
FieldPrefix_auto_cast,
FieldPrefix_any_int,
FieldPrefix_subtype, // does not imply `using` semantics
};
struct ParseFieldPrefixMapping {
String name;
TokenKind token_kind;
FieldPrefixKind prefix;
FieldFlag flag;
};
gb_global ParseFieldPrefixMapping parse_field_prefix_mappings[] = {
{str_lit("using"), Token_using, FieldPrefix_using, FieldFlag_using},
{str_lit("auto_cast"), Token_auto_cast, FieldPrefix_auto_cast, FieldFlag_auto_cast},
{str_lit("no_alias"), Token_Hash, FieldPrefix_no_alias, FieldFlag_no_alias},
{str_lit("c_vararg"), Token_Hash, FieldPrefix_c_vararg, FieldFlag_c_vararg},
{str_lit("const"), Token_Hash, FieldPrefix_const, FieldFlag_const},
{str_lit("any_int"), Token_Hash, FieldPrefix_any_int, FieldFlag_any_int},
{str_lit("subtype"), Token_Hash, FieldPrefix_subtype, FieldFlag_subtype},
{str_lit("using"), Token_using, FieldFlag_using},
{str_lit("auto_cast"), Token_auto_cast, FieldFlag_auto_cast},
{str_lit("no_alias"), Token_Hash, FieldFlag_no_alias},
{str_lit("c_vararg"), Token_Hash, FieldFlag_c_vararg},
{str_lit("const"), Token_Hash, FieldFlag_const},
{str_lit("any_int"), Token_Hash, FieldFlag_any_int},
{str_lit("subtype"), Token_Hash, FieldFlag_subtype},
{str_lit("by_ptr"), Token_Hash, FieldFlag_by_ptr},
};
FieldPrefixKind is_token_field_prefix(AstFile *f) {
FieldFlag is_token_field_prefix(AstFile *f) {
switch (f->curr_token.kind) {
case Token_EOF:
return FieldPrefix_Invalid;
return FieldFlag_Invalid;
case Token_using:
return FieldPrefix_using;
return FieldFlag_using;
case Token_auto_cast:
return FieldPrefix_auto_cast;
return FieldFlag_auto_cast;
case Token_Hash:
advance_token(f);
@@ -3604,33 +3581,33 @@ FieldPrefixKind is_token_field_prefix(AstFile *f) {
auto const &mapping = parse_field_prefix_mappings[i];
if (mapping.token_kind == Token_Hash) {
if (f->curr_token.string == mapping.name) {
return mapping.prefix;
return mapping.flag;
}
}
}
break;
}
return FieldPrefix_Unknown;
return FieldFlag_Unknown;
}
return FieldPrefix_Invalid;
return FieldFlag_Invalid;
}
u32 parse_field_prefixes(AstFile *f) {
i32 counts[gb_count_of(parse_field_prefix_mappings)] = {};
for (;;) {
FieldPrefixKind kind = is_token_field_prefix(f);
if (kind == FieldPrefix_Invalid) {
FieldFlag flag = is_token_field_prefix(f);
if (flag & FieldFlag_Invalid) {
break;
}
if (kind == FieldPrefix_Unknown) {
if (flag & FieldFlag_Unknown) {
syntax_error(f->curr_token, "Unknown prefix kind '#%.*s'", LIT(f->curr_token.string));
advance_token(f);
continue;
}
for (i32 i = 0; i < gb_count_of(parse_field_prefix_mappings); i++) {
if (parse_field_prefix_mappings[i].prefix == kind) {
if (parse_field_prefix_mappings[i].flag == flag) {
counts[i] += 1;
advance_token(f);
break;
@@ -3896,7 +3873,8 @@ Ast *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKi
while (f->curr_token.kind != follow &&
f->curr_token.kind != Token_EOF) {
f->curr_token.kind != Token_EOF &&
f->curr_token.kind != Token_Semicolon) {
CommentGroup *docs = f->lead_comment;
u32 set_flags = parse_field_prefixes(f);
Token tag = {};
@@ -3924,7 +3902,7 @@ Ast *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKi
default_value = parse_expr(f, false);
if (!allow_default_parameters) {
syntax_error(f->curr_token, "Default parameters are only allowed for procedures");
default_value = nullptr;
default_value = nullptr;
}
}
+9 -3
View File
@@ -282,6 +282,8 @@ enum StateFlag : u8 {
StateFlag_type_assert = 1<<2,
StateFlag_no_type_assert = 1<<3,
StateFlag_SelectorCallExpr = 1<<6,
StateFlag_BeenHandled = 1<<7,
};
@@ -300,13 +302,18 @@ enum FieldFlag : u32 {
FieldFlag_const = 1<<5,
FieldFlag_any_int = 1<<6,
FieldFlag_subtype = 1<<7,
FieldFlag_by_ptr = 1<<8,
// Internal use by the parser only
FieldFlag_Tags = 1<<10,
FieldFlag_Results = 1<<16,
FieldFlag_Unknown = 1u<<30,
FieldFlag_Invalid = 1u<<31,
// Parameter List Restrictions
FieldFlag_Signature = FieldFlag_ellipsis|FieldFlag_using|FieldFlag_no_alias|FieldFlag_c_vararg|FieldFlag_auto_cast|FieldFlag_const|FieldFlag_any_int,
FieldFlag_Signature = FieldFlag_ellipsis|FieldFlag_using|FieldFlag_no_alias|FieldFlag_c_vararg|FieldFlag_auto_cast|FieldFlag_const|FieldFlag_any_int|FieldFlag_by_ptr,
FieldFlag_Struct = FieldFlag_using|FieldFlag_subtype|FieldFlag_Tags,
};
@@ -332,7 +339,6 @@ char const *inline_asm_dialect_strings[InlineAsmDialect_COUNT] = {
enum UnionTypeKind : u8 {
UnionType_Normal = 0,
UnionType_maybe = 1, // removed
UnionType_no_nil = 2,
UnionType_shared_nil = 3,
};
@@ -411,7 +417,7 @@ AST_KIND(_ExprBegin, "", bool) \
Token ellipsis; \
ProcInlining inlining; \
bool optional_ok_one; \
void *sce_temp_data; \
bool was_selector; \
}) \
AST_KIND(FieldValue, "field value", struct { Token eq; Ast *field, *value; }) \
AST_KIND(EnumFieldValue, "enum field value", struct { \
@@ -79,8 +79,8 @@ test_leb128 :: proc(t: ^testing.T) {
}
}
for num_bytes in 1..uint(16) {
for _ in 0..RANDOM_TESTS {
for num_bytes in 1..=uint(16) {
for _ in 0..=RANDOM_TESTS {
unsigned, signed := get_random(num_bytes)
{
@@ -109,7 +109,7 @@ test_leb128 :: proc(t: ^testing.T) {
get_random :: proc(byte_count: uint) -> (u: u128, i: i128) {
assert(byte_count >= 0 && byte_count <= size_of(u128))
for _ in 1..byte_count {
for _ in 1..=byte_count {
u <<= 8
u |= u128(rand.uint32() & 0xff)
}
+1 -1
View File
@@ -281,7 +281,7 @@ doc_to_string :: proc(doc: ^xml.Document) -> (result: string) {
}
buf: strings.Builder
defer strings.destroy_builder(&buf)
defer strings.builder_destroy(&buf)
print(strings.to_writer(&buf), doc)
return strings.clone(strings.to_string(buf))
+1
View File
@@ -5,6 +5,7 @@ package odin_gl
import "core:os"
import "core:fmt"
import "core:strings"
_ :: fmt
Shader_Type :: enum i32 {
NONE = 0x0000,
+44
View File
@@ -947,6 +947,13 @@ impl_DrawTransformFeedbackStream: proc "c" (mode: u32, id: u32, stream: u32)
impl_BeginQueryIndexed: proc "c" (target: u32, index: u32, id: u32)
impl_EndQueryIndexed: proc "c" (target: u32, index: u32)
impl_GetQueryIndexediv: proc "c" (target: u32, index: u32, pname: u32, params: [^]i32)
impl_GetTextureHandleARB: proc "c" (texture: u32) -> u64
impl_GetTextureSamplerHandleARB: proc "c" (texture, sampler: u32) -> u64
impl_GetImageHandleARB: proc "c" (texture: u32, level: i32, layered: bool, layer: i32, format: u32) -> u64
impl_MakeTextureHandleResidentARB: proc "c" (handle: u64)
impl_MakeImageHandleResidentARB: proc "c" (handle: u64, access: u32)
impl_MakeTextureHandleNonResidentARB:proc "c" (handle: u64)
impl_MakeImageHandleNonResidentARB: proc "c" (handle: u64)
load_4_0 :: proc(set_proc_address: Set_Proc_Address_Type) {
set_proc_address(&impl_MinSampleShading, "glMinSampleShading")
@@ -995,6 +1002,42 @@ load_4_0 :: proc(set_proc_address: Set_Proc_Address_Type) {
set_proc_address(&impl_BeginQueryIndexed, "glBeginQueryIndexed")
set_proc_address(&impl_EndQueryIndexed, "glEndQueryIndexed")
set_proc_address(&impl_GetQueryIndexediv, "glGetQueryIndexediv")
// Load ARB (architecture review board, vendor specific) extensions that might be available
set_proc_address(&impl_GetTextureHandleARB, "glGetTextureHandleARB")
if impl_GetTextureHandleARB == nil {
set_proc_address(&impl_GetTextureHandleARB, "glGetTextureHandleNV")
}
set_proc_address(&impl_GetTextureSamplerHandleARB, "glGetTextureSamplerHandleARB")
if impl_GetTextureSamplerHandleARB == nil {
set_proc_address(&impl_GetTextureSamplerHandleARB, "glGetTextureSamplerHandleNV")
}
set_proc_address(&impl_GetImageHandleARB, "glGetImageHandleARB")
if impl_GetImageHandleARB == nil {
set_proc_address(&impl_GetImageHandleARB, "glGetImageHandleNV")
}
set_proc_address(&impl_MakeTextureHandleResidentARB, "glMakeTextureHandleResidentARB")
if impl_MakeTextureHandleResidentARB == nil {
set_proc_address(&impl_MakeTextureHandleResidentARB, "glMakeTextureHandleResidentNV")
}
set_proc_address(&impl_MakeImageHandleResidentARB, "glMakeImageHandleResidentARB")
if impl_MakeImageHandleResidentARB == nil {
set_proc_address(&impl_MakeImageHandleResidentARB, "glMakeImageHandleResidentNV")
}
set_proc_address(&impl_MakeTextureHandleNonResidentARB, "glMakeTextureHandleNonResidentARB")
if impl_MakeTextureHandleNonResidentARB == nil {
set_proc_address(&impl_MakeTextureHandleNonResidentARB, "glMakeTextureHandleNonResidentNV")
}
set_proc_address(&impl_MakeImageHandleNonResidentARB, "glMakeImageHandleNonResidentARB")
if impl_MakeImageHandleNonResidentARB == nil {
set_proc_address(&impl_MakeImageHandleNonResidentARB, "glMakeImageHandleNonResidentNV")
}
}
@@ -1594,3 +1637,4 @@ load_4_6 :: proc(set_proc_address: Set_Proc_Address_Type) {
set_proc_address(&impl_MultiDrawElementsIndirectCount, "glMultiDrawElementsIndirectCount")
set_proc_address(&impl_PolygonOffsetClamp, "glPolygonOffsetClamp")
}
+30
View File
@@ -449,6 +449,20 @@ when !ODIN_DEBUG {
BeginQueryIndexed :: proc "c" (target: u32, index: u32, id: u32) { impl_BeginQueryIndexed(target, index, id) }
EndQueryIndexed :: proc "c" (target: u32, index: u32) { impl_EndQueryIndexed(target, index) }
GetQueryIndexediv :: proc "c" (target: u32, index: u32, pname: u32, params: [^]i32) { impl_GetQueryIndexediv(target, index, pname, params) }
GetTextureHandleARB :: proc "c" (texture: u32) -> u64
{ return impl_GetTextureHandleARB(texture) }
GetTextureSamplerHandleARB :: proc "c" (texture, sampler: u32) -> u64
{ return impl_GetTextureSamplerHandleARB(texture, sampler) }
GetImageHandleARB :: proc "c" (texture: u32, level: i32, layered: bool, layer: i32, format: u32) -> u64
{ return impl_GetImageHandleARB(texture, level, layered, layer, format) }
MakeTextureHandleResidentARB :: proc "c" (handle: u64)
{ impl_MakeTextureHandleResidentARB(handle) }
MakeImageHandleResidentARB :: proc "c" (handle: u64, access: u32)
{ impl_MakeImageHandleResidentARB(handle, access) }
MakeTextureHandleNonResidentARB:: proc "c" (handle: u64)
{ impl_MakeTextureHandleNonResidentARB(handle) }
MakeImageHandleNonResidentARB :: proc "c" (handle: u64)
{ impl_MakeImageHandleNonResidentARB(handle) }
// VERSION_4_1
ReleaseShaderCompiler :: proc "c" () { impl_ReleaseShaderCompiler() }
@@ -1249,6 +1263,22 @@ when !ODIN_DEBUG {
BeginQueryIndexed :: proc "c" (target: u32, index: u32, id: u32, loc := #caller_location) { impl_BeginQueryIndexed(target, index, id); debug_helper(loc, 0, target, index, id) }
EndQueryIndexed :: proc "c" (target: u32, index: u32, loc := #caller_location) { impl_EndQueryIndexed(target, index); debug_helper(loc, 0, target, index) }
GetQueryIndexediv :: proc "c" (target: u32, index: u32, pname: u32, params: [^]i32, loc := #caller_location) { impl_GetQueryIndexediv(target, index, pname, params); debug_helper(loc, 0, target, index, pname, params) }
GetTextureHandleARB :: proc "c" (target: u32, loc := #caller_location) -> u64
{ ret := impl_GetTextureHandleARB(target); debug_helper(loc, 0, target); return ret }
GetTextureSamplerHandleARB :: proc "c" (texture, sampler: u32, loc := #caller_location) -> u64
{ ret := impl_GetTextureSamplerHandleARB(texture, sampler); debug_helper(loc, 0, texture, sampler); return ret }
GetImageHandleARB :: proc "c" (texture: u32, level: i32, layered: bool, layer: i32, format: u32, loc := #caller_location) -> u64
{ ret := impl_GetImageHandleARB(texture, level, layered, layer, format); debug_helper(loc, 0, texture, level, layered, layer, format); return ret }
MakeTextureHandleResidentARB :: proc "c" (handle: u64, loc := #caller_location)
{ impl_MakeTextureHandleResidentARB(handle); debug_helper(loc, 0, handle) }
MakeImageHandleResidentARB :: proc "c" (handle: u64, access: u32, loc := #caller_location)
{ impl_MakeImageHandleResidentARB(handle, access); debug_helper(loc, 0, handle, access) }
MakeTextureHandleNonResidentARB:: proc "c" (handle: u64, loc := #caller_location)
{ impl_MakeTextureHandleNonResidentARB(handle); debug_helper(loc, 0, handle) }
MakeImageHandleNonResidentARB :: proc "c" (handle: u64, loc := #caller_location)
{ impl_MakeImageHandleNonResidentARB(handle); debug_helper(loc, 0, handle) }
// VERSION_4_1
ReleaseShaderCompiler :: proc "c" (loc := #caller_location) { impl_ReleaseShaderCompiler(); debug_helper(loc, 0) }
+4 -4
View File
@@ -38,10 +38,10 @@ IUnknown_VTable :: struct {
@(default_calling_convention="stdcall")
foreign dxgi {
CreateDXGIFactory :: proc(riid: ^IID, ppFactory: rawptr) -> HRESULT ---
CreateDXGIFactory1 :: proc(riid: ^IID, ppFactory: rawptr) -> HRESULT ---
CreateDXGIFactory2 :: proc(Flags: u32, riid: ^IID, ppFactory: rawptr) -> HRESULT ---
DXGIGetDebugInterface1 :: proc(Flags: u32, riid: ^IID, pDebug: rawptr) -> HRESULT ---
CreateDXGIFactory :: proc(riid: ^IID, ppFactory: ^rawptr) -> HRESULT ---
CreateDXGIFactory1 :: proc(riid: ^IID, ppFactory: ^rawptr) -> HRESULT ---
CreateDXGIFactory2 :: proc(Flags: u32, riid: ^IID, ppFactory: ^rawptr) -> HRESULT ---
DXGIGetDebugInterface1 :: proc(Flags: u32, riid: ^IID, pDebug: ^rawptr) -> HRESULT ---
}
STANDARD_MULTISAMPLE_QUALITY_PATTERN :: 0xffffffff
+7
View File
@@ -13,6 +13,13 @@ when ODIN_OS == .Windows {
} else when ODIN_OS == .Linux {
// TODO: Add the billion-or-so static libs to link to in linux
foreign import glfw "system:glfw"
} else when ODIN_OS == .Darwin {
foreign import glfw {
"../lib/darwin/libglfw3.a",
"system:Cocoa.framework",
"system:IOKit.framework",
"system:OpenGL.framework",
}
} else {
foreign import glfw "system:glfw"
}
+1 -1
View File
@@ -4,7 +4,7 @@ package glfw
/* Versions */
VERSION_MAJOR :: 3
VERSION_MINOR :: 3
VERSION_REVISION :: 4
VERSION_REVISION :: 8
/* Booleans */
TRUE :: true
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -353,7 +353,7 @@ end :: proc(ctx: ^Context) {
/* reset input state */
ctx.key_pressed_bits = {} // clear
strings.reset_builder(&ctx.text_input)
strings.builder_reset(&ctx.text_input)
ctx.mouse_pressed_bits = {} // clear
ctx.mouse_released_bits = {} // clear
ctx.scroll_delta = Vec2{0, 0}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+14 -5
View File
@@ -106,11 +106,20 @@ when ODIN_OS == .Windows {
"system:pthread",
}
} else when ODIN_OS == .Darwin {
foreign import lib {
"macos/libraylib.a",
"system:Cocoa.framework",
"system:OpenGL.framework",
"system:IOKit.framework",
when ODIN_ARCH == .arm64 {
foreign import lib {
"macos-arm64/libraylib.a",
"system:Cocoa.framework",
"system:OpenGL.framework",
"system:IOKit.framework",
}
} else {
foreign import lib {
"macos/libraylib.a",
"system:Cocoa.framework",
"system:OpenGL.framework",
"system:IOKit.framework",
}
}
} else {
foreign import lib "system:raylib"
+1 -1
View File
@@ -185,4 +185,4 @@ foreign lib {
space: colorspace, alloc_context: rawptr,
s0, t0, s1, t1: f32) -> c.int ---
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+2 -2
View File
@@ -10,6 +10,6 @@ The `js_wasm32` target assumes that the WASM output will be ran within a web bro
<!-- Copy `vendor:wasm/js/runtime.js` into your web server -->
<script type="text/javascript" src="runtime.js"></script>
<script type="text/javascript">
odin.runWasm(pathToWasm, webglCanvasElement, consolePreElement);
odin.runWasm(pathToWasm, consolePreElement);
</script>
```
```
+30 -3
View File
@@ -79,6 +79,8 @@ Event_Kind :: enum u32 {
Context_Menu,
Custom,
}
event_kind_string := [Event_Kind]string{
.Invalid = "",
@@ -155,6 +157,8 @@ event_kind_string := [Event_Kind]string{
.Touch_Start = "touchstart",
.Context_Menu = "contextmenu",
.Custom = "?custom?",
}
Delta_Mode :: enum u32 {
@@ -186,6 +190,13 @@ Event_Phase :: enum u8 {
Bubbling_Phase = 3,
}
Event_Option :: enum u8 {
Bubbles = 0,
Cancelable = 1,
Composed = 2,
}
Event_Options :: distinct bit_set[Event_Option; u8]
Event :: struct {
kind: Event_Kind,
target_kind: Event_Target_Kind,
@@ -194,9 +205,7 @@ Event :: struct {
timestamp: f64,
phase: Event_Phase,
bubbles: bool,
cancelable: bool,
composed: bool,
options: Event_Options,
is_composing: bool,
is_trusted: bool,
@@ -255,6 +264,7 @@ foreign dom_lib {
event_stop_propagation :: proc() ---
event_stop_immediate_propagation :: proc() ---
event_prevent_default :: proc() ---
dispatch_custom_event :: proc(id: string, name: string, options := Event_Options{}) -> bool ---
}
add_event_listener :: proc(id: string, kind: Event_Kind, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool {
@@ -301,6 +311,23 @@ remove_event_listener_from_event :: proc(e: Event) -> bool {
return remove_event_listener(e.id, e.kind, e.user_data, e.callback)
}
add_custom_event_listener :: proc(id: string, name: string, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool {
@(default_calling_convention="contextless")
foreign dom_lib {
@(link_name="add_event_listener")
_add_event_listener :: proc(id: string, name: string, name_code: Event_Kind, user_data: rawptr, callback: proc "odin" (Event), use_capture: bool) -> bool ---
}
return _add_event_listener(id, name, .Custom, user_data, callback, use_capture)
}
remove_custom_event_listener :: proc(id: string, name: string, user_data: rawptr, callback: proc(e: Event)) -> bool {
@(default_calling_convention="contextless")
foreign dom_lib {
@(link_name="remove_event_listener")
_remove_event_listener :: proc(id: string, name: string, user_data: rawptr, callback: proc "odin" (Event)) -> bool ---
}
return _remove_event_listener(id, name, user_data, callback)
}
+41 -14
View File
@@ -1,6 +1,14 @@
"use strict";
(function() {
function getElement(name) {
if (name) {
return document.getElementById(name);
}
return undefined;
}
class WasmMemoryInterface {
constructor() {
this.memory = null;
@@ -204,12 +212,12 @@ class WebGLInterface {
return {
SetCurrentContextById: (name_ptr, name_len) => {
let name = this.mem.loadString(name_ptr, name_len);
let element = document.getElementById(name);
let element = getElement(name);
return this.setCurrentContext(element, {alpha: true, antialias: true, depth: true, premultipliedAlpha: true});
},
CreateCurrentContextById: (name_ptr, name_len, attributes) => {
let name = this.mem.loadString(name_ptr, name_len);
let element = document.getElementById(name);
let element = getElement(name);
let contextSettings = {
alpha: !(attributes & (1<<0)),
@@ -1380,9 +1388,11 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
wmi.storeF64(off(8), e.timeStamp*1e-3);
wmi.storeU8(off(1), e.eventPhase);
wmi.storeU8(off(1), !!e.bubbles);
wmi.storeU8(off(1), !!e.cancelable);
wmi.storeU8(off(1), !!e.composed);
let options = 0;
if (!!e.bubbles) { options |= 1<<0; }
if (!!e.cancelable) { options |= 1<<1; }
if (!!e.composed) { options |= 1<<2; }
wmi.storeU8(off(1), options);
wmi.storeU8(off(1), !!e.isComposing);
wmi.storeU8(off(1), !!e.isTrusted);
@@ -1433,7 +1443,7 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
add_event_listener: (id_ptr, id_len, name_ptr, name_len, name_code, data, callback, use_capture) => {
let id = wasmMemoryInterface.loadString(id_ptr, id_len);
let name = wasmMemoryInterface.loadString(name_ptr, name_len);
let element = document.getElementById(id);
let element = getElement(id);
if (element == undefined) {
return false;
}
@@ -1454,7 +1464,7 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
remove_event_listener: (id_ptr, id_len, name_ptr, name_len, data, callback) => {
let id = wasmMemoryInterface.loadString(id_ptr, id_len);
let name = wasmMemoryInterface.loadString(name_ptr, name_len);
let element = document.getElementById(id);
let element = getElement(id);
if (element == undefined) {
return false;
}
@@ -1514,14 +1524,31 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
}
},
dispatch_custom_event: (id_ptr, id_len, name_ptr, name_len, options_bits) => {
let id = wasmMemoryInterface.loadString(id_ptr, id_len);
let name = wasmMemoryInterface.loadString(name_ptr, name_len);
let options = {
bubbles: (options_bits & (1<<0)) !== 0,
cancelabe: (options_bits & (1<<1)) !== 0,
composed: (options_bits & (1<<2)) !== 0,
};
let element = getElement(id);
if (element) {
element.dispatchEvent(new Event(name, options));
return true;
}
return false;
},
get_element_value_f64: (id_ptr, id_len) => {
let id = wasmMemoryInterface.loadString(id_ptr, id_len);
let element = document.getElementById(id);
let element = getElement(id);
return element ? element.value : 0;
},
get_element_value_string: (id_ptr, id_len, buf_ptr, buf_len) => {
let id = wasmMemoryInterface.loadString(id_ptr, id_len);
let element = document.getElementById(id);
let element = getElement(id);
if (element) {
let str = element.value;
if (buf_len > 0 && buf_ptr) {
@@ -1535,7 +1562,7 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
},
get_element_value_string_length: (id_ptr, id_len) => {
let id = wasmMemoryInterface.loadString(id_ptr, id_len);
let element = document.getElementById(id);
let element = getElement(id);
if (element) {
return element.value.length;
}
@@ -1543,7 +1570,7 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
},
get_element_min_max: (ptr_array2_f64, id_ptr, id_len) => {
let id = wasmMemoryInterface.loadString(id_ptr, id_len);
let element = document.getElementById(id);
let element = getElement(id);
if (element) {
let values = wasmMemoryInterface.loadF64Array(ptr_array2_f64, 2);
values[0] = element.min;
@@ -1552,7 +1579,7 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
},
set_element_value_f64: (id_ptr, id_len, value) => {
let id = wasmMemoryInterface.loadString(id_ptr, id_len);
let element = document.getElementById(id);
let element = getElement(id);
if (element) {
element.value = value;
}
@@ -1560,7 +1587,7 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
set_element_value_string: (id_ptr, id_len, value_ptr, value_id) => {
let id = wasmMemoryInterface.loadString(id_ptr, id_len);
let value = wasmMemoryInterface.loadString(value_ptr, value_len);
let element = document.getElementById(id);
let element = getElement(id);
if (element) {
element.value = value;
}
@@ -1569,7 +1596,7 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
get_bounding_client_rect: (rect_ptr, id_ptr, id_len) => {
let id = wasmMemoryInterface.loadString(id_ptr, id_len);
let element = document.getElementById(id);
let element = getElement(id);
if (element) {
let values = wasmMemoryInterface.loadF64Array(rect_ptr, 4);
let rect = element.getBoundingClientRect();