mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Compare commits
118 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5961bcaf86 | ||
|
|
fd5489458a | ||
|
|
cf5dd5496a | ||
|
|
ccffa03de2 | ||
|
|
ce0ab62c78 | ||
|
|
0bc5cbca74 | ||
|
|
a2aa9fae6b | ||
|
|
9d79c3f33d | ||
|
|
a26055c932 | ||
|
|
b296875c05 | ||
|
|
a54658d37f | ||
|
|
0a0e097bdf | ||
|
|
2df51bfe07 | ||
|
|
cb065152ea | ||
|
|
07fa14f00b | ||
|
|
ff1b17d18b | ||
|
|
c3d5778ae0 | ||
|
|
373ad1a399 | ||
|
|
6deed2d4a4 | ||
|
|
6324d78c32 | ||
|
|
9e14338b77 | ||
|
|
6e4614b6a4 | ||
|
|
0b52819090 | ||
|
|
404a78943d | ||
|
|
7215a9fa12 | ||
|
|
463c6957fc | ||
|
|
8ec3a52ef7 | ||
|
|
ab1efdda73 | ||
|
|
4f3b6f922d | ||
|
|
869a1d93cb | ||
|
|
5d468ccbf0 | ||
|
|
887ed5b9e9 | ||
|
|
5c1a6d7623 | ||
|
|
1b49ebf855 | ||
|
|
98155b61f1 | ||
|
|
60cdea5292 | ||
|
|
49e836b1ab | ||
|
|
5b83108dd1 | ||
|
|
a50de26c5d | ||
|
|
7b50c87858 | ||
|
|
a816a78e98 | ||
|
|
39694e65c0 | ||
|
|
2a41fa6281 | ||
|
|
49b8cfe267 | ||
|
|
20dfdf5c5d | ||
|
|
1e543dc286 | ||
|
|
06884720e5 | ||
|
|
1ea181524e | ||
|
|
b16ee3119d | ||
|
|
4e66693065 | ||
|
|
5f96b8e4c6 | ||
|
|
748a2f6530 | ||
|
|
6360ddbc77 | ||
|
|
eccc6700dc | ||
|
|
52ececba37 | ||
|
|
ffc65bcbf4 | ||
|
|
0da6bf4455 | ||
|
|
7063e684ba | ||
|
|
07363c6ecd | ||
|
|
5070840da9 | ||
|
|
4a25bcc5ee | ||
|
|
d43d7100af | ||
|
|
791cbbfb62 | ||
|
|
9b05dfdef1 | ||
|
|
b072e88bb3 | ||
|
|
af33d2b1cc | ||
|
|
d438d7510e | ||
|
|
1673aef74f | ||
|
|
b3bce10699 | ||
|
|
3ff922e12b | ||
|
|
3b718335ec | ||
|
|
f25ad512a7 | ||
|
|
5a3c484ceb | ||
|
|
331a77c1c2 | ||
|
|
045053f6bf | ||
|
|
4809979898 | ||
|
|
a5b2636b2e | ||
|
|
c483c3b75f | ||
|
|
c10d449e43 | ||
|
|
54b110a367 | ||
|
|
ee8dc3d681 | ||
|
|
a38a627a1d | ||
|
|
8aaf54e8b1 | ||
|
|
423152202f | ||
|
|
f37e7460aa | ||
|
|
8f5d5a0bb5 | ||
|
|
883052a6bb | ||
|
|
9cf271f5fb | ||
|
|
5d8cad91b1 | ||
|
|
614c6989d8 | ||
|
|
03ad72afbb | ||
|
|
b924ede71a | ||
|
|
a81f857d8c | ||
|
|
6169d7acdf | ||
|
|
4af31da7ea | ||
|
|
0bd2c81757 | ||
|
|
5ed1281451 | ||
|
|
7b649314ec | ||
|
|
e37343fbe3 | ||
|
|
7b02907830 | ||
|
|
6eee760239 | ||
|
|
ae33d1a206 | ||
|
|
3430240c2a | ||
|
|
6f11260a5c | ||
|
|
df67b7dddd | ||
|
|
f3b7df2ab0 | ||
|
|
a000ae560a | ||
|
|
0d85caf21c | ||
|
|
e34a26422f | ||
|
|
fe70f10bcc | ||
|
|
d6be1cbf65 | ||
|
|
04cd079d4e | ||
|
|
b4b14674b4 | ||
|
|
5a1831c989 | ||
|
|
e9ec421b3b | ||
|
|
872f63eecc | ||
|
|
1eb8c0ced1 | ||
|
|
b5ae2485a7 |
206
.github/workflows/main.yml
vendored
206
.github/workflows/main.yml
vendored
@@ -12,6 +12,7 @@ env:
|
||||
LLVM_RELEASE_VERSION_LINUX: 19
|
||||
LLVM_RELEASE_VERSION_OPENBSD: 19
|
||||
LLVM_RELEASE_VERSION_UBUNTU22: 19
|
||||
LLVM_RELEASE_VERSION_ALPINEv3_22: 20
|
||||
LLVM_DEV_VERSION: 22
|
||||
jobs:
|
||||
|
||||
@@ -78,15 +79,15 @@ jobs:
|
||||
|
||||
- name: Vendor-fetch
|
||||
run: |
|
||||
build\${{ matrix.build_type }}\c3c.exe vendor-fetch raylib55
|
||||
build\${{ matrix.build_type }}\c3c.exe vendor-fetch raylib
|
||||
|
||||
- name: Try raylib5
|
||||
run: |
|
||||
cd resources
|
||||
..\build\${{ matrix.build_type }}\c3c.exe vendor-fetch raylib55
|
||||
..\build\${{ matrix.build_type }}\c3c.exe compile --lib raylib55 --print-linking examples\raylib\raylib_arkanoid.c3
|
||||
..\build\${{ matrix.build_type }}\c3c.exe compile --lib raylib55 --print-linking examples\raylib\raylib_snake.c3
|
||||
..\build\${{ matrix.build_type }}\c3c.exe compile --lib raylib55 --print-linking examples\raylib\raylib_tetris.c3
|
||||
..\build\${{ matrix.build_type }}\c3c.exe vendor-fetch raylib
|
||||
..\build\${{ matrix.build_type }}\c3c.exe compile --lib raylib --print-linking examples\raylib\raylib_arkanoid.c3
|
||||
..\build\${{ matrix.build_type }}\c3c.exe compile --lib raylib --print-linking examples\raylib\raylib_snake.c3
|
||||
..\build\${{ matrix.build_type }}\c3c.exe compile --lib raylib --print-linking examples\raylib\raylib_tetris.c3
|
||||
|
||||
- name: run compiler tests
|
||||
run: |
|
||||
@@ -159,7 +160,7 @@ jobs:
|
||||
|
||||
- name: Vendor-fetch
|
||||
run: |
|
||||
./build/c3c vendor-fetch raylib55
|
||||
./build/c3c vendor-fetch raylib
|
||||
|
||||
- name: Build testproject lib
|
||||
run: |
|
||||
@@ -384,7 +385,7 @@ jobs:
|
||||
|
||||
- name: Vendor-fetch
|
||||
run: |
|
||||
./build/c3c vendor-fetch raylib55
|
||||
./build/c3c vendor-fetch raylib
|
||||
|
||||
- name: run compiler tests
|
||||
run: |
|
||||
@@ -409,6 +410,187 @@ jobs:
|
||||
name: c3-linux-${{matrix.build_type}}
|
||||
path: c3-linux-${{matrix.build_type}}.tar.gz
|
||||
|
||||
build-linux-alpine:
|
||||
runs-on: ubuntu-22.04
|
||||
container:
|
||||
image: alpine:3.22
|
||||
strategy:
|
||||
# Don't abort runners if a single one fails
|
||||
fail-fast: false
|
||||
matrix:
|
||||
build_type: [Release, Debug]
|
||||
llvm_version: [18, 19, 20]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install common deps
|
||||
run: |
|
||||
apk update
|
||||
apk add zlib-dev zlib-static python3 samurai cmake curl-dev curl-static openssl-dev
|
||||
|
||||
- name: Install Clang ${{matrix.llvm_version}}
|
||||
run: |
|
||||
apk add "llvm${{matrix.llvm_version}}-dev" "llvm${{matrix.llvm_version}}-static" \
|
||||
"llvm${{matrix.llvm_version}}-gtest" "llvm${{matrix.llvm_version}}-linker-tools" \
|
||||
"llvm${{matrix.llvm_version}}-test-utils" "llvm${{matrix.llvm_version}}-test-utils-pyc" \
|
||||
"lld${{matrix.llvm_version}}-dev" "clang${{matrix.llvm_version}}-dev" \
|
||||
"clang${{matrix.llvm_version}}-extra-tools" "clang${{matrix.llvm_version}}-static"
|
||||
- name: CMake
|
||||
if: matrix.llvm_version == env.LLVM_DEV_VERSION
|
||||
run: |
|
||||
cmake -B build \
|
||||
-G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=${{matrix.build_type}}" \
|
||||
-DCMAKE_C_COMPILER=clang-${{matrix.llvm_version}} \
|
||||
-DCMAKE_CXX_COMPILER=clang++-${{matrix.llvm_version}} \
|
||||
-DCMAKE_LINKER=lld-link-${{matrix.llvm_version}} \
|
||||
-DCMAKE_OBJCOPY=llvm-objcopy-${{matrix.llvm_version}} \
|
||||
-DCMAKE_STRIP=llvm-strip-${{matrix.llvm_version}} \
|
||||
-DCMAKE_DLLTOOL=llvm-dlltool-${{matrix.llvm_version}} \
|
||||
-DLLVM_ENABLE_LIBXML2=OFF \
|
||||
-DC3_LINK_DYNAMIC=ON \
|
||||
-DC3_LLVM_VERSION=${{matrix.llvm_version}}
|
||||
cmake --build build
|
||||
- name: CMake_Stable
|
||||
if: matrix.llvm_version >= 18 && matrix.llvm_version != env.LLVM_DEV_VERSION
|
||||
run: |
|
||||
cmake -B build \
|
||||
-G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=${{matrix.build_type}} \
|
||||
-DCMAKE_C_COMPILER=clang-${{matrix.llvm_version}} \
|
||||
-DCMAKE_CXX_COMPILER=clang++-${{matrix.llvm_version}} \
|
||||
-DCMAKE_LINKER=lld-link-${{matrix.llvm_version}} \
|
||||
-DCMAKE_OBJCOPY=llvm-objcopy-${{matrix.llvm_version}} \
|
||||
-DCMAKE_STRIP=llvm-strip-${{matrix.llvm_version}} \
|
||||
-DCMAKE_DLLTOOL=llvm-dlltool-${{matrix.llvm_version}} \
|
||||
-DLLVM_ENABLE_LIBXML2=OFF \
|
||||
-DC3_LINK_DYNAMIC=ON \
|
||||
-DC3_LLVM_VERSION=${{matrix.llvm_version}}.1
|
||||
cmake --build build
|
||||
|
||||
- name: Compile and run some examples
|
||||
run: |
|
||||
export C3C="$(realpath ./build/c3c)"
|
||||
cd resources
|
||||
"$C3C" compile examples/base64.c3
|
||||
"$C3C" compile examples/binarydigits.c3
|
||||
"$C3C" compile examples/brainfk.c3
|
||||
"$C3C" compile examples/factorial_macro.c3
|
||||
"$C3C" compile examples/fasta.c3
|
||||
"$C3C" compile examples/gameoflife.c3
|
||||
"$C3C" compile examples/hash.c3
|
||||
"$C3C" compile-only examples/levenshtein.c3
|
||||
"$C3C" compile examples/load_world.c3
|
||||
"$C3C" compile-only examples/map.c3
|
||||
"$C3C" compile examples/mandelbrot.c3
|
||||
"$C3C" compile examples/plus_minus.c3
|
||||
"$C3C" compile examples/nbodies.c3
|
||||
"$C3C" compile examples/spectralnorm.c3
|
||||
"$C3C" compile examples/swap.c3
|
||||
"$C3C" compile examples/contextfree/boolerr.c3
|
||||
"$C3C" compile examples/contextfree/dynscope.c3
|
||||
"$C3C" compile examples/contextfree/guess_number.c3
|
||||
"$C3C" compile examples/contextfree/multi.c3
|
||||
"$C3C" compile examples/contextfree/cleanup.c3
|
||||
"$C3C" compile-run examples/hello_world_many.c3
|
||||
"$C3C" compile-run examples/time.c3
|
||||
"$C3C" compile-run examples/fannkuch-redux.c3
|
||||
"$C3C" compile-run examples/contextfree/boolerr.c3
|
||||
"$C3C" compile-run examples/load_world.c3
|
||||
"$C3C" compile-run examples/process.c3
|
||||
"$C3C" compile-run examples/ls.c3
|
||||
# "$C3C" compile-run --linker=builtin linux_stack.c3 # Program will hang due to incorrect linking to `/lib64/ld-linux-x86-64.so.2` instead of `/lib/ld-musl-x86_64.so.1`
|
||||
"$C3C" compile-run linux_stack.c3
|
||||
"$C3C" compile-run examples/args.c3 -- foo -bar "baz baz"
|
||||
|
||||
- name: Compile and run dynlib-test
|
||||
run: |
|
||||
export C3C="$(realpath ./build/c3c)"
|
||||
cd resources/examples/dynlib-test
|
||||
"$C3C" -vv dynamic-lib add.c3
|
||||
mv add.so libadd.so
|
||||
cc test.c -L. -ladd -Wl,-rpath=.
|
||||
./a.out
|
||||
"$C3C" compile-run test.c3 -L . -l add -z -Wl,-rpath=.
|
||||
|
||||
- name: Compile and run staticlib-test
|
||||
run: |
|
||||
export C3C="$(realpath ./build/c3c)"
|
||||
cd resources/examples/staticlib-test
|
||||
"$C3C" -vv static-lib add.c3
|
||||
mv add.a libadd.a
|
||||
cc test.c -L. -ladd
|
||||
./a.out
|
||||
"$C3C" compile-run test.c3 -L . -l add
|
||||
|
||||
- name: Compile run unit tests
|
||||
run: |
|
||||
export C3C="$(realpath ./build/c3c)"
|
||||
cd test
|
||||
"$C3C" compile-test unit -D SLOW_TESTS
|
||||
|
||||
- name: Build testproject
|
||||
run: |
|
||||
export C3C="$(realpath ./build/c3c)"
|
||||
cd resources/testproject
|
||||
"$C3C" run -vvv --trust=full
|
||||
|
||||
- name: Test WASM
|
||||
run: |
|
||||
export C3C="$(realpath ./build/c3c)"
|
||||
cd resources/testfragments
|
||||
"$C3C" compile --target wasm32 -g0 --no-entry -Os wasm4.c3
|
||||
|
||||
- name: Install QEMU and Risc-V toolchain
|
||||
run: |
|
||||
apk add qemu-dev qemu-system-riscv32 gcc-riscv-none-elf make
|
||||
|
||||
- name: Compile and run Baremetal Risc-V Example
|
||||
run: |
|
||||
cd resources/examples/embedded/riscv-qemu
|
||||
make C3C_PATH=../../../../build/ run
|
||||
|
||||
- name: Build testproject direct linker
|
||||
run: |
|
||||
export C3C="$(realpath ./build/c3c)"
|
||||
cd resources/testproject
|
||||
"$C3C" run -vvv --linker=builtin --trust=full --linux-libc=musl
|
||||
|
||||
- name: Init a library & a project
|
||||
run: |
|
||||
./build/c3c init-lib mylib
|
||||
ls mylib.c3l
|
||||
./build/c3c init myproject
|
||||
ls myproject
|
||||
|
||||
- name: Vendor-fetch
|
||||
run: |
|
||||
"$(realpath ./build/c3c)" vendor-fetch raylib55
|
||||
|
||||
- name: run compiler tests
|
||||
run: |
|
||||
export C3C="$(realpath ./build/c3c)"
|
||||
cd test
|
||||
"$C3C" compile-run -O1 src/test_suite_runner.c3 -- ../build/c3c test_suite/
|
||||
|
||||
- name: bundle_output
|
||||
if: matrix.llvm_version == env.LLVM_RELEASE_VERSION_ALPINEv3_22
|
||||
run: |
|
||||
mkdir c3
|
||||
cp -r lib c3
|
||||
cp msvc_build_libraries.py c3
|
||||
cp build/c3c c3
|
||||
cp README.md c3
|
||||
cp releasenotes.md c3
|
||||
tar -czf c3-musl-${{matrix.build_type}}.tar.gz c3
|
||||
|
||||
- name: upload artifacts
|
||||
if: matrix.llvm_version == env.LLVM_RELEASE_VERSION_ALPINEv3_22
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: c3-musl-${{matrix.build_type}}
|
||||
path: c3-musl-${{matrix.build_type}}.tar.gz
|
||||
|
||||
build-linux-ubuntu22:
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
@@ -515,7 +697,7 @@ jobs:
|
||||
|
||||
- name: Vendor-fetch
|
||||
run: |
|
||||
./build/c3c vendor-fetch raylib55
|
||||
./build/c3c vendor-fetch raylib
|
||||
|
||||
- name: run compiler tests
|
||||
run: |
|
||||
@@ -658,7 +840,7 @@ jobs:
|
||||
|
||||
- name: Vendor-fetch
|
||||
run: |
|
||||
./build/c3c vendor-fetch raylib55
|
||||
./build/c3c vendor-fetch raylib
|
||||
|
||||
- name: Compile and run some examples
|
||||
run: |
|
||||
@@ -777,7 +959,7 @@ jobs:
|
||||
uses: vmactions/openbsd-vm@main
|
||||
with:
|
||||
prepare: |
|
||||
pkg_add cmake llvm-19.1.7p3 ninja
|
||||
pkg_add cmake llvm-20.1.8p1 ninja
|
||||
|
||||
run: |
|
||||
echo "CMake"
|
||||
@@ -904,7 +1086,7 @@ jobs:
|
||||
- run: mv c3-ubuntu-22-Debug/c3-ubuntu-22-Debug.tar.gz c3-ubuntu-22-Debug/c3-ubuntu-22-debug.tar.gz
|
||||
- run: mv c3-macos-Release/c3-macos-Release.zip c3-macos-Release/c3-macos.zip
|
||||
- run: mv c3-macos-Debug/c3-macos-Debug.zip c3-macos-Debug/c3-macos-debug.zip
|
||||
- run: gh release delete latest-prerelease --cleanup-tag -y || true
|
||||
- run: gh release delete latest-prerelease-tag --cleanup-tag -y || true
|
||||
- run: echo "RELEASE_NAME=latest-prerelease-$(date +'%Y%m%d-%H%M')" >> $GITHUB_ENV
|
||||
|
||||
- id: create_release
|
||||
@@ -912,7 +1094,7 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: latest-prerelease
|
||||
tag_name: latest-prerelease-tag
|
||||
name: ${{ env.RELEASE_NAME }}
|
||||
draft: false
|
||||
prerelease: true
|
||||
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -92,3 +92,8 @@ result
|
||||
/test/tmp/*
|
||||
/test/testrun
|
||||
/test/test_suite_runner
|
||||
|
||||
# patches, originals and rejects
|
||||
*.patch
|
||||
*.rej
|
||||
*.orig
|
||||
|
||||
@@ -65,8 +65,8 @@ if(MSVC)
|
||||
else()
|
||||
add_compile_options(-gdwarf-3 -fno-exceptions)
|
||||
|
||||
# add_compile_options(-fsanitize=address,undefined)
|
||||
# add_link_options(-fsanitize=address,undefined)
|
||||
#add_compile_options(-fsanitize=address,undefined)
|
||||
#add_link_options(-fsanitize=address,undefined)
|
||||
endif()
|
||||
|
||||
# Options
|
||||
|
||||
38
README.md
38
README.md
@@ -8,11 +8,11 @@ for programmers who like C.
|
||||
|
||||
Precompiled binaries for the following operating systems are available:
|
||||
|
||||
- Windows x64 [download](https://github.com/c3lang/c3c/releases/download/latest-prerelease/c3-windows.zip), [install instructions](#installing-on-windows-with-precompiled-binaries).
|
||||
- Debian x64 [download](https://github.com/c3lang/c3c/releases/download/latest-prerelease/c3-linux.tar.gz), [install instructions](#installing-on-debian-with-precompiled-binaries).
|
||||
- Ubuntu x86 [download](https://github.com/c3lang/c3c/releases/download/latest-prerelease/c3-ubuntu-20.tar.gz), [install instructions](#installing-on-ubuntu-with-precompiled-binaries).
|
||||
- MacOS Arm64 [download](https://github.com/c3lang/c3c/releases/download/latest-prerelease/c3-macos.zip), [install instructions](#installing-on-macos-with-precompiled-binaries).
|
||||
- OpenBSD x64 [download](https://github.com/c3lang/c3c/releases/download/latest-prerelease/c3-openbsd.tar.gz), [install instructions](#installing-on-openbsd-with-precompiled-binaries).
|
||||
- Windows x64 [download](https://github.com/c3lang/c3c/releases/download/latest-prerelease-tag/c3-windows.zip), [install instructions](#installing-on-windows-with-precompiled-binaries).
|
||||
- Debian x64 [download](https://github.com/c3lang/c3c/releases/download/latest-prerelease-tag/c3-linux.tar.gz), [install instructions](#installing-on-debian-with-precompiled-binaries).
|
||||
- Ubuntu x86 [download](https://github.com/c3lang/c3c/releases/download/latest-prerelease-tag/c3-ubuntu-20.tar.gz), [install instructions](#installing-on-ubuntu-with-precompiled-binaries).
|
||||
- MacOS Arm64 [download](https://github.com/c3lang/c3c/releases/download/latest-prerelease-tag/c3-macos.zip), [install instructions](#installing-on-macos-with-precompiled-binaries).
|
||||
- OpenBSD x64 [download](https://github.com/c3lang/c3c/releases/download/latest-prerelease-tag/c3-openbsd.tar.gz), [install instructions](#installing-on-openbsd-with-precompiled-binaries).
|
||||
|
||||
The manual for C3 can be found at [www.c3-lang.org](http://www.c3-lang.org).
|
||||
|
||||
@@ -142,7 +142,7 @@ fn void main()
|
||||
|
||||
### Current status
|
||||
|
||||
The current stable version of the compiler is **version 0.7.6**.
|
||||
The current stable version of the compiler is **version 0.7.8**.
|
||||
|
||||
The upcoming 0.7.x releases will focus on expanding the standard library,
|
||||
fixing bugs and improving compile time analysis.
|
||||
@@ -151,7 +151,7 @@ Follow the issues [here](https://github.com/c3lang/c3c/issues).
|
||||
If you have suggestions on how to improve the language, either [file an issue](https://github.com/c3lang/c3c/issues)
|
||||
or discuss C3 on its dedicated Discord: [https://discord.gg/qN76R87](https://discord.gg/qN76R87).
|
||||
|
||||
The compiler is currently verified to compile on Linux, Windows and MacOS.
|
||||
The compiler is currently verified to compile on Linux, OpenBSD, Windows and MacOS.
|
||||
|
||||
**Support matrix**
|
||||
|
||||
@@ -172,6 +172,7 @@ The compiler is currently verified to compile on Linux, Windows and MacOS.
|
||||
| ELF freestanding Aarch64 | No | Untested | No | No | No | Yes* |
|
||||
| ELF freestanding Riscv64 | No | Untested | No | No | No | Untested |
|
||||
| ELF freestanding Riscv32 | No | Untested | No | No | No | Untested |
|
||||
| ELF freestanding Xtensa* | No | Untested | No | No | No | Untested |
|
||||
| FreeBSD x86 | Untested | Untested | No | Yes | Untested | Yes* |
|
||||
| FreeBSD x64 | Untested | Untested | No | Yes | Untested | Yes* |
|
||||
| NetBSD x86 | Untested | Untested | No | Yes | Untested | Yes* |
|
||||
@@ -184,7 +185,8 @@ The compiler is currently verified to compile on Linux, Windows and MacOS.
|
||||
|
||||
*\* Inline asm is still a work in progress*<br>
|
||||
*\* OpenBSD 7.7 is the only tested version*<br>
|
||||
*\* OpenBSD has limited stacktrace, needs to be tested further*
|
||||
*\* OpenBSD has limited stacktrace, needs to be tested further*<br>
|
||||
*\* Xtensa support is enabled by compiling with `-DXTENSA_ENABLE`. The [espressif llvm fork](https://github.com/espressif/llvm-project) is recommended for best compatibility*
|
||||
|
||||
More platforms will be supported in the future.
|
||||
|
||||
@@ -203,8 +205,8 @@ More platforms will be supported in the future.
|
||||
This installs the latest prerelease build, as opposed to the latest released version.
|
||||
|
||||
#### Installing on Windows with precompiled binaries
|
||||
1. Download the zip file: [https://github.com/c3lang/c3c/releases/download/latest-prerelease/c3-windows.zip](https://github.com/c3lang/c3c/releases/download/latest-prerelease/c3-windows.zip)
|
||||
(debug version [here](https://github.com/c3lang/c3c/releases/download/latest-prerelease/c3-windows-debug.zip))
|
||||
1. Download the zip file: [https://github.com/c3lang/c3c/releases/download/latest-prerelease-tag/c3-windows.zip](https://github.com/c3lang/c3c/releases/download/latest-prerelease-tag/c3-windows.zip)
|
||||
(debug version [here](https://github.com/c3lang/c3c/releases/download/latest-prerelease-tag/c3-windows-debug.zip))
|
||||
2. Unzip exe and standard lib.
|
||||
3. If you don't have Visual Studio 17 installed you can either do so, or run the `msvc_build_libraries.py` Python script which will download the necessary files to compile on Windows.
|
||||
4. Run `c3c.exe`.
|
||||
@@ -227,8 +229,8 @@ If you don't have Visual Studio 17 installed you can either do so, or run the `m
|
||||
|
||||
|
||||
#### Installing on Debian with precompiled binaries
|
||||
1. Download tar file: [https://github.com/c3lang/c3c/releases/download/latest-prerelease/c3-linux.tar.gz](https://github.com/c3lang/c3c/releases/download/latest-prerelease/c3-linux.tar.gz)
|
||||
(debug version [here](https://github.com/c3lang/c3c/releases/download/latest-prerelease/c3-linux-debug.tar.gz))
|
||||
1. Download tar file: [https://github.com/c3lang/c3c/releases/download/latest-prerelease-tag/c3-linux.tar.gz](https://github.com/c3lang/c3c/releases/download/latest-prerelease-tag/c3-linux.tar.gz)
|
||||
(debug version [here](https://github.com/c3lang/c3c/releases/download/latest-prerelease-tag/c3-linux-debug.tar.gz))
|
||||
2. Unpack executable and standard lib.
|
||||
3. Run `./c3c`.
|
||||
|
||||
@@ -247,23 +249,23 @@ curl -fsSL https://raw.githubusercontent.com/c3lang/c3c/refs/heads/master/instal
|
||||
```
|
||||
|
||||
#### Installing on Ubuntu with precompiled binaries
|
||||
1. Download tar file: [https://github.com/c3lang/c3c/releases/download/latest-prerelease/c3-ubuntu-20.tar.gz](https://github.com/c3lang/c3c/releases/download/latest-prerelease/c3-ubuntu-20.tar.gz)
|
||||
(debug version [here](https://github.com/c3lang/c3c/releases/download/latest-prerelease/c3-ubuntu-20-debug.tar.gz))
|
||||
1. Download tar file: [https://github.com/c3lang/c3c/releases/download/latest-prerelease-tag/c3-ubuntu-20.tar.gz](https://github.com/c3lang/c3c/releases/download/latest-prerelease-tag/c3-ubuntu-20.tar.gz)
|
||||
(debug version [here](https://github.com/c3lang/c3c/releases/download/latest-prerelease-tag/c3-ubuntu-20-debug.tar.gz))
|
||||
2. Unpack executable and standard lib.
|
||||
3. Run `./c3c`.
|
||||
|
||||
#### Installing on MacOS with precompiled binaries
|
||||
1. Make sure you have XCode with command line tools installed.
|
||||
2. Download the zip file: [https://github.com/c3lang/c3c/releases/download/latest-prerelease/c3-macos.zip](https://github.com/c3lang/c3c/releases/download/latest-prerelease/c3-macos.zip)
|
||||
(debug version [here](https://github.com/c3lang/c3c/releases/download/latest-prerelease/c3-macos-debug.zip))
|
||||
2. Download the zip file: [https://github.com/c3lang/c3c/releases/download/latest-prerelease-tag/c3-macos.zip](https://github.com/c3lang/c3c/releases/download/latest-prerelease-tag/c3-macos.zip)
|
||||
(debug version [here](https://github.com/c3lang/c3c/releases/download/latest-prerelease-tag/c3-macos-debug.zip))
|
||||
3. Unzip executable and standard lib.
|
||||
4. Run `./c3c`.
|
||||
|
||||
(*Note that there is a known issue with debug symbol generation on MacOS 13, see [issue #1086](https://github.com/c3lang/c3c/issues/1086))
|
||||
|
||||
#### Installing on OpenBSD with precompiled binaries
|
||||
1. Download tar file: [https://github.com/c3lang/c3c/releases/download/latest-prerelease/c3-openbsd.tar.gz](https://github.com/c3lang/c3c/releases/download/latest-prerelease/c3-openbsd.tar.gz)
|
||||
(debug version [here](https://github.com/c3lang/c3c/releases/download/latest-prerelease/c3-openbsd-debug.tar.gz))
|
||||
1. Download tar file: [https://github.com/c3lang/c3c/releases/download/latest-prerelease-tag/c3-openbsd.tar.gz](https://github.com/c3lang/c3c/releases/download/latest-prerelease-tag/c3-openbsd.tar.gz)
|
||||
(debug version [here](https://github.com/c3lang/c3c/releases/download/latest-prerelease-tag/c3-openbsd-debug.tar.gz))
|
||||
2. Unpack executable and standard lib.
|
||||
3. Run `./c3c`.
|
||||
|
||||
|
||||
@@ -21,11 +21,11 @@ fn void bench_ctr_xcrypt() @benchmark
|
||||
Aes ctx;
|
||||
|
||||
// encrypt
|
||||
ctx.init_with_iv(aes, CTR, key, iv);
|
||||
ctx.init(aes, key, iv);
|
||||
ctx.encrypt_buffer(text, &out);
|
||||
|
||||
// decrypt
|
||||
ctx.init_with_iv(aes, CTR, key, iv);
|
||||
ctx.init(aes, key, iv);
|
||||
ctx.decrypt_buffer(cipher, &out);
|
||||
}
|
||||
|
||||
|
||||
@@ -532,7 +532,8 @@ fn bool List.remove_first_item(&self, Type value) @if(ELEMENT_IS_EQUATABLE)
|
||||
fn usz List.remove_item(&self, Type value) @if(ELEMENT_IS_EQUATABLE)
|
||||
{
|
||||
usz old_size = self.size;
|
||||
defer {
|
||||
defer
|
||||
{
|
||||
if (old_size != self.size) self._update_size_change(old_size, self.size);
|
||||
}
|
||||
return list_common::list_remove_item(self, value);
|
||||
|
||||
@@ -135,11 +135,14 @@ macro bool @typeis(#value, $Type) @const @builtin @deprecated("Use `$typeof(#val
|
||||
}
|
||||
|
||||
|
||||
fn bool print_backtrace(String message, int backtraces_to_ignore) @if (env::NATIVE_STACKTRACE) => @stack_mem(0x1100; Allocator smem)
|
||||
fn bool print_backtrace(String message, int backtraces_to_ignore, void *added_backtrace = null) @if (env::NATIVE_STACKTRACE) => @stack_mem(0x1100; Allocator smem)
|
||||
{
|
||||
void*[256] buffer;
|
||||
void*[] backtraces = backtrace::capture_current(&buffer);
|
||||
backtraces_to_ignore++;
|
||||
if (added_backtrace)
|
||||
{
|
||||
backtraces[++backtraces_to_ignore] = added_backtrace;
|
||||
}
|
||||
@stack_mem(2048; Allocator mem)
|
||||
{
|
||||
BacktraceList? backtrace = backtrace::symbolize_backtrace(mem, backtraces);
|
||||
@@ -500,7 +503,7 @@ macro void? @try(#v, #expr) @builtin @maydiscard
|
||||
{
|
||||
char[] data;
|
||||
// Read until end of file
|
||||
if (@try_catch(data, load_line(), io::EOF)) break;
|
||||
if (@try_catch(data, load_line(), io::EOF)!) break;
|
||||
.. use data ..
|
||||
}
|
||||
|
||||
@@ -547,6 +550,27 @@ macro isz @str_find(String $string, String $needle) @builtin => $$str_find($stri
|
||||
macro String @str_upper(String $str) @builtin => $$str_upper($str);
|
||||
macro String @str_lower(String $str) @builtin => $$str_lower($str);
|
||||
macro uint @str_hash(String $str) @builtin => $$str_hash($str);
|
||||
macro String @str_pascalcase(String $str) @builtin => $$str_pascalcase($str);
|
||||
macro String @str_snakecase(String $str) @builtin => $$str_snakecase($str);
|
||||
macro String @str_camelcase(String $str) @builtin => @str_capitalize($$str_pascalcase($str));
|
||||
macro String @str_constantcase(String $str) @builtin => @str_upper($$str_snakecase($str));
|
||||
macro String @str_replace(String $str, String $pattern, String $replace, uint $limit = 0) @builtin => $$str_replace($str, $pattern, $replace, $limit);
|
||||
macro String @str_capitalize(String $str) @builtin
|
||||
{
|
||||
$switch $str.len:
|
||||
$case 0: return $str;
|
||||
$case 1: return $$str_upper($str);
|
||||
$default: return $$str_upper($str[0:1]) +++ $str[1..];
|
||||
$endswitch
|
||||
}
|
||||
macro String @str_uncapitalize(String $str) @builtin
|
||||
{
|
||||
$switch $str.len:
|
||||
$case 0: return $str;
|
||||
$case 1: return $$str_lower($str);
|
||||
$default: return $$str_lower($str[0:1]) +++ $str[1..];
|
||||
$endswitch
|
||||
}
|
||||
|
||||
macro @generic_hash_core(h, value)
|
||||
{
|
||||
@@ -920,23 +944,20 @@ macro void* get_returnaddress(int n)
|
||||
}
|
||||
|
||||
module std::core::builtin @if((env::LINUX || env::ANDROID || env::DARWIN) && env::COMPILER_SAFE_MODE && env::DEBUG_SYMBOLS);
|
||||
import libc, std::io;
|
||||
import libc, std::io, std::os::posix;
|
||||
|
||||
fn void sig_panic(String message)
|
||||
{
|
||||
default_panic(message, "???", "???", 0);
|
||||
}
|
||||
|
||||
SignalFunction old_bus_error;
|
||||
SignalFunction old_segmentation_fault;
|
||||
|
||||
fn void sig_bus_error(CInt i)
|
||||
fn void sig_bus_error(CInt i, void* info, void* context)
|
||||
{
|
||||
$if !env::NATIVE_STACKTRACE:
|
||||
sig_panic("Illegal memory access.");
|
||||
$else
|
||||
$if $defined(io::stderr):
|
||||
if (!print_backtrace("Illegal memory access.", 1))
|
||||
if (!print_backtrace("Illegal memory access.", 2, posix::stack_instruction(context)))
|
||||
{
|
||||
io::eprintn("\nERROR: 'Illegal memory access'.");
|
||||
}
|
||||
@@ -945,13 +966,13 @@ fn void sig_bus_error(CInt i)
|
||||
$$trap();
|
||||
}
|
||||
|
||||
fn void sig_segmentation_fault(CInt i)
|
||||
fn void sig_segmentation_fault(CInt i, void* p1, void* context)
|
||||
{
|
||||
$if !env::NATIVE_STACKTRACE:
|
||||
sig_panic("Out of bounds memory access.");
|
||||
$else
|
||||
$if $defined(io::stderr):
|
||||
if (!print_backtrace("Out of bounds memory access.", 1))
|
||||
if (!print_backtrace("Out of bounds memory access.", 2, posix::stack_instruction(context)))
|
||||
{
|
||||
io::eprintn("\nERROR: Memory error without backtrace, possible stack overflow.");
|
||||
}
|
||||
@@ -960,17 +981,12 @@ fn void sig_segmentation_fault(CInt i)
|
||||
$$trap();
|
||||
}
|
||||
|
||||
fn void install_signal_handler(CInt signal, SignalFunction func) @local
|
||||
{
|
||||
SignalFunction old = libc::signal(signal, func);
|
||||
// Restore
|
||||
if ((iptr)old > 1024) libc::signal(signal, old);
|
||||
}
|
||||
|
||||
|
||||
// Clean this up
|
||||
fn void install_signal_handlers() @init(101) @local @if(env::BACKTRACE)
|
||||
{
|
||||
install_signal_handler(libc::SIGBUS, &sig_bus_error);
|
||||
install_signal_handler(libc::SIGSEGV, &sig_segmentation_fault);
|
||||
posix::install_signal_handler(libc::SIGBUS, &sig_bus_error);
|
||||
posix::install_signal_handler(libc::SIGSEGV, &sig_segmentation_fault);
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ macro int @main_to_void_main_args(#m, int argc, char** argv)
|
||||
|
||||
module std::core::main_stub @if(env::WIN32);
|
||||
|
||||
extern fn Char16** _win_command_line_to_argv_w(ushort* cmd_line, int* argc_ptr) @extern("CommandLineToArgvW");
|
||||
extern fn Char16** _win_command_line_to_argv_w(ushort* cmd_line, int* argc_ptr) @cname("CommandLineToArgvW");
|
||||
|
||||
macro String[] win_command_line_to_strings(ushort* cmd_line) @private
|
||||
{
|
||||
|
||||
@@ -42,7 +42,7 @@ macro @enum_lookup_new($Type, $name, value)
|
||||
module std::core::runtime @if(env::FREESTANDING_WASM);
|
||||
|
||||
extern fn void __wasm_call_ctors();
|
||||
fn void wasm_initialize() @extern("_initialize") @wasm
|
||||
fn void wasm_initialize() @cname("_initialize") @wasm
|
||||
{
|
||||
// The linker synthesizes this to call constructors.
|
||||
__wasm_call_ctors();
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
module std::core::runtime;
|
||||
import std::core::test @public;
|
||||
import std::core::mem::allocator @public;
|
||||
import libc, std::time, std::io, std::sort;
|
||||
import std::os::env;
|
||||
import libc, std::time, std::io, std::sort, std::os;
|
||||
|
||||
|
||||
alias TestFn = fn void();
|
||||
|
||||
@@ -18,6 +18,8 @@ struct TestContext
|
||||
String test_filter;
|
||||
<* Triggers debugger breakpoint when assert or test:: checks failed *>
|
||||
bool breakpoint_on_assert;
|
||||
<* Controls level of printed logs *>
|
||||
LogPriority log_level;
|
||||
|
||||
// internal state
|
||||
bool assert_print_backtrace;
|
||||
@@ -86,7 +88,21 @@ fn bool terminal_has_ansi_codes() @local => @pool()
|
||||
$endif
|
||||
}
|
||||
|
||||
fn void sig_bus_error(CInt i, void*, void* context) @local @if(env::POSIX)
|
||||
{
|
||||
panic_test("Bus error", "Unknown", "Unknown", 1, posix::stack_instruction(context));
|
||||
}
|
||||
|
||||
fn void sig_segmentation_fault(CInt i, void*, void* context) @local @if(env::POSIX)
|
||||
{
|
||||
panic_test("Segmentation fault", "Unknown", "Unknown", 1, posix::stack_instruction(context));
|
||||
}
|
||||
|
||||
fn void test_panic(String message, String file, String function, uint line) @local
|
||||
{
|
||||
panic_test(message, file, function, line);
|
||||
}
|
||||
fn void panic_test(String message, String file, String function, uint line, void* extra_trace = null) @local
|
||||
{
|
||||
if (test_context.is_in_panic) return;
|
||||
test_context.is_in_panic = true;
|
||||
@@ -96,7 +112,7 @@ fn void test_panic(String message, String file, String function, uint line) @loc
|
||||
if (test_context.assert_print_backtrace)
|
||||
{
|
||||
$if env::NATIVE_STACKTRACE:
|
||||
builtin::print_backtrace(message, 0);
|
||||
builtin::print_backtrace(message, extra_trace ? 3 : 0, extra_trace);
|
||||
$endif
|
||||
}
|
||||
io::printf("\nTest failed ^^^ ( %s:%s ) %s\n", file, line, message);
|
||||
@@ -165,6 +181,7 @@ fn void unmute_output(bool has_error) @local
|
||||
(void)stdout.flush();
|
||||
}
|
||||
|
||||
|
||||
fn bool run_tests(String[] args, TestUnit[] tests) @private
|
||||
{
|
||||
usz max_name;
|
||||
@@ -175,6 +192,10 @@ fn bool run_tests(String[] args, TestUnit[] tests) @private
|
||||
io::printn("There are no test units to run.");
|
||||
return true; // no tests == technically a pass
|
||||
}
|
||||
$if !env::NO_LIBC && env::POSIX:
|
||||
posix::install_signal_handler(libc::SIGBUS, &sig_bus_error);
|
||||
posix::install_signal_handler(libc::SIGSEGV, &sig_segmentation_fault);
|
||||
$endif
|
||||
foreach (&unit : tests)
|
||||
{
|
||||
if (max_name < unit.name.len) max_name = unit.name.len;
|
||||
@@ -183,6 +204,7 @@ fn bool run_tests(String[] args, TestUnit[] tests) @private
|
||||
{
|
||||
.assert_print_backtrace = true,
|
||||
.breakpoint_on_assert = false,
|
||||
.log_level = LogPriority.ERROR,
|
||||
.test_filter = "",
|
||||
.has_ansi_codes = terminal_has_ansi_codes(),
|
||||
.stored.allocator = mem,
|
||||
@@ -200,6 +222,7 @@ fn bool run_tests(String[] args, TestUnit[] tests) @private
|
||||
case "--test-noleak":
|
||||
check_leaks = false;
|
||||
case "--test-nocapture":
|
||||
case "--test-show-output":
|
||||
context.is_no_capture = true;
|
||||
case "--noansi":
|
||||
context.has_ansi_codes = false;
|
||||
@@ -215,11 +238,28 @@ fn bool run_tests(String[] args, TestUnit[] tests) @private
|
||||
}
|
||||
context.test_filter = args[i + 1];
|
||||
i++;
|
||||
case "--test-log-level":
|
||||
if (i == args.len - 1)
|
||||
{
|
||||
io::printn("Missing log level for argument `--test-log-level`.");
|
||||
return false;
|
||||
}
|
||||
@pool()
|
||||
{
|
||||
String upper = args[i + 1].to_upper_copy(tmem);
|
||||
if (catch @try(context.log_level, enum_by_name(LogPriority, upper)))
|
||||
{
|
||||
io::printn("Log level given to `--test-log-level` is not one of verbose, debug, info, warn, error or critical.");
|
||||
return false;
|
||||
}
|
||||
};
|
||||
i++;
|
||||
default:
|
||||
io::printfn("Unknown argument: %s", args[i]);
|
||||
}
|
||||
}
|
||||
test_context = &context;
|
||||
log::set_priority_all(test_context.log_level);
|
||||
|
||||
if (sort_tests)
|
||||
{
|
||||
|
||||
@@ -70,7 +70,7 @@ macro WString @wstring(String $string) @builtin
|
||||
}
|
||||
|
||||
<*
|
||||
Create a slice of an UTF32 encoded string at compile time.
|
||||
Create a slice of an UTF16 encoded string at compile time.
|
||||
|
||||
@param $string : "The string to encode"
|
||||
*>
|
||||
@@ -1067,14 +1067,10 @@ macro String.to_integer(self, $Type, int base = 10)
|
||||
{
|
||||
if (is_negative)
|
||||
{
|
||||
$Type new_value = value * base_used - c;
|
||||
if (new_value > value) return INTEGER_OVERFLOW?;
|
||||
value = new_value;
|
||||
value = value.overflow_mul(base_used).overflow_sub(c) ?? INTEGER_OVERFLOW?!;
|
||||
break;
|
||||
}
|
||||
$Type new_value = value * base_used + c;
|
||||
if (new_value < value) return INTEGER_OVERFLOW?;
|
||||
value = new_value;
|
||||
value = value.overflow_mul(base_used).overflow_add(c) ?? INTEGER_OVERFLOW?!;
|
||||
};
|
||||
}
|
||||
return value;
|
||||
|
||||
@@ -26,6 +26,7 @@ fn void? test_div() @test
|
||||
test::le(2, 3);
|
||||
test::eq_approx(m::divide(1, 3)!, 0.333, places: 3);
|
||||
test::@check(2 == 2, "divide: %d", divide(6, 3)!);
|
||||
test::@error(m::divide(3, 0));
|
||||
test::@error(m::divide(3, 0), MathError.DIVISION_BY_ZERO);
|
||||
}
|
||||
|
||||
@@ -78,14 +79,15 @@ macro @check(#condition, String format = "", args...)
|
||||
}
|
||||
|
||||
<*
|
||||
Check if function returns specific error
|
||||
Check if function returns (specific) error
|
||||
|
||||
@param #funcresult : `result of function execution`
|
||||
@param error_expected : `expected error of function execution`
|
||||
@require runtime::test_context != null : "Only allowed in @test functions"
|
||||
*>
|
||||
macro @error(#funcresult, fault error_expected)
|
||||
macro @error(#funcresult, fault error_expected = ...)
|
||||
{
|
||||
$if $defined(error_expected):
|
||||
if (catch err = #funcresult)
|
||||
{
|
||||
if (err != error_expected)
|
||||
@@ -96,6 +98,10 @@ macro @error(#funcresult, fault error_expected)
|
||||
return;
|
||||
}
|
||||
print_panicf("`%s` error [%s] was not returned.", $stringify(#funcresult), error_expected);
|
||||
$else
|
||||
if (catch err = #funcresult) return;
|
||||
print_panicf("`%s` unexpectedly did not return error.", $stringify(#funcresult));
|
||||
$endif
|
||||
}
|
||||
|
||||
<*
|
||||
|
||||
@@ -141,8 +141,6 @@ fn usz? Formatter.out_str(&self, any arg) @private
|
||||
{
|
||||
switch (arg.type.kindof)
|
||||
{
|
||||
case TYPEID:
|
||||
return self.out_substr("typeid");
|
||||
case VOID:
|
||||
return self.out_substr("void");
|
||||
case FAULT:
|
||||
@@ -188,6 +186,8 @@ fn usz? Formatter.out_str(&self, any arg) @private
|
||||
if (@catch(n) != NOT_FOUND) n!;
|
||||
switch (arg.type.kindof)
|
||||
{
|
||||
case TYPEID:
|
||||
return self.out_substr("typeid[")! + self.ntoa((iptr)*(typeid*)arg, false, 16)! + self.out_substr("]")!;
|
||||
case ENUM:
|
||||
usz i = types::any_to_enum_ordinal(arg, usz)!!;
|
||||
assert(i < arg.type.names.len, "Illegal enum value found, numerical value was %d.", i);
|
||||
|
||||
@@ -526,6 +526,19 @@ fn usz? Formatter.floatformat(&self, FloatFormatting formatting, double y) @priv
|
||||
return len;
|
||||
}
|
||||
|
||||
const char[201] DIGIT_PAIRS @private =
|
||||
"00102030405060708090"
|
||||
"01112131415161718191"
|
||||
"02122232425262728292"
|
||||
"03132333435363738393"
|
||||
"04142434445464748494"
|
||||
"05152535455565758595"
|
||||
"06162636465666768696"
|
||||
"07172737475767778797"
|
||||
"08182838485868788898"
|
||||
"09192939495969798999";
|
||||
|
||||
|
||||
fn usz? Formatter.ntoa(&self, uint128 value, bool negative, uint base) @private
|
||||
{
|
||||
char[PRINTF_NTOA_BUFFER_SIZE] buf @noinit;
|
||||
@@ -538,14 +551,56 @@ fn usz? Formatter.ntoa(&self, uint128 value, bool negative, uint base) @private
|
||||
if (!self.flags.precision || value)
|
||||
{
|
||||
char past_10 = (self.flags.uppercase ? 'A' : 'a') - 10;
|
||||
do
|
||||
switch (base)
|
||||
{
|
||||
if (len >= PRINTF_NTOA_BUFFER_SIZE) return INTERNAL_BUFFER_EXCEEDED?;
|
||||
char digit = (char)(value % base);
|
||||
buf[len++] = digit + (digit < 10 ? '0' : past_10);
|
||||
value /= base;
|
||||
case 2:
|
||||
do
|
||||
{
|
||||
if (len >= PRINTF_NTOA_BUFFER_SIZE) return INTERNAL_BUFFER_EXCEEDED?;
|
||||
buf[len++] = '0' + (char)value & 1;
|
||||
value >>= 1;
|
||||
}
|
||||
while (value);
|
||||
case 10:
|
||||
if (!value)
|
||||
{
|
||||
if (len >= PRINTF_NTOA_BUFFER_SIZE) return INTERNAL_BUFFER_EXCEEDED?;
|
||||
buf[len++] = '0';
|
||||
break;
|
||||
}
|
||||
while (value >= 10)
|
||||
{
|
||||
if (len + 1 >= PRINTF_NTOA_BUFFER_SIZE) return INTERNAL_BUFFER_EXCEEDED?;
|
||||
char digit = (char)(value % 100);
|
||||
buf[len:2] = DIGIT_PAIRS[2 * digit:2];
|
||||
len += 2;
|
||||
value /= 100;
|
||||
}
|
||||
if (value > 0)
|
||||
{
|
||||
if (len >= PRINTF_NTOA_BUFFER_SIZE) return INTERNAL_BUFFER_EXCEEDED?;
|
||||
buf[len++] = '0' + (char)value;
|
||||
}
|
||||
case 16:
|
||||
do
|
||||
{
|
||||
if (len >= PRINTF_NTOA_BUFFER_SIZE) return INTERNAL_BUFFER_EXCEEDED?;
|
||||
char digit = (char)value & 0xF;
|
||||
buf[len++] = digit + (digit < 10 ? '0' : past_10);
|
||||
value >>= 4;
|
||||
}
|
||||
while (value);
|
||||
case 8:
|
||||
do
|
||||
{
|
||||
if (len >= PRINTF_NTOA_BUFFER_SIZE) return INTERNAL_BUFFER_EXCEEDED?;
|
||||
buf[len++] = '0' + (char)value & 0x7;
|
||||
value >>= 3;
|
||||
}
|
||||
while (value);
|
||||
default:
|
||||
unreachable();
|
||||
}
|
||||
while (value);
|
||||
}
|
||||
return self.ntoa_format((String)buf[:PRINTF_NTOA_BUFFER_SIZE], len, negative, base);
|
||||
}
|
||||
|
||||
@@ -267,7 +267,32 @@ fn void? out_putstream_fn(void* data, char c) @private
|
||||
return (*stream).write_byte(c);
|
||||
}
|
||||
|
||||
fn void? out_putchar_fn(void* data @unused, char c) @private
|
||||
macro usz putchar_buf_size() @const
|
||||
{
|
||||
$switch env::MEMORY_ENV:
|
||||
$case NORMAL: return 32 * 1024;
|
||||
$case SMALL: return 1024;
|
||||
$case TINY: return 256;
|
||||
$case NONE: return 256;
|
||||
$endswitch
|
||||
}
|
||||
|
||||
struct PutcharBuffer
|
||||
{
|
||||
char[putchar_buf_size()] data;
|
||||
usz len;
|
||||
bool should_flush;
|
||||
}
|
||||
|
||||
fn void? write_putchar_buffer(PutcharBuffer* buff, bool flush) @private
|
||||
{
|
||||
File* stdout = io::stdout();
|
||||
libc::fwrite(&buff.data, 1, buff.len, stdout.file);
|
||||
buff.len = 0;
|
||||
if (flush) stdout.flush()!;
|
||||
}
|
||||
|
||||
fn void? out_putchar_buffer_fn(void* data @unused, char c) @private
|
||||
{
|
||||
$if env::TESTING:
|
||||
// HACK: this is used for the purpose of unit test output hijacking
|
||||
@@ -275,7 +300,10 @@ fn void? out_putchar_fn(void* data @unused, char c) @private
|
||||
assert(stdout.file);
|
||||
libc::fputc(c, stdout.file);
|
||||
$else
|
||||
libc::putchar(c);
|
||||
PutcharBuffer* buff = data;
|
||||
buff.data[buff.len++] = c;
|
||||
if (c == '\n') buff.should_flush = true;
|
||||
if (buff.len == buff.data.len) write_putchar_buffer(buff, false)!;
|
||||
$endif
|
||||
}
|
||||
|
||||
@@ -296,8 +324,11 @@ fn void? out_putchar_fn(void* data @unused, char c) @private
|
||||
fn usz? printf(String format, args...) @format(0) @maydiscard
|
||||
{
|
||||
Formatter formatter;
|
||||
formatter.init(&out_putchar_fn);
|
||||
return formatter.vprintf(format, args);
|
||||
PutcharBuffer buff;
|
||||
formatter.init(&out_putchar_buffer_fn, &buff);
|
||||
usz? len = formatter.vprintf(format, args);
|
||||
write_putchar_buffer(&buff, buff.should_flush)!;
|
||||
return len;
|
||||
}
|
||||
|
||||
<*
|
||||
@@ -310,10 +341,11 @@ fn usz? printf(String format, args...) @format(0) @maydiscard
|
||||
fn usz? printfn(String format, args...) @format(0) @maydiscard
|
||||
{
|
||||
Formatter formatter;
|
||||
formatter.init(&out_putchar_fn);
|
||||
PutcharBuffer buff;
|
||||
formatter.init(&out_putchar_buffer_fn, &buff);
|
||||
usz? len = formatter.vprintf(format, args);
|
||||
out_putchar_fn(null, '\n')!;
|
||||
io::stdout().flush()!;
|
||||
formatter.out('\n')!;
|
||||
write_putchar_buffer(&buff, true)!;
|
||||
return len + 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -186,13 +186,11 @@ fn bool Path.equals(self, Path p2) @operator(==)
|
||||
fn Path? Path.append(self, Allocator allocator, String filename)
|
||||
{
|
||||
if (!self.path_string.len) return new(allocator, filename, self.env)!;
|
||||
assert(!is_separator(self.path_string[^1], self.env));
|
||||
|
||||
@pool()
|
||||
{
|
||||
DString dstr = dstring::temp_with_capacity(self.path_string.len + 1 + filename.len);
|
||||
dstr.append(self.path_string);
|
||||
dstr.append(PREFERRED_SEPARATOR);
|
||||
if (!is_separator(self.path_string[^1], self.env)) dstr.append(PREFERRED_SEPARATOR);
|
||||
dstr.append(filename);
|
||||
return new(allocator, dstr.str_view(), self.env);
|
||||
};
|
||||
@@ -399,6 +397,19 @@ fn Path? Path.parent(self)
|
||||
{
|
||||
if (is_separator(c, self.env))
|
||||
{
|
||||
if (i == 0) return { self.path_string[..0], self.env, null };
|
||||
if (self.env == WIN32 && i > 1)
|
||||
{
|
||||
if (try volume_len = volume_name_len(self.path_string, WIN32))
|
||||
{
|
||||
// Handle C:\foo
|
||||
if (volume_len == i)
|
||||
{
|
||||
if (i + 1 == self.path_string.len) return NO_PARENT?;
|
||||
return { self.path_string[:i + 1], WIN32, null };
|
||||
}
|
||||
}
|
||||
}
|
||||
return { self.path_string[:i], self.env, null };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,6 +116,9 @@ macro usz? write_all(stream, char[] buffer)
|
||||
return n;
|
||||
}
|
||||
|
||||
<*
|
||||
@require @is_instream(s)
|
||||
*>
|
||||
macro usz? read_using_read_byte(s, char[] buffer)
|
||||
{
|
||||
usz len = 0;
|
||||
@@ -133,12 +136,18 @@ macro usz? read_using_read_byte(s, char[] buffer)
|
||||
return len;
|
||||
}
|
||||
|
||||
<*
|
||||
@require @is_outstream(s)
|
||||
*>
|
||||
macro void? write_byte_using_write(s, char c)
|
||||
{
|
||||
char[1] buff = { c };
|
||||
s.write(&buff)!;
|
||||
}
|
||||
|
||||
<*
|
||||
@require @is_instream(s)
|
||||
*>
|
||||
macro char? read_byte_using_read(s)
|
||||
{
|
||||
char[1] buffer;
|
||||
@@ -149,10 +158,12 @@ macro char? read_byte_using_read(s)
|
||||
|
||||
alias ReadByteFn = fn char?();
|
||||
|
||||
|
||||
<*
|
||||
@require @is_outstream(s)
|
||||
*>
|
||||
macro usz? write_using_write_byte(s, char[] bytes)
|
||||
{
|
||||
foreach (c : bytes) s.write_byte(self, c)!;
|
||||
foreach (c : bytes) s.write_byte(c)!;
|
||||
return bytes.len;
|
||||
}
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ extern fn CInt close(CInt fd) @if(!env::WIN32);
|
||||
extern fn double difftime(Time_t time1, Time_t time2) @if(!env::WIN32);
|
||||
extern fn DivResult div(CInt numer, CInt denom);
|
||||
extern fn void exit(CInt status);
|
||||
extern fn void _exit(CInt status) @extern("_Exit");
|
||||
extern fn void _exit(CInt status) @cname("_Exit");
|
||||
extern fn CInt fclose(CFile stream);
|
||||
extern fn CFile fdopen(CInt fd, ZString mode) @if(!env::WIN32);
|
||||
extern fn CInt feof(CFile stream);
|
||||
@@ -211,9 +211,9 @@ const CInt STDOUT_FD = 1;
|
||||
const CInt STDERR_FD = 2;
|
||||
|
||||
module libc @if(env::LINUX || env::ANDROID);
|
||||
extern CFile __stdin @extern("stdin");
|
||||
extern CFile __stdout @extern("stdout");
|
||||
extern CFile __stderr @extern("stderr");
|
||||
extern CFile __stdin @cname("stdin");
|
||||
extern CFile __stdout @cname("stdout");
|
||||
extern CFile __stderr @cname("stderr");
|
||||
extern fn usz malloc_usable_size(void* ptr);
|
||||
macro usz malloc_size(void* ptr) => malloc_usable_size(ptr);
|
||||
extern fn void* aligned_alloc(usz align, usz size);
|
||||
@@ -262,30 +262,30 @@ module libc @if(!env::LIBC);
|
||||
import std::core::mem;
|
||||
|
||||
|
||||
fn void longjmp(JmpBuf* buffer, CInt value) @weak @extern("longjmp") @nostrip
|
||||
fn void longjmp(JmpBuf* buffer, CInt value) @weak @cname("longjmp") @nostrip
|
||||
{
|
||||
unreachable("longjmp unavailable");
|
||||
}
|
||||
|
||||
fn CInt setjmp(JmpBuf* buffer) @weak @extern("setjmp") @nostrip
|
||||
fn CInt setjmp(JmpBuf* buffer) @weak @cname("setjmp") @nostrip
|
||||
{
|
||||
unreachable("setjmp unavailable");
|
||||
}
|
||||
|
||||
fn void* malloc(usz size) @weak @extern("malloc") @nostrip
|
||||
fn void* malloc(usz size) @weak @cname("malloc") @nostrip
|
||||
{
|
||||
unreachable("malloc unavailable");
|
||||
}
|
||||
fn void* calloc(usz count, usz size) @weak @extern("calloc") @nostrip
|
||||
fn void* calloc(usz count, usz size) @weak @cname("calloc") @nostrip
|
||||
{
|
||||
unreachable("calloc unavailable");
|
||||
}
|
||||
fn void* free(void*) @weak @extern("free")
|
||||
fn void* free(void*) @weak @cname("free")
|
||||
{
|
||||
unreachable("free unavailable");
|
||||
}
|
||||
|
||||
fn void* realloc(void* ptr, usz size) @weak @extern("realloc") @nostrip
|
||||
fn void* realloc(void* ptr, usz size) @weak @cname("realloc") @nostrip
|
||||
{
|
||||
unreachable("realloc unavailable");
|
||||
}
|
||||
@@ -294,69 +294,69 @@ alias memcpy = mem::__memcpy;
|
||||
alias memmove = mem::__memcpy;
|
||||
alias memset = mem::__memset;
|
||||
|
||||
fn int fseek(CFile stream, SeekIndex offset, int whence) @weak @extern("fseek") @nostrip
|
||||
fn int fseek(CFile stream, SeekIndex offset, int whence) @weak @cname("fseek") @nostrip
|
||||
{
|
||||
unreachable("'fseek' not available.");
|
||||
}
|
||||
fn CFile fopen(ZString filename, ZString mode) @weak @extern("fopen") @nostrip
|
||||
fn CFile fopen(ZString filename, ZString mode) @weak @cname("fopen") @nostrip
|
||||
{
|
||||
unreachable("'fopen' not available.");
|
||||
}
|
||||
|
||||
fn CFile freopen(ZString filename, ZString mode, CFile stream) @weak @extern("fopen") @nostrip
|
||||
fn CFile freopen(ZString filename, ZString mode, CFile stream) @weak @cname("fopen") @nostrip
|
||||
{
|
||||
unreachable("'freopen' not available.");
|
||||
}
|
||||
|
||||
fn usz fwrite(void* ptr, usz size, usz nmemb, CFile stream) @weak @extern("fwrite") @nostrip
|
||||
fn usz fwrite(void* ptr, usz size, usz nmemb, CFile stream) @weak @cname("fwrite") @nostrip
|
||||
{
|
||||
unreachable("'fwrite' not available.");
|
||||
}
|
||||
|
||||
fn usz fread(void* ptr, usz size, usz nmemb, CFile stream) @weak @extern("fread") @nostrip
|
||||
fn usz fread(void* ptr, usz size, usz nmemb, CFile stream) @weak @cname("fread") @nostrip
|
||||
{
|
||||
unreachable("'fread' not available.");
|
||||
}
|
||||
|
||||
fn CFile fclose(CFile) @weak @extern("fclose") @nostrip
|
||||
fn CFile fclose(CFile) @weak @cname("fclose") @nostrip
|
||||
{
|
||||
unreachable("'fclose' not available.");
|
||||
}
|
||||
|
||||
fn int fflush(CFile stream) @weak @extern("fflush") @nostrip
|
||||
fn int fflush(CFile stream) @weak @cname("fflush") @nostrip
|
||||
{
|
||||
unreachable("'fflush' not available.");
|
||||
}
|
||||
|
||||
fn int fputc(int c, CFile stream) @weak @extern("fputc") @nostrip
|
||||
fn int fputc(int c, CFile stream) @weak @cname("fputc") @nostrip
|
||||
{
|
||||
unreachable("'fputc' not available.");
|
||||
}
|
||||
|
||||
fn char* fgets(ZString str, int n, CFile stream) @weak @extern("fgets") @nostrip
|
||||
fn char* fgets(ZString str, int n, CFile stream) @weak @cname("fgets") @nostrip
|
||||
{
|
||||
unreachable("'fgets' not available.");
|
||||
}
|
||||
|
||||
fn int fgetc(CFile stream) @weak @extern("fgetc") @nostrip
|
||||
fn int fgetc(CFile stream) @weak @cname("fgetc") @nostrip
|
||||
{
|
||||
unreachable("'fgetc' not available.");
|
||||
}
|
||||
|
||||
fn int feof(CFile stream) @weak @extern("feof") @nostrip
|
||||
fn int feof(CFile stream) @weak @cname("feof") @nostrip
|
||||
{
|
||||
unreachable("'feof' not available.");
|
||||
}
|
||||
|
||||
fn int putc(int c, CFile stream) @weak @extern("putc") @nostrip
|
||||
fn int putc(int c, CFile stream) @weak @cname("putc") @nostrip
|
||||
{
|
||||
unreachable("'putc' not available.");
|
||||
}
|
||||
fn int putchar(int c) @weak @extern("putchar") @nostrip
|
||||
fn int putchar(int c) @weak @cname("putchar") @nostrip
|
||||
{
|
||||
unreachable("'putchar' not available.");
|
||||
}
|
||||
fn int puts(ZString str) @weak @extern("puts") @nostrip
|
||||
fn int puts(ZString str) @weak @cname("puts") @nostrip
|
||||
{
|
||||
unreachable("'puts' not available.");
|
||||
}
|
||||
|
||||
@@ -41,6 +41,6 @@ struct Stat
|
||||
long[2] st_qspare;
|
||||
}
|
||||
|
||||
extern fn int stat(ZString str, Stat* stat) @extern("stat64");
|
||||
extern fn int stat(ZString str, Stat* stat) @cname("stat64");
|
||||
|
||||
extern fn CInt sysctl(CInt *name, CUInt namelen, void *oldp, usz *oldlenp, void *newp, usz newlen);
|
||||
|
||||
@@ -62,7 +62,7 @@ struct SystemInfo
|
||||
ushort wProcessorRevision;
|
||||
}
|
||||
|
||||
extern fn CInt get_system_info(SystemInfo*) @extern("GetSystemInfo");
|
||||
extern fn CInt get_system_info(SystemInfo*) @cname("GetSystemInfo");
|
||||
|
||||
// Aliases to simplify libc use
|
||||
macro Tm* localtime_r(Time_t* timer, Tm* buf) => _localtime64_s(buf, timer);
|
||||
|
||||
@@ -506,19 +506,56 @@ fn BigInt BigInt.abs(&self)
|
||||
return self.is_negative() ? self.unary_minus() : *self;
|
||||
}
|
||||
|
||||
fn usz? BigInt.to_format(&self, Formatter* format) @dynamic
|
||||
{
|
||||
@stack_mem(4100; Allocator mem)
|
||||
{
|
||||
return format.print(self.to_string_with_radix(10, mem));
|
||||
};
|
||||
}
|
||||
|
||||
fn String BigInt.to_string(&self, Allocator allocator) @dynamic
|
||||
{
|
||||
return self.to_string_with_radix(10, allocator);
|
||||
}
|
||||
|
||||
fn usz? BigInt.to_format(&self, Formatter* format) @dynamic
|
||||
{
|
||||
if (self.is_zero())
|
||||
{
|
||||
format.print("0")!;
|
||||
return 1;
|
||||
}
|
||||
BigInt a = *self;
|
||||
bool negative = self.is_negative();
|
||||
usz len;
|
||||
if (negative)
|
||||
{
|
||||
format.out('-')!;
|
||||
len++;
|
||||
a.negate();
|
||||
}
|
||||
uint[280] chunks @noinit;
|
||||
int chunk_count;
|
||||
|
||||
const BASE10_9 = 1000000000;
|
||||
foreach_r(d : self.data[:self.len])
|
||||
{
|
||||
ulong carry = d;
|
||||
for (int i = 0; i < chunk_count; i++)
|
||||
{
|
||||
ulong v = (ulong)chunks[i] << 32 + carry;
|
||||
carry = v / BASE10_9;
|
||||
chunks[i] = (uint)(v - carry * BASE10_9);
|
||||
}
|
||||
if (carry)
|
||||
{
|
||||
ulong new_carry = carry / BASE10_9;
|
||||
chunks[chunk_count++] = (uint)(carry - new_carry * BASE10_9);
|
||||
if (new_carry) chunks[chunk_count++] = (uint)new_carry;
|
||||
}
|
||||
}
|
||||
int ms = chunk_count - 1;
|
||||
len += format.printf("%d", chunks[ms])!;
|
||||
foreach_r (c : chunks[:ms])
|
||||
{
|
||||
len += format.printf("%09d", c)!;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
<*
|
||||
@require radix > 1 && radix <= 36 : "Radix must be 2-36"
|
||||
*>
|
||||
@@ -527,7 +564,7 @@ fn String BigInt.to_string_with_radix(&self, int radix, Allocator allocator)
|
||||
if (self.is_zero()) return "0".copy(allocator);
|
||||
|
||||
const char[*] CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
@stack_mem(4100; Allocator mem)
|
||||
@stack_mem(4120; Allocator mem)
|
||||
{
|
||||
BigInt a = *self;
|
||||
DString str;
|
||||
|
||||
@@ -6,7 +6,7 @@ import std::math::complex;
|
||||
import std::math::matrix;
|
||||
import std::math::quaternion;
|
||||
|
||||
attrdef @MathLibc(name) = @extern(name), @link(env::POSIX, "m");
|
||||
attrdef @MathLibc(name) = @cname(name), @link(env::POSIX, "m");
|
||||
|
||||
const E = 2.718281828459045235360287471352662497757247093699959574966967627724076630353547594571382178525166427427466;
|
||||
const LOG2E = 1.44269504088896340735992468100189214; // log2(e)
|
||||
@@ -73,6 +73,11 @@ faultdef OVERFLOW, MATRIX_INVERSE_DOESNT_EXIST;
|
||||
*>
|
||||
macro deg_to_rad(x) => x * PI / 180;
|
||||
|
||||
<*
|
||||
@require types::is_numerical($typeof(x)) : `The input must be a numerical value or numerical vector`
|
||||
*>
|
||||
macro rad_to_deg(x) => x * 180 / PI;
|
||||
|
||||
<*
|
||||
@require types::is_numerical($typeof(x)) : `The input must be a numerical value or numerical vector`
|
||||
*>
|
||||
@@ -1042,8 +1047,8 @@ extern fn void _sincosf(float, float*, float*) @MathLibc("__sincosf") @if(env::D
|
||||
extern fn void _sincos(double, double*, double*) @MathLibc("sincos") @if(!env::DARWIN && !env::WIN32);
|
||||
extern fn void _sincosf(float, float*, float*) @MathLibc("sincosf") @if(!env::DARWIN && !env::WIN32);
|
||||
|
||||
fn void _sincos(double a, double* s, double* c) @extern("sincos") @if(env::WIN32) { *s = sin(a); *c = cos(a); }
|
||||
fn void _sincosf(float a, float* s, float* c) @extern("sincosf") @if(env::WIN32) { *s = sin(a); *c = cos(a); }
|
||||
fn void _sincos(double a, double* s, double* c) @cname("sincos") @if(env::WIN32) { *s = sin(a); *c = cos(a); }
|
||||
fn void _sincosf(float a, float* s, float* c) @cname("sincosf") @if(env::WIN32) { *s = sin(a); *c = cos(a); }
|
||||
|
||||
extern fn double _tan(double x) @MathLibc("tan");
|
||||
extern fn float _tanf(float x) @MathLibc("tanf");
|
||||
@@ -1157,7 +1162,7 @@ macro bool overflow_sub(a, b, out) => $$overflow_sub(a, b, out);
|
||||
@require values::@is_flat_intlike(a) &&& values::@is_flat_intlike(b) : "a and b must both be integer or integer vector based"
|
||||
@require $defined(*out) &&& @typematch(*out, a) : "out must be a pointer of the same type as a and b"
|
||||
*>
|
||||
macro bool overflow_mul(a, b, out) => $$overflow_mul(a, b, out);
|
||||
macro overflow_mul(a, b, out) => $$overflow_mul(a, b, out);
|
||||
|
||||
<*
|
||||
@require types::is_vector($Type) || ($Type.kindof == ARRAY &&& types::is_numerical($typefrom($Type.inner)))
|
||||
|
||||
@@ -12,7 +12,7 @@ module std::math::nolibc @if(env::NO_LIBC || $feature(C3_MATH));
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
fn double __cos(double x, double y) @extern("__cos") @weak @nostrip
|
||||
fn double __cos(double x, double y) @cname("__cos") @weak @nostrip
|
||||
{
|
||||
const C1 = 4.16666666666666019037e-02; /* 0x3FA55555, 0x5555554C */
|
||||
const C2 = -1.38888888888741095749e-03; /* 0xBF56C16C, 0x16C15177 */
|
||||
|
||||
@@ -22,7 +22,7 @@ const double C1 @private = 0x155553e1053a42.0p-57; /* 0.0416666233237390631894
|
||||
const double C2 @private = -0x16c087e80f1e27.0p-62; /* -0.00138867637746099294692 */
|
||||
const double C3 @private = 0x199342e0ee5069.0p-68; /* 0.0000243904487962774090654 */
|
||||
|
||||
fn float __cosdf(double x) @extern("__cosdf") @weak @nostrip
|
||||
fn float __cosdf(double x) @cname("__cosdf") @weak @nostrip
|
||||
{
|
||||
/* Try to optimize for parallel evaluation as in __tandf.c. */
|
||||
double z = x * x;
|
||||
|
||||
@@ -13,7 +13,7 @@ union FloatInternal
|
||||
}
|
||||
|
||||
// Based on the musl implementation
|
||||
fn double fmod(double x, double y) @extern("fmod") @weak @nostrip
|
||||
fn double fmod(double x, double y) @cname("fmod") @weak @nostrip
|
||||
{
|
||||
DoubleInternal ux = { .f = x };
|
||||
DoubleInternal uy = { .f = y };
|
||||
@@ -83,7 +83,7 @@ fn double fmod(double x, double y) @extern("fmod") @weak @nostrip
|
||||
return ux.f;
|
||||
}
|
||||
|
||||
fn float fmodf(float x, float y) @extern("fmodf") @weak @nostrip
|
||||
fn float fmodf(float x, float y) @cname("fmodf") @weak @nostrip
|
||||
{
|
||||
FloatInternal ux = { .f = x };
|
||||
FloatInternal uy = { .f = y };
|
||||
|
||||
@@ -11,7 +11,7 @@ module std::math::nolibc @if(env::NO_LIBC || $feature(C3_MATH));
|
||||
* is preserved.
|
||||
* ====================================================
|
||||
*/
|
||||
fn double __sin(double x, double y, int iy) @extern("__sin") @weak @nostrip
|
||||
fn double __sin(double x, double y, int iy) @cname("__sin") @weak @nostrip
|
||||
{
|
||||
|
||||
const S1 = -1.66666666666666324348e-01; /* 0xBFC55555, 0x55555549 */
|
||||
|
||||
@@ -16,7 +16,7 @@ module std::math::nolibc @if(env::NO_LIBC || $feature(C3_MATH));
|
||||
* ====================================================
|
||||
*/
|
||||
// |sin(x)/x - s(x)| < 2**-37.5 (~[-4.89e-12, 4.824e-12]).
|
||||
fn float __sindf(double x) @extern("__sindf") @weak @nostrip
|
||||
fn float __sindf(double x) @cname("__sindf") @weak @nostrip
|
||||
{
|
||||
const S1F = -0x15555554cbac77.0p-55; /* -0.166666666416265235595 */
|
||||
const S2F = 0x111110896efbb2.0p-59; /* 0.0083333293858894631756 */
|
||||
|
||||
@@ -27,7 +27,7 @@ const double[*] TAN_T = {
|
||||
2.59073051863633712884e-05, /* 3EFB2A70, 74BF7AD4 */
|
||||
};
|
||||
|
||||
fn double __tan(double x, double y, int odd) @extern("__tan") @weak @nostrip
|
||||
fn double __tan(double x, double y, int odd) @cname("__tan") @weak @nostrip
|
||||
{
|
||||
const double PIO4 = 7.85398163397448278999e-01; /* 3FE921FB, 54442D18 */
|
||||
const double PIO4LO = 3.06161699786838301793e-17; /* 3C81A626, 33145C07 */
|
||||
|
||||
@@ -25,7 +25,7 @@ const double[*] TANDF = {
|
||||
0x1362b9bf971bcd.0p-59, /* 0.00946564784943673166728 */
|
||||
};
|
||||
|
||||
fn float __tandf(double x, int odd) @extern("__tandf") @weak @nostrip
|
||||
fn float __tandf(double x, int odd) @cname("__tandf") @weak @nostrip
|
||||
{
|
||||
double z = x * x;
|
||||
/*
|
||||
|
||||
@@ -32,7 +32,7 @@ fn double _r(double z) @local
|
||||
return p / q;
|
||||
}
|
||||
|
||||
fn double _acos(double x) @weak @extern("acos") @nostrip
|
||||
fn double _acos(double x) @weak @cname("acos") @nostrip
|
||||
{
|
||||
uint hx = x.high_word();
|
||||
uint ix = hx & 0x7fffffff;
|
||||
@@ -100,7 +100,7 @@ fn float _r_f(float z) @local
|
||||
return p / q;
|
||||
}
|
||||
|
||||
fn float _acosf(float x) @weak @extern("acosf") @nostrip
|
||||
fn float _acosf(float x) @weak @cname("acosf") @nostrip
|
||||
{
|
||||
uint hx = bitcast(x, uint);
|
||||
uint ix = hx & 0x7fffffff;
|
||||
|
||||
@@ -32,7 +32,7 @@ fn double _r(double z) @local
|
||||
return p / q;
|
||||
}
|
||||
|
||||
fn double _asin(double x) @weak @extern("asin") @nostrip
|
||||
fn double _asin(double x) @weak @cname("asin") @nostrip
|
||||
{
|
||||
uint hx = x.high_word();
|
||||
uint ix = hx & 0x7fffffff;
|
||||
@@ -102,7 +102,7 @@ fn float _r_f(float z) @local
|
||||
return p / q;
|
||||
}
|
||||
|
||||
fn float _asinf(float x) @weak @extern("asinf") @nostrip
|
||||
fn float _asinf(float x) @weak @cname("asinf") @nostrip
|
||||
{
|
||||
uint hx = bitcast(x, uint);
|
||||
uint ix = hx & 0x7fffffff;
|
||||
|
||||
@@ -40,7 +40,7 @@ const double[*] AT @private = {
|
||||
1.62858201153657823623e-02, /* 0x3F90AD3A, 0xE322DA11 */
|
||||
};
|
||||
|
||||
fn double _atan(double x) @weak @extern("atan") @nostrip
|
||||
fn double _atan(double x) @weak @cname("atan") @nostrip
|
||||
{
|
||||
int id @noinit;
|
||||
uint ix = x.high_word();
|
||||
@@ -138,7 +138,7 @@ const float[*] ATF @private = {
|
||||
6.1687607318e-02,
|
||||
};
|
||||
|
||||
fn float _atanf(float x) @weak @extern("atanf") @nostrip
|
||||
fn float _atanf(float x) @weak @cname("atanf") @nostrip
|
||||
{
|
||||
int id @noinit;
|
||||
uint ix = x.word();
|
||||
@@ -217,7 +217,7 @@ fn float _atanf(float x) @weak @extern("atanf") @nostrip
|
||||
|
||||
const PI_LO @private = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */
|
||||
|
||||
fn double _atan2(double y, double x) @weak @extern("atan2") @nostrip
|
||||
fn double _atan2(double y, double x) @weak @cname("atan2") @nostrip
|
||||
{
|
||||
if (math::is_nan(x) || math::is_nan(y)) return x + y;
|
||||
|
||||
@@ -301,7 +301,7 @@ fn double _atan2(double y, double x) @weak @extern("atan2") @nostrip
|
||||
const float PI_F @private = 3.1415927410e+00; /* 0x40490fdb */
|
||||
const float PI_LO_F @private = -8.7422776573e-08; /* 0xb3bbbd2e */
|
||||
|
||||
fn float _atan2f(float y, float x) @weak @extern("atan2f") @nostrip
|
||||
fn float _atan2f(float y, float x) @weak @cname("atan2f") @nostrip
|
||||
{
|
||||
if (math::is_nan(x) || math::is_nan(y)) return x + y;
|
||||
uint ix = x.word();
|
||||
|
||||
@@ -12,7 +12,7 @@ module std::math::nolibc @if(env::NO_LIBC || $feature(C3_MATH));
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
fn double _atanh(double x) @weak @extern("atanh") @nostrip
|
||||
fn double _atanh(double x) @weak @cname("atanh") @nostrip
|
||||
{
|
||||
double t @noinit;
|
||||
uint hx = x.high_word();
|
||||
@@ -61,7 +61,7 @@ fn double _atanh(double x) @weak @extern("atanh") @nostrip
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
fn float _atanhf(float x) @weak @extern("atanhf") @nostrip
|
||||
fn float _atanhf(float x) @weak @cname("atanhf") @nostrip
|
||||
{
|
||||
float t @noinit;
|
||||
uint hx = bitcast(x, uint);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module std::math::nolibc @if(env::NO_LIBC || $feature(C3_MATH));
|
||||
|
||||
fn double _ceil(double x) @weak @extern("ceil") @nostrip
|
||||
fn double _ceil(double x) @weak @cname("ceil") @nostrip
|
||||
{
|
||||
ulong ui = bitcast(x, ulong);
|
||||
int e = (int)((ui >> 52) & 0x7ff);
|
||||
@@ -17,7 +17,7 @@ fn double _ceil(double x) @weak @extern("ceil") @nostrip
|
||||
}
|
||||
|
||||
|
||||
fn float _ceilf(float x) @weak @extern("ceilf") @nostrip
|
||||
fn float _ceilf(float x) @weak @cname("ceilf") @nostrip
|
||||
{
|
||||
uint u = bitcast(x, uint);
|
||||
int e = (int)((u >> 23) & 0xff) - 0x7f;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module std::math::nolibc @if(env::NO_LIBC || $feature(C3_MATH));
|
||||
|
||||
fn float _cosf(float x) @extern("cosf") @weak @nostrip
|
||||
fn float _cosf(float x) @cname("cosf") @weak @nostrip
|
||||
{
|
||||
uint ix = x.word();
|
||||
uint sign = ix >> 31;
|
||||
@@ -51,7 +51,7 @@ fn float _cosf(float x) @extern("cosf") @weak @nostrip
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
fn double _cos(double x) @extern("cos") @weak @nostrip
|
||||
fn double _cos(double x) @cname("cos") @weak @nostrip
|
||||
{
|
||||
// High word of x.
|
||||
uint ix = x.high_word() & 0x7fffffff;
|
||||
|
||||
@@ -17,7 +17,7 @@ const float EXPF_P2 = -2.7777778450e-03f;
|
||||
const float EXPF_P3 = 6.6137559770e-05f;
|
||||
const float EXPF_P4 = -1.6533901999e-06f;
|
||||
|
||||
fn double exp(double x) @extern("exp") @nostrip @weak
|
||||
fn double exp(double x) @cname("exp") @nostrip @weak
|
||||
{
|
||||
if (x != x) return x;
|
||||
if (x == double.inf) return double.inf;
|
||||
@@ -38,7 +38,7 @@ fn double exp(double x) @extern("exp") @nostrip @weak
|
||||
return ldexp(exp_r, (int)k);
|
||||
}
|
||||
|
||||
fn float expf(float x) @extern("expf") @nostrip @weak
|
||||
fn float expf(float x) @cname("expf") @nostrip @weak
|
||||
{
|
||||
if (x != x) return x;
|
||||
if (x == float.inf) return float.inf;
|
||||
|
||||
@@ -3,7 +3,7 @@ module std::math::nolibc @if(env::NO_LIBC || $feature(C3_MATH));
|
||||
macro uint _top12f(float x) @private => bitcast(x, uint) >> 20;
|
||||
|
||||
|
||||
fn float _exp2f(float x) @extern("exp2f") @weak @nostrip
|
||||
fn float _exp2f(float x) @cname("exp2f") @weak @nostrip
|
||||
{
|
||||
double xd = x;
|
||||
uint abstop = _top12f(x) & 0x7ff;
|
||||
@@ -80,7 +80,7 @@ macro uint _top12d(double x) @private
|
||||
return (uint)(bitcast(x, ulong) >> 52);
|
||||
}
|
||||
|
||||
fn double _exp2(double x) @extern("exp2") @weak @nostrip
|
||||
fn double _exp2(double x) @cname("exp2") @weak @nostrip
|
||||
{
|
||||
uint abstop = _top12d(x) & 0x7ff;
|
||||
ulong u = bitcast(x, ulong);
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
module std::math::nolibc @if(env::NO_LIBC || $feature(C3_MATH));
|
||||
|
||||
fn double _fabs(double x) @weak @extern("fabs") @nostrip
|
||||
fn double _fabs(double x) @weak @cname("fabs") @nostrip
|
||||
{
|
||||
ulong ix = bitcast(x, ulong);
|
||||
ix &= ~(1ul << 63);
|
||||
return bitcast(ix, double);
|
||||
}
|
||||
|
||||
fn float _fabsf(float x) @weak @extern("fabsf") @nostrip
|
||||
fn float _fabsf(float x) @weak @cname("fabsf") @nostrip
|
||||
{
|
||||
uint ix = bitcast(x, uint);
|
||||
ix &= 0x7fffffff;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module std::math::nolibc @if(env::NO_LIBC || $feature(C3_MATH));
|
||||
|
||||
fn double _floor(double x) @weak @extern("floor") @nostrip
|
||||
fn double _floor(double x) @weak @cname("floor") @nostrip
|
||||
{
|
||||
ulong ui = bitcast(x, ulong);
|
||||
int e = (int)((ui >> 52) & 0x7ff);
|
||||
@@ -17,7 +17,7 @@ fn double _floor(double x) @weak @extern("floor") @nostrip
|
||||
}
|
||||
|
||||
|
||||
fn float _floorf(float x) @weak @extern("floorf") @nostrip
|
||||
fn float _floorf(float x) @weak @cname("floorf") @nostrip
|
||||
{
|
||||
uint u = bitcast(x, uint);
|
||||
int e = (int)((u >> 23) & 0xff) - 0x7f;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module std::math::nolibc @if(env::NO_LIBC || $feature(C3_MATH));
|
||||
|
||||
fn double frexp(double x, int* exp) @extern("frexp")
|
||||
fn double frexp(double x, int* exp) @cname("frexp")
|
||||
{
|
||||
uint hx = x.high_word();
|
||||
uint ix = hx & 0x7fffffff;
|
||||
@@ -31,7 +31,7 @@ fn double frexp(double x, int* exp) @extern("frexp")
|
||||
}
|
||||
}
|
||||
|
||||
fn float frexpf(float x, int* exp) @extern("frexpf")
|
||||
fn float frexpf(float x, int* exp) @cname("frexpf")
|
||||
{
|
||||
uint ix = x.word();
|
||||
uint hx = ix & 0x7fffffff;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module std::math::nolibc @if(env::NO_LIBC || $feature(C3_MATH));
|
||||
|
||||
fn double ldexp(double x, int exp) @extern("ldexp")
|
||||
fn double ldexp(double x, int exp) @cname("ldexp")
|
||||
{
|
||||
uint hx = x.high_word();
|
||||
int hexp = (int)((hx & 0x7ff00000) >> 20);
|
||||
@@ -35,7 +35,7 @@ fn double ldexp(double x, int exp) @extern("ldexp")
|
||||
}
|
||||
}
|
||||
|
||||
fn float ldexpf(float x, int exp) @extern("ldexpf")
|
||||
fn float ldexpf(float x, int exp) @cname("ldexpf")
|
||||
{
|
||||
uint ix = x.word();
|
||||
int hexp = (int)((ix & 0x7f800000) >> 23);
|
||||
|
||||
@@ -19,7 +19,7 @@ const float LOGF_L4 = 2.4279078841e-01f;
|
||||
const double SQRT2 = 1.41421356237309504880;
|
||||
const float SQRT2F = 1.41421356237309504880f;
|
||||
|
||||
fn double log(double x) @extern("log") @nostrip @weak
|
||||
fn double log(double x) @cname("log") @nostrip @weak
|
||||
{
|
||||
if (x != x) return x;
|
||||
if (x < 0.0) return double.nan;
|
||||
@@ -50,7 +50,7 @@ fn double log(double x) @extern("log") @nostrip @weak
|
||||
return k * LOG_LN2_HI - ((hfsq - (s * (hfsq + r) + k * LOG_LN2_LO)) - f);
|
||||
}
|
||||
|
||||
fn float logf(float x) @extern("logf") @nostrip @weak
|
||||
fn float logf(float x) @cname("logf") @nostrip @weak
|
||||
{
|
||||
if (x != x) return x;
|
||||
if (x < 0.0f) return float.nan;
|
||||
|
||||
@@ -48,7 +48,7 @@ const LG5 @local = 1.818357216161805012e-01; /* 3FC74664 96CB03DE */
|
||||
const LG6 @local = 1.531383769920937332e-01; /* 3FC39A09 D078C69F */
|
||||
const LG7 @local = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */
|
||||
|
||||
fn double _log1p(double x) @weak @extern("log1p") @nostrip
|
||||
fn double _log1p(double x) @weak @cname("log1p") @nostrip
|
||||
{
|
||||
uint hx = x.high_word();
|
||||
int k = 1;
|
||||
@@ -162,7 +162,7 @@ const float LG2_F @local = 0xccce13.0p-25; /* 0.40000972152 */
|
||||
const float LG3_F @local = 0x91e9ee.0p-25; /* 0.28498786688 */
|
||||
const float LG4_F @local = 0xf89e26.0p-26; /* 0.24279078841 */
|
||||
|
||||
fn float _log1pf(float x) @weak @extern("log1pf") @nostrip
|
||||
fn float _log1pf(float x) @weak @cname("log1pf") @nostrip
|
||||
{
|
||||
uint ix = x.word();
|
||||
int k = 1;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module std::math::nolibc @if(env::NO_LIBC || $feature(C3_MATH));
|
||||
|
||||
fn double pow(double x, double y) @extern("pow")
|
||||
fn double pow(double x, double y) @cname("pow")
|
||||
{
|
||||
if (x != x || y != y) return double.nan;
|
||||
|
||||
@@ -54,7 +54,7 @@ fn double pow(double x, double y) @extern("pow")
|
||||
return result;
|
||||
}
|
||||
|
||||
fn float powf(float x, float y) @extern("powf")
|
||||
fn float powf(float x, float y) @cname("powf")
|
||||
{
|
||||
if (x != x || y != y) return float.nan;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module std::math::nolibc @if(env::NO_LIBC || $feature(C3_MATH));
|
||||
|
||||
fn double _round(double x) @extern("round") @weak @nostrip
|
||||
fn double _round(double x) @cname("round") @weak @nostrip
|
||||
{
|
||||
ulong u = bitcast(x, ulong);
|
||||
int e = (int)((u >> 52) & 0x7ff);
|
||||
@@ -26,7 +26,7 @@ fn double _round(double x) @extern("round") @weak @nostrip
|
||||
return y;
|
||||
}
|
||||
|
||||
fn float _roundf(float x) @extern("roundf") @weak @nostrip
|
||||
fn float _roundf(float x) @cname("roundf") @weak @nostrip
|
||||
{
|
||||
uint u = bitcast(x, uint);
|
||||
int e = (u >> 23) & 0xff;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module std::math::nolibc @if(env::NO_LIBC || $feature(C3_MATH));
|
||||
|
||||
fn double _scalbn(double x, int n) @weak @extern("scalbn") @nostrip
|
||||
fn double _scalbn(double x, int n) @weak @cname("scalbn") @nostrip
|
||||
{
|
||||
switch
|
||||
{
|
||||
|
||||
@@ -16,7 +16,7 @@ module std::math::nolibc @if(env::NO_LIBC || $feature(C3_MATH));
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
fn float _sinf(float x) @weak @extern("sinf") @nostrip
|
||||
fn float _sinf(float x) @weak @cname("sinf") @nostrip
|
||||
{
|
||||
uint ix = x.word();
|
||||
int sign = ix >> 31;
|
||||
@@ -84,7 +84,7 @@ fn float _sinf(float x) @weak @extern("sinf") @nostrip
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
fn double sin(double x) @extern("sin") @weak @nostrip
|
||||
fn double sin(double x) @cname("sin") @weak @nostrip
|
||||
{
|
||||
// High word of x.
|
||||
uint ix = x.high_word() & 0x7fffffff;
|
||||
|
||||
@@ -16,7 +16,7 @@ module std::math::nolibc @if(env::NO_LIBC || $feature(C3_MATH));
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
fn void sincosf(float x, float *sin, float *cos) @extern("__sincosf") @weak @nostrip
|
||||
fn void sincosf(float x, float *sin, float *cos) @cname("__sincosf") @weak @nostrip
|
||||
{
|
||||
uint ix = x.word();
|
||||
uint sign = ix >> 31;
|
||||
@@ -104,7 +104,7 @@ fn void sincosf(float x, float *sin, float *cos) @extern("__sincosf") @weak @nos
|
||||
|
||||
}
|
||||
|
||||
fn void sincos(double x, double *sin, double *cos) @extern("__sincos") @weak @nostrip
|
||||
fn void sincos(double x, double *sin, double *cos) @cname("__sincos") @weak @nostrip
|
||||
{
|
||||
// High word of x.
|
||||
uint ix = x.high_word() & 0x7fffffff;
|
||||
|
||||
@@ -12,7 +12,7 @@ module std::math::nolibc @if(env::NO_LIBC || $feature(C3_MATH));
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
fn double tan(double x) @extern("tan") @weak @nostrip
|
||||
fn double tan(double x) @cname("tan") @weak @nostrip
|
||||
{
|
||||
uint ix = x.high_word();
|
||||
ix &= 0x7fffffff;
|
||||
@@ -57,7 +57,7 @@ fn double tan(double x) @extern("tan") @weak @nostrip
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
fn float tanf(float x) @extern("tanf") @weak @nostrip
|
||||
fn float tanf(float x) @cname("tanf") @weak @nostrip
|
||||
{
|
||||
uint ix = x.word();
|
||||
uint sign = ix >> 31;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module std::math::nolibc @if(env::NO_LIBC || $feature(C3_MATH));
|
||||
|
||||
fn double sincos_broken(double x) @extern("sincos") @weak @nostrip
|
||||
fn double sincos_broken(double x) @cname("sincos") @weak @nostrip
|
||||
{
|
||||
unreachable("'sinccos' not supported");
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module std::math::nolibc @if(env::NO_LIBC || $feature(C3_MATH));
|
||||
|
||||
fn double _trunc(double x) @weak @extern("trunc") @nostrip
|
||||
fn double _trunc(double x) @weak @cname("trunc") @nostrip
|
||||
{
|
||||
ulong i = bitcast(x, ulong);
|
||||
int e = (int)((i >> 52) & 0x7ff) - 0x3ff + 12;
|
||||
@@ -13,7 +13,7 @@ fn double _trunc(double x) @weak @extern("trunc") @nostrip
|
||||
return bitcast(i, double);
|
||||
}
|
||||
|
||||
fn float _truncf(float x) @weak @extern("truncf") @nostrip
|
||||
fn float _truncf(float x) @weak @cname("truncf") @nostrip
|
||||
{
|
||||
uint i = bitcast(x, uint);
|
||||
int e = (int)((i >> 23) & 0xff) - 0x7f + 9;
|
||||
|
||||
@@ -32,12 +32,15 @@ macro QuaternionNumber QuaternionNumber.sub(self, QuaternionNumber b) @operator(
|
||||
macro QuaternionNumber QuaternionNumber.negate(self) @operator(-) => { .v = -self.v };
|
||||
macro QuaternionNumber QuaternionNumber.sub_each(self, Real b) => { .v = self.v - b };
|
||||
macro QuaternionNumber QuaternionNumber.scale(self, Real s) @operator_s(*) => { .v = self.v * s };
|
||||
macro QuaternionNumber.to_angle(self) => 2 * math::acos(self.v.w);
|
||||
macro QuaternionNumber QuaternionNumber.normalize(self) => { .v = self.v.normalize() };
|
||||
macro Real QuaternionNumber.length(self) => self.v.length();
|
||||
macro QuaternionNumber QuaternionNumber.lerp(self, QuaternionNumber q2, Real amount) => { .v = self.v.lerp(q2.v, amount) };
|
||||
fn QuaternionNumber QuaternionNumber.nlerp(self, QuaternionNumber q2, Real amount) => { .v = self.v.lerp(q2.v, amount).normalize() };
|
||||
|
||||
macro Matrix4f QuaternionNumber.to_matrixf(&self) => into_matrix(self, Matrix4f);
|
||||
macro Matrix4 QuaternionNumber.to_matrix(&self) => into_matrix(self, Matrix4);
|
||||
fn QuaternionNumber QuaternionNumber.nlerp(self, QuaternionNumber q2, Real amount) => { .v = self.v.lerp(q2.v, amount).normalize() };
|
||||
|
||||
|
||||
fn QuaternionNumber QuaternionNumber.invert(self)
|
||||
{
|
||||
@@ -47,6 +50,8 @@ fn QuaternionNumber QuaternionNumber.invert(self)
|
||||
return { self.v[0] * -inv_length, self.v[1] * -inv_length, self.v[2] * -inv_length, self.v[3] * inv_length };
|
||||
}
|
||||
|
||||
fn QuaternionNumber QuaternionNumber.conjugate(&self) => { -self.v.x, -self.v.y, -self.v.z, self.v.w };
|
||||
|
||||
fn QuaternionNumber QuaternionNumber.slerp(self, QuaternionNumber q2, Real amount)
|
||||
{
|
||||
QuaternionNumber result = {};
|
||||
@@ -77,13 +82,35 @@ fn QuaternionNumber QuaternionNumber.slerp(self, QuaternionNumber q2, Real amoun
|
||||
}
|
||||
|
||||
fn QuaternionNumber QuaternionNumber.mul(self, QuaternionNumber b) @operator(*)
|
||||
{
|
||||
return { self.i * b.l + self.l * b.i + self.j * b.k - self.k * b.j,
|
||||
self.j * b.l + self.l * b.j + self.k * b.i - self.i * b.k,
|
||||
self.k * b.l + self.l * b.k + self.i * b.j - self.j * b.i,
|
||||
self.l * b.l - self.i * b.i - self.j * self.j - self.k * self.k };
|
||||
{
|
||||
Real[<3>] q1_axis = { self.v.x, self.v.y, self.v.z };
|
||||
Real[<3>] q2_axis = { b.v.x, b.v.y, b.v.z };
|
||||
|
||||
Real scalar = (self.v.w * b.v.w - q1_axis.dot(q2_axis));
|
||||
Real[<3>] axis = self.v.w * q2_axis + b.v.w * q1_axis + q1_axis.cross(q2_axis);
|
||||
|
||||
return { ...axis, scalar };
|
||||
}
|
||||
|
||||
|
||||
fn QuaternionNumber from_axis_angle(Real[<3>] axis, Real angle)
|
||||
{
|
||||
Real[<3>] normal_axis = axis.normalize();
|
||||
Real half_angle = angle * 0.5;
|
||||
Real sin_half = math::sin(half_angle);
|
||||
|
||||
return { ...(normal_axis * sin_half), math::cos(half_angle) };
|
||||
}
|
||||
|
||||
fn Real[<3>] QuaternionNumber.rotate_vec3(self, Real[<3>] vector) @operator(*)
|
||||
{
|
||||
QuaternionNumber p = { ...vector, 0 };
|
||||
QuaternionNumber result = self * p * self.conjugate();
|
||||
return result.v.xyz;
|
||||
}
|
||||
|
||||
|
||||
|
||||
macro into_matrix(QuaternionNumber* q, $Type) @private
|
||||
{
|
||||
QuaternionNumber rotation = q.normalize();
|
||||
@@ -93,9 +120,9 @@ macro into_matrix(QuaternionNumber* q, $Type) @private
|
||||
var w = rotation.l;
|
||||
|
||||
return ($Type) {
|
||||
1 - 2*y*y - 2*z*z, 2*x*y - 2*z*w, 2*x*z + 2*y*w, 0,
|
||||
2*x*y + 2*z*w, 1 - 2*x*x - 2*z*z, 2*y*z - 2*x*w, 0,
|
||||
2*x*z - 2*y*w, 2*y*z + 2*x*w , 1 - 2*x*x - 2*y*y, 0,
|
||||
0.0, 0.0, 0.0, 1.0,
|
||||
1 - 2*y*y - 2*z*z, 2*x*y - 2*z*w, 2*x*z + 2*y*w, 0,
|
||||
2*x*y + 2*z*w, 1 - 2*x*x - 2*z*z, 2*y*z - 2*x*w, 0,
|
||||
2*x*z - 2*y*w, 2*y*z + 2*x*w, 1 - 2*x*x - 2*y*y, 0,
|
||||
0.0, 0.0, 0.0, 1.0,
|
||||
};
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
module std::math::math_rt;
|
||||
|
||||
fn int128 __divti3(int128 a, int128 b) @extern("__divti3") @weak @nostrip
|
||||
fn int128 __divti3(int128 a, int128 b) @cname("__divti3") @weak @nostrip
|
||||
{
|
||||
int128 sign_a = a >> 127; // -1 : 0
|
||||
int128 sign_b = b >> 127; // -1 : 0
|
||||
@@ -182,17 +182,17 @@ macro uint128 @__udivmodti4(uint128 a, uint128 b, bool $return_rem)
|
||||
$endif
|
||||
}
|
||||
|
||||
fn uint128 __umodti3(uint128 n, uint128 d) @extern("__umodti3") @weak @nostrip
|
||||
fn uint128 __umodti3(uint128 n, uint128 d) @cname("__umodti3") @weak @nostrip
|
||||
{
|
||||
return @__udivmodti4(n, d, true);
|
||||
}
|
||||
|
||||
fn uint128 __udivti3(uint128 n, uint128 d) @extern("__udivti3") @weak @nostrip
|
||||
fn uint128 __udivti3(uint128 n, uint128 d) @cname("__udivti3") @weak @nostrip
|
||||
{
|
||||
return @__udivmodti4(n, d, false);
|
||||
}
|
||||
|
||||
fn int128 __modti3(int128 a, int128 b) @extern("__modti3") @weak @nostrip
|
||||
fn int128 __modti3(int128 a, int128 b) @cname("__modti3") @weak @nostrip
|
||||
{
|
||||
int128 sign = b >> 127;
|
||||
uint128 unsigned_b = (uint128)(b ^ sign) + (-sign);
|
||||
@@ -212,7 +212,7 @@ union Int128bits @private
|
||||
uint128 all;
|
||||
}
|
||||
|
||||
fn uint128 __lshrti3(uint128 a, uint b) @extern("__lshrti3") @weak @nostrip
|
||||
fn uint128 __lshrti3(uint128 a, uint b) @cname("__lshrti3") @weak @nostrip
|
||||
{
|
||||
Int128bits result;
|
||||
result.all = a;
|
||||
@@ -230,7 +230,7 @@ fn uint128 __lshrti3(uint128 a, uint b) @extern("__lshrti3") @weak @nostrip
|
||||
return result.all;
|
||||
}
|
||||
|
||||
fn int128 __ashrti3(int128 a, uint b) @extern("__ashrti3") @weak @nostrip
|
||||
fn int128 __ashrti3(int128 a, uint b) @cname("__ashrti3") @weak @nostrip
|
||||
{
|
||||
Int128bits result;
|
||||
result.all = a;
|
||||
@@ -248,7 +248,7 @@ fn int128 __ashrti3(int128 a, uint b) @extern("__ashrti3") @weak @nostrip
|
||||
return result.all;
|
||||
}
|
||||
|
||||
fn int128 __ashlti3(int128 a, uint b) @extern("__ashlti3") @weak @nostrip
|
||||
fn int128 __ashlti3(int128 a, uint b) @cname("__ashlti3") @weak @nostrip
|
||||
{
|
||||
Int128bits result;
|
||||
result.all = a;
|
||||
@@ -287,7 +287,7 @@ fn int128 __mulddi3(ulong a, ulong b) @private
|
||||
return r.all;
|
||||
}
|
||||
|
||||
fn int128 __multi3(int128 a, int128 b) @extern("__multi3") @weak @nostrip
|
||||
fn int128 __multi3(int128 a, int128 b) @cname("__multi3") @weak @nostrip
|
||||
{
|
||||
Int128bits x = { .all = a };
|
||||
Int128bits y = { .all = b };
|
||||
@@ -296,14 +296,14 @@ fn int128 __multi3(int128 a, int128 b) @extern("__multi3") @weak @nostrip
|
||||
return r.all;
|
||||
}
|
||||
|
||||
fn float __floattisf(int128 a) @extern("__floattisf") @weak @nostrip => float_from_i128(float, a);
|
||||
fn double __floattidf(int128 a) @extern("__floattidf") @weak @nostrip => float_from_i128(double, a);
|
||||
fn float __floatuntisf(uint128 a) @extern("__floatuntisf") @weak @nostrip => float_from_u128(float, a);
|
||||
fn double __floatuntidf(uint128 a) @extern("__floatuntidf") @weak @nostrip => float_from_u128(double, a);
|
||||
fn uint128 __fixunsdfti(double a) @weak @extern("__fixunsdfti") @nostrip => fixuint(a);
|
||||
fn uint128 __fixunssfti(float a) @weak @extern("__fixunssfti") @nostrip => fixuint(a);
|
||||
fn int128 __fixdfti(double a) @weak @extern("__fixdfti") @nostrip => fixint(a);
|
||||
fn int128 __fixsfti(float a) @weak @extern("__fixsfti") @nostrip => fixint(a);
|
||||
fn float __floattisf(int128 a) @cname("__floattisf") @weak @nostrip => float_from_i128(float, a);
|
||||
fn double __floattidf(int128 a) @cname("__floattidf") @weak @nostrip => float_from_i128(double, a);
|
||||
fn float __floatuntisf(uint128 a) @cname("__floatuntisf") @weak @nostrip => float_from_u128(float, a);
|
||||
fn double __floatuntidf(uint128 a) @cname("__floatuntidf") @weak @nostrip => float_from_u128(double, a);
|
||||
fn uint128 __fixunsdfti(double a) @weak @cname("__fixunsdfti") @nostrip => fixuint(a);
|
||||
fn uint128 __fixunssfti(float a) @weak @cname("__fixunssfti") @nostrip => fixuint(a);
|
||||
fn int128 __fixdfti(double a) @weak @cname("__fixdfti") @nostrip => fixint(a);
|
||||
fn int128 __fixsfti(float a) @weak @cname("__fixsfti") @nostrip => fixint(a);
|
||||
|
||||
|
||||
macro float_from_i128($Type, a) @private
|
||||
|
||||
@@ -8,7 +8,7 @@ macro force_eval_add(x, v)
|
||||
@volatile_store(temp, x + v);
|
||||
}
|
||||
|
||||
fn double __roundeven(double x) @extern("roundeven") @weak @nostrip
|
||||
fn double __roundeven(double x) @cname("roundeven") @weak @nostrip
|
||||
{
|
||||
ulong u = bitcast(x, ulong);
|
||||
int e = (int)((u >> 52) & 0x7ff);
|
||||
@@ -42,7 +42,7 @@ fn double __roundeven(double x) @extern("roundeven") @weak @nostrip
|
||||
return y;
|
||||
}
|
||||
|
||||
fn float __roundevenf(float x) @extern("roundevenf") @weak @nostrip
|
||||
fn float __roundevenf(float x) @cname("roundevenf") @weak @nostrip
|
||||
{
|
||||
uint u = bitcast(x, uint);
|
||||
int e = (u >> 23) & 0xff;
|
||||
@@ -75,7 +75,7 @@ fn float __roundevenf(float x) @extern("roundevenf") @weak @nostrip
|
||||
return y;
|
||||
}
|
||||
|
||||
fn double __powidf2(double a, int b) @extern("__powidf2") @weak @nostrip
|
||||
fn double __powidf2(double a, int b) @cname("__powidf2") @weak @nostrip
|
||||
{
|
||||
bool recip = b < 0;
|
||||
double r = 1;
|
||||
|
||||
@@ -41,8 +41,8 @@ fn double double[<3>].angle(self, double[<3>] v2) => angle3(self, v2);
|
||||
fn float[<3>] float[<3>].refract(self, float[<3>] n, float r) => refract3(self, n, r);
|
||||
fn double[<3>] double[<3>].refract(self, double[<3>] n, double r) => refract3(self, n, r);
|
||||
|
||||
fn float[<3>] float[<3>].rotate_quat(self, Quaternionf q) => rotate_by_quat3(self, q);
|
||||
fn double[<3>] double[<3>].rotate_quat(self, Quaternion q) => rotate_by_quat3(self, q);
|
||||
fn float[<3>] float[<3>].rotate_quat(self, Quaternionf q) => q * self;
|
||||
fn double[<3>] double[<3>].rotate_quat(self, Quaternion q) => q * self;
|
||||
|
||||
fn float[<3>] float[<3>].rotate_axis(self, float[<3>] axis, float angle) => rotate_axis_angle(self, axis, angle);
|
||||
fn double[<3>] double[<3>].rotate_axis(self, double[<3>] axis, double angle) => rotate_axis_angle(self, axis, angle);
|
||||
@@ -144,21 +144,6 @@ macro void ortho_normalize3(v1, v2) @private
|
||||
*v2 = v1n.cross(vn1);
|
||||
}
|
||||
|
||||
macro rotate_by_quat3(v, q) @private
|
||||
{
|
||||
return ($typeof(v)){
|
||||
v[0] * (q.i * q.i + q.l * q.l - q.j * q.j - q.k * q.k)
|
||||
+ v[1] * (2 * q.i * q.j - 2 * q.l * q.k)
|
||||
+ v[2] * (2 * q.i * q.k - 2 * q.l * q.j),
|
||||
v[0] * (2 * q.l * q.k + 2 * q.i * q.j)
|
||||
+ v[1] * (q.l * q.l - q.i * q.i + q.j * q.j - q.k * q.k)
|
||||
+ v[2] * (-2 * q.l * q.i + 2 * q.j * q.k),
|
||||
v[0] * (-2 * q.l * q.j + 2 * q.i * q.k)
|
||||
+ v[1] * (2 * q.l * q.i + 2 * q.j * q.k)
|
||||
+ v[2] * (q.l * q.l - q.i * q.i - q.j * q.j + q.k * q.k)
|
||||
};
|
||||
}
|
||||
|
||||
macro rotate_axis_angle(v, axis, angle) @private
|
||||
{
|
||||
axis = axis.normalize();
|
||||
|
||||
@@ -22,6 +22,7 @@ extern fn CInt bind(NativeSocket socket, SockAddrPtr address, Socklen_t address_
|
||||
extern fn CInt listen(NativeSocket socket, CInt backlog);
|
||||
extern fn NativeSocket accept(NativeSocket socket, SockAddrPtr address, Socklen_t* address_len);
|
||||
extern fn CInt poll(Posix_pollfd* fds, Posix_nfds_t nfds, CInt timeout);
|
||||
extern fn CInt socketpair(AIFamily domain, AISockType type, CInt protocol, NativeSocket[2]* sv);
|
||||
|
||||
const CUShort POLLIN = 0x0001;
|
||||
const CUShort POLLPRI = 0x0002;
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
module std::net::os @if(env::WIN32);
|
||||
import std::os, std::io, libc;
|
||||
import std::os, std::io, libc, std::thread;
|
||||
import std::core::mem;
|
||||
import std::os::win32;
|
||||
|
||||
|
||||
|
||||
const AIFamily PLATFORM_AF_IPX = 6;
|
||||
const AIFamily PLATFORM_AF_APPLETALK = 16;
|
||||
@@ -21,6 +25,33 @@ extern fn int connect(NativeSocket, SockAddrPtr address, Socklen_t address_len);
|
||||
extern fn int bind(NativeSocket, SockAddrPtr address, Socklen_t address_len);
|
||||
extern fn int listen(NativeSocket, int backlog);
|
||||
extern fn NativeSocket accept(NativeSocket, SockAddrPtr address, Socklen_t* address_len);
|
||||
extern fn CInt getsockname(NativeSocket socket, SockAddrPtr address, Socklen_t* address_len);
|
||||
|
||||
char[408] wsa_data @local;
|
||||
int wsa_init @local;
|
||||
|
||||
macro void? start_wsa()
|
||||
{
|
||||
if (mem::compare_exchange(&wsa_init, 0, 1) == 0)
|
||||
{
|
||||
Win32_WORD version = 0x0202;
|
||||
CInt wsa_error = win32::wsaStartup(version, &wsa_data);
|
||||
if (wsa_error > 0)
|
||||
{
|
||||
mem::@atomic_store(wsa_init, 0);
|
||||
return os::socket_error()?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn void close_wsa()
|
||||
{
|
||||
if (mem::compare_exchange(&wsa_init, 1, 0) == 1)
|
||||
{
|
||||
win32::wsaCleanup();
|
||||
mem::@atomic_store(wsa_init, 0);
|
||||
}
|
||||
}
|
||||
|
||||
macro bool NativeSocket.is_valid(self)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
module std::net @if(os::SUPPORTS_INET);
|
||||
import std::time, libc, std::os;
|
||||
import std::core::env;
|
||||
import std::net::os;
|
||||
|
||||
|
||||
|
||||
macro void? apply_sockoptions(sockfd, options) @private
|
||||
{
|
||||
@@ -9,6 +13,9 @@ macro void? apply_sockoptions(sockfd, options) @private
|
||||
|
||||
fn Socket? connect_from_addrinfo(AddrInfo* addrinfo, SocketOption[] options) @private
|
||||
{
|
||||
$if env::WIN32:
|
||||
os::start_wsa()!;
|
||||
$endif
|
||||
@loop_over_ai(addrinfo; NativeSocket sockfd, AddrInfo* ai)
|
||||
{
|
||||
apply_sockoptions(sockfd, options)!;
|
||||
@@ -37,6 +44,9 @@ fn bool last_error_is_delayed_connect()
|
||||
|
||||
fn Socket? connect_with_timeout_from_addrinfo(AddrInfo* addrinfo, SocketOption[] options, Duration timeout) @private
|
||||
{
|
||||
$if env::WIN32:
|
||||
os::start_wsa()!;
|
||||
$endif
|
||||
Clock c = 0;
|
||||
@loop_over_ai(addrinfo; NativeSocket sockfd, AddrInfo* ai)
|
||||
{
|
||||
@@ -82,6 +92,9 @@ fn Socket? connect_with_timeout_from_addrinfo(AddrInfo* addrinfo, SocketOption[]
|
||||
|
||||
fn Socket? connect_async_from_addrinfo(AddrInfo* addrinfo, SocketOption[] options) @private
|
||||
{
|
||||
$if env::WIN32:
|
||||
os::start_wsa()!;
|
||||
$endif
|
||||
@loop_over_ai(addrinfo; NativeSocket sockfd, AddrInfo* ai)
|
||||
{
|
||||
apply_sockoptions(sockfd, options)!;
|
||||
@@ -98,6 +111,9 @@ fn Socket? connect_async_from_addrinfo(AddrInfo* addrinfo, SocketOption[] option
|
||||
|
||||
macro void @network_loop_over_ai(network, host, port; @body(fd, ai)) @private
|
||||
{
|
||||
$if env::WIN32:
|
||||
os::start_wsa()!;
|
||||
$endif
|
||||
AddrInfo* ai = network.addrinfo(host, port)!;
|
||||
AddrInfo* first = ai;
|
||||
defer os::freeaddrinfo(first);
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
module std::net::tcp @if(os::SUPPORTS_INET);
|
||||
import std::net @public;
|
||||
import std::time, libc;
|
||||
import std::os::win32;
|
||||
import std::core::env;
|
||||
import std::net::os;
|
||||
|
||||
|
||||
|
||||
typedef TcpSocket = inline Socket;
|
||||
typedef TcpServerSocket = inline Socket;
|
||||
@@ -44,6 +49,9 @@ fn TcpSocket? accept(TcpServerSocket* server_socket)
|
||||
{
|
||||
TcpSocket socket;
|
||||
socket.ai_addrlen = socket.ai_addr_storage.len;
|
||||
$if env::WIN32:
|
||||
os::start_wsa()!;
|
||||
$endif
|
||||
socket.sock = os::accept(server_socket.sock, (SockAddrPtr)&socket.ai_addr_storage, &socket.ai_addrlen);
|
||||
if (!socket.sock.is_valid()) return net::ACCEPT_FAILED?;
|
||||
return socket;
|
||||
@@ -51,6 +59,9 @@ fn TcpSocket? accept(TcpServerSocket* server_socket)
|
||||
|
||||
fn TcpServerSocket? listen_to(AddrInfo* ai, uint backlog, SocketOption... options)
|
||||
{
|
||||
$if env::WIN32:
|
||||
os::start_wsa()!;
|
||||
$endif
|
||||
net::@loop_over_ai(ai; NativeSocket sockfd, AddrInfo* ai_candidate)
|
||||
{
|
||||
net::apply_sockoptions(sockfd, options)!;
|
||||
@@ -60,4 +71,55 @@ fn TcpServerSocket? listen_to(AddrInfo* ai, uint backlog, SocketOption... option
|
||||
return os::socket_error()?;
|
||||
}
|
||||
|
||||
struct TcpSocketPair
|
||||
{
|
||||
TcpSocket send;
|
||||
TcpSocket recv;
|
||||
}
|
||||
|
||||
fn TcpSocketPair*? TcpSocketPair.init(&self)
|
||||
{
|
||||
$if env::WIN32:
|
||||
os::start_wsa()!;
|
||||
|
||||
TcpServerSocket listen_sock = tcp::listen("127.0.0.1", 0, 0)!;
|
||||
|
||||
TcpSocket listen_sock_info;
|
||||
listen_sock_info.ai_addrlen = listen_sock.ai_addr_storage.len;
|
||||
|
||||
int sock_result = os::getsockname(listen_sock.sock, (SockAddrPtr) &listen_sock_info.ai_addr_storage, &listen_sock_info.ai_addrlen);
|
||||
if (sock_result < 0) return os::socket_error()?;
|
||||
|
||||
char[] listen_port_bytes = listen_sock_info.ai_addr_storage[2:2];
|
||||
char msb = listen_port_bytes[0];
|
||||
char lsb = listen_port_bytes[1];
|
||||
int listen_port = (msb << 8) | lsb;
|
||||
|
||||
defer (void)listen_sock.close();
|
||||
TcpSocket tcp_send_sock = tcp::connect_async("127.0.0.1", listen_port)!;
|
||||
TcpSocket tcp_recv_sock = tcp::accept(&listen_sock)!;
|
||||
|
||||
$else
|
||||
NativeSocket[2] sockets;
|
||||
isz sockpair_result = os::socketpair(os::AF_UNIX, os::SOCK_STREAM, 0, &sockets);
|
||||
if (sockpair_result < 0) return os::socket_error()?;
|
||||
|
||||
Socket send_sock = { .sock = sockets[0] };
|
||||
TcpSocket tcp_send_sock = (TcpSocket) send_sock;
|
||||
|
||||
Socket recv_sock = { .sock = sockets[1] };
|
||||
TcpSocket tcp_recv_sock = (TcpSocket) recv_sock;
|
||||
$endif
|
||||
|
||||
*self = { .send = tcp_send_sock, .recv = tcp_recv_sock };
|
||||
return self;
|
||||
}
|
||||
|
||||
fn void? TcpSocketPair.destroy(&self)
|
||||
{
|
||||
{
|
||||
defer catch (void)self.recv.close();
|
||||
self.send.close()!;
|
||||
}
|
||||
self.recv.close()!;
|
||||
}
|
||||
|
||||
@@ -40,30 +40,30 @@ struct LogMessage @packed
|
||||
ZString message;
|
||||
}
|
||||
|
||||
extern fn CInt log_write(LogPriority prio, ZString tag, ZString text) @extern("__android_log_write");
|
||||
extern fn CInt log_print(LogPriority prio, ZString tag, ZString fmt, ...) @extern("__android_log_print");
|
||||
extern fn void log_assert(ZString cond, ZString tag, ZString fmt, ...) @extern("__android_log_assert");
|
||||
extern fn CInt log_write(LogPriority prio, ZString tag, ZString text) @cname("__android_log_write");
|
||||
extern fn CInt log_print(LogPriority prio, ZString tag, ZString fmt, ...) @cname("__android_log_print");
|
||||
extern fn void log_assert(ZString cond, ZString tag, ZString fmt, ...) @cname("__android_log_assert");
|
||||
|
||||
fn bool log_id_is_valid(LogId id)
|
||||
{
|
||||
return id >= LOG_ID_MIN && id < LOG_ID_MAX;
|
||||
}
|
||||
|
||||
extern fn CInt log_buf_write(CInt bufID, CInt prio, ZString tag, ZString text) @extern("__android_log_buf_write");
|
||||
extern fn CInt log_buf_print(CInt bufID, CInt prio, ZString tag, ZString fmt, ...) @extern("__android_log_buf_print");
|
||||
extern fn CInt log_buf_write(CInt bufID, CInt prio, ZString tag, ZString text) @cname("__android_log_buf_write");
|
||||
extern fn CInt log_buf_print(CInt bufID, CInt prio, ZString tag, ZString fmt, ...) @cname("__android_log_buf_print");
|
||||
|
||||
alias LoggerFunction = fn void(LogMessage* log_message);
|
||||
alias AborterFunction = fn void(ZString abort_message);
|
||||
|
||||
extern fn void log_write_log_message(LogMessage log_message) @extern("__android_log_write_log_message");
|
||||
extern fn void log_set_logger(LoggerFunction logger) @extern("__android_log_set_logger");
|
||||
extern fn void log_logd_logger(LogMessage log_message) @extern("__android_log_logd_logger");
|
||||
extern fn void log_stderr_logger(LogMessage log_message) @extern("__android_log_stderr_logger");
|
||||
extern fn void log_set_aborter(AborterFunction aborter) @extern("__android_log_set_aborter");
|
||||
extern fn void log_call_aborter(ZString abort_message) @extern("__android_log_call_aborter");
|
||||
extern fn void log_default_aborter(ZString abort_message) @extern("__android_log_default_aborter");
|
||||
extern fn CInt log_is_loggable(CInt prio, ZString tag, CInt default_prio) @extern("__android_log_is_loggable");
|
||||
extern fn CInt log_is_loggable_len(CInt prio, ZString tag, isz len, CInt default_prio) @extern("__android_log_is_loggable_len");
|
||||
extern fn CInt log_set_minimum_priority(CInt priority) @extern("__android_log_set_minimum_priority");
|
||||
extern fn CInt log_get_minimum_priority() @extern("__android_log_get_minimum_priority");
|
||||
extern fn void log_set_default_tag(ZString tag) @extern("__android_log_set_default_tag");
|
||||
extern fn void log_write_log_message(LogMessage log_message) @cname("__android_log_write_log_message");
|
||||
extern fn void log_set_logger(LoggerFunction logger) @cname("__android_log_set_logger");
|
||||
extern fn void log_logd_logger(LogMessage log_message) @cname("__android_log_logd_logger");
|
||||
extern fn void log_stderr_logger(LogMessage log_message) @cname("__android_log_stderr_logger");
|
||||
extern fn void log_set_aborter(AborterFunction aborter) @cname("__android_log_set_aborter");
|
||||
extern fn void log_call_aborter(ZString abort_message) @cname("__android_log_call_aborter");
|
||||
extern fn void log_default_aborter(ZString abort_message) @cname("__android_log_default_aborter");
|
||||
extern fn CInt log_is_loggable(CInt prio, ZString tag, CInt default_prio) @cname("__android_log_is_loggable");
|
||||
extern fn CInt log_is_loggable_len(CInt prio, ZString tag, isz len, CInt default_prio) @cname("__android_log_is_loggable_len");
|
||||
extern fn CInt log_set_minimum_priority(CInt priority) @cname("__android_log_set_minimum_priority");
|
||||
extern fn CInt log_get_minimum_priority() @cname("__android_log_get_minimum_priority");
|
||||
extern fn void log_set_default_tag(ZString tag) @cname("__android_log_set_default_tag");
|
||||
|
||||
@@ -10,9 +10,9 @@ macro void* CFAllocatorRef.alloc(CFAllocatorRef allocator, usz size) => macos_CF
|
||||
macro usz CFAllocatorRef.get_preferred_size(CFAllocatorRef allocator, usz req_size) => macos_CFAllocatorGetPreferredSizeForSize(allocator, req_size, 0);
|
||||
macro void CFAllocatorRef.set_default(CFAllocatorRef allocator) => macos_CFAllocatorSetDefault(allocator);
|
||||
|
||||
extern fn CFAllocatorRef macos_CFAllocatorCreate(CFAllocatorRef allocator, CFAllocatorContextRef context) @extern("CFAllocatorCreate") @builtin;
|
||||
extern fn void macos_CFAllocatorDeallocate(CFAllocatorRef allocator, void* ptr) @extern("CFAllocatorDeallocate") @builtin;
|
||||
extern fn CFAllocatorRef macos_CFAllocatorGetDefault() @extern("CFAllocatorGetDefault") @builtin;
|
||||
extern fn void macos_CFAllocatorSetDefault(CFAllocatorRef allocator) @extern("CFAllocatorSetDefault") @builtin;
|
||||
extern fn void* macos_CFAllocatorAllocate(CFAllocatorRef allocator, CFIndex size, CFOptionFlags hint) @extern("CFAllocatorAllocate") @builtin;
|
||||
extern fn CFIndex macos_CFAllocatorGetPreferredSizeForSize(CFAllocatorRef allocator, CFIndex size, CFOptionFlags hint) @extern("CFAllocatorGetPreferredSizeForSize") @builtin;
|
||||
extern fn CFAllocatorRef macos_CFAllocatorCreate(CFAllocatorRef allocator, CFAllocatorContextRef context) @cname("CFAllocatorCreate") @builtin;
|
||||
extern fn void macos_CFAllocatorDeallocate(CFAllocatorRef allocator, void* ptr) @cname("CFAllocatorDeallocate") @builtin;
|
||||
extern fn CFAllocatorRef macos_CFAllocatorGetDefault() @cname("CFAllocatorGetDefault") @builtin;
|
||||
extern fn void macos_CFAllocatorSetDefault(CFAllocatorRef allocator) @cname("CFAllocatorSetDefault") @builtin;
|
||||
extern fn void* macos_CFAllocatorAllocate(CFAllocatorRef allocator, CFIndex size, CFOptionFlags hint) @cname("CFAllocatorAllocate") @builtin;
|
||||
extern fn CFIndex macos_CFAllocatorGetPreferredSizeForSize(CFAllocatorRef allocator, CFIndex size, CFOptionFlags hint) @cname("CFAllocatorGetPreferredSizeForSize") @builtin;
|
||||
|
||||
@@ -6,13 +6,13 @@ typedef CFArrayCallBacksRef = void*;
|
||||
typedef CFMutableArray = inline CFArray;
|
||||
typedef CFMutableArrayRef = CFMutableArray*;
|
||||
|
||||
extern fn CFIndex CFArray.getCount(&self) @extern("CFArrayGetCount");
|
||||
extern fn void* CFArray.getValueAtIndex(&self, CFIndex i) @extern("CFArrayGetValueAtIndex");
|
||||
extern fn CFIndex CFArray.getCount(&self) @cname("CFArrayGetCount");
|
||||
extern fn void* CFArray.getValueAtIndex(&self, CFIndex i) @cname("CFArrayGetValueAtIndex");
|
||||
|
||||
extern fn CFArrayRef macos_CFArrayCreate(CFAllocatorRef allocator, void** values, CFIndex num_values, CFArrayCallBacksRef callBacks) @extern("CFArrayCreate") @builtin;
|
||||
extern fn CFArrayRef macos_CFArrayCopy(CFAllocatorRef allocator, CFArrayRef array) @extern("CFArrayCopy") @builtin;
|
||||
extern fn void CFMutableArray.appendArray(&self, CFArrayRef otherArray, CFRange otherRange) @extern("CFArrayAppendArray");
|
||||
extern fn void CFMutableArray.appendValue(&self, void *value) @extern("CFArrayAppendValue");
|
||||
extern fn CFArrayRef macos_CFArrayCreate(CFAllocatorRef allocator, void** values, CFIndex num_values, CFArrayCallBacksRef callBacks) @cname("CFArrayCreate") @builtin;
|
||||
extern fn CFArrayRef macos_CFArrayCopy(CFAllocatorRef allocator, CFArrayRef array) @cname("CFArrayCopy") @builtin;
|
||||
extern fn void CFMutableArray.appendArray(&self, CFArrayRef otherArray, CFRange otherRange) @cname("CFArrayAppendArray");
|
||||
extern fn void CFMutableArray.appendValue(&self, void *value) @cname("CFArrayAppendValue");
|
||||
|
||||
extern fn CFMutableArrayRef macos_CFArrayCreateMutable(CFAllocatorRef allocator, CFIndex capacity, CFArrayCallBacksRef callBacks) @extern("CFArrayCreateMutable") @builtin;
|
||||
extern fn CFMutableArrayRef macos_CFArrayCreateMutable(CFAllocatorRef allocator, CFIndex capacity, CFArrayCallBacksRef callBacks) @cname("CFArrayCreateMutable") @builtin;
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
module std::os::darwin::cocoa @if(env::OS_TYPE == MACOS) @link("Cocoa.framework");
|
||||
|
||||
extern fn int nsApplicationMain(int argc, char **argv) @extern("NSApplicationMain");
|
||||
extern fn int nsApplicationMain(int argc, char **argv) @cname("NSApplicationMain");
|
||||
|
||||
@@ -13,12 +13,32 @@ struct CFRange
|
||||
CFIndex length;
|
||||
}
|
||||
|
||||
extern fn ZString CFString.getCStringPtr(&self, CFStringEncoding encoding) @extern("CFStringGetCStringPtr");
|
||||
extern fn ZString CFString.getCString(&self, char* buffer, usz len, CFStringEncoding encoding) @extern("CFStringGetCString");
|
||||
alias CGFloat = $typefrom(env::ARCH_64_BIT ??? double : float);
|
||||
|
||||
extern fn CFTypeRef CFType.retain(&self) @extern("CFRetain");
|
||||
extern fn void CFType.release(&self) @extern("CFRelease");
|
||||
extern fn CFIndex CFType.getRetainCount(&self) @extern("CFGetRetainCount");
|
||||
struct CGPoint
|
||||
{
|
||||
CGFloat x;
|
||||
CGFloat y;
|
||||
}
|
||||
|
||||
struct CGSize
|
||||
{
|
||||
CGFloat width;
|
||||
CGFloat height;
|
||||
}
|
||||
|
||||
struct CGRect
|
||||
{
|
||||
CGPoint origin;
|
||||
CGSize size;
|
||||
}
|
||||
|
||||
extern fn ZString CFString.getCStringPtr(&self, CFStringEncoding encoding) @cname("CFStringGetCStringPtr");
|
||||
extern fn ZString CFString.getCString(&self, char* buffer, usz len, CFStringEncoding encoding) @cname("CFStringGetCString");
|
||||
|
||||
extern fn CFTypeRef CFType.retain(&self) @cname("CFRetain");
|
||||
extern fn void CFType.release(&self) @cname("CFRelease");
|
||||
extern fn CFIndex CFType.getRetainCount(&self) @cname("CFGetRetainCount");
|
||||
|
||||
enum CFStringEncoding : const uint
|
||||
{
|
||||
|
||||
@@ -37,7 +37,7 @@ const HW_L3CACHESIZE = 22; /* int: L3 Cache Size in Bytes */
|
||||
const HW_MAXID = 23; /* number of valid hw ids */
|
||||
|
||||
extern fn CInt sysctl(CInt *name, CUInt namelen, void *oldp, usz *oldlenp, void *newp, usz newlen);
|
||||
extern fn CInt darwin_NSGetExecutablePath(char* buffer, uint *size) @extern("_NSGetExecutablePath") @builtin;
|
||||
extern fn CInt darwin_NSGetExecutablePath(char* buffer, uint *size) @cname("_NSGetExecutablePath") @builtin;
|
||||
extern fn Darwin_segment_command_64* getsegbyname(ZString segname);
|
||||
extern fn uint _dyld_image_count();
|
||||
extern fn ZString _dyld_get_image_name(uint image_index);
|
||||
@@ -88,8 +88,8 @@ fn String? executable_path()
|
||||
char[4096] buf;
|
||||
uint temp_len = buf.len;
|
||||
if (darwin_NSGetExecutablePath(&buf, &temp_len) < 0) return NOT_FOUND?;
|
||||
path[:len] = buf[:len];
|
||||
len = (int)((ZString)&buf).len();
|
||||
path[:len] = buf[:len];
|
||||
}
|
||||
return (String)path[:len];
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ enum NSSearchPathDirectory : const NSUInteger
|
||||
}
|
||||
|
||||
// real signature in Foundation
|
||||
extern fn CFArrayRef nsSearchPathForDirectoriesInDomains(NSSearchPathDirectory directory, NSSearchPathDomainMask domainMask, bool expandTilde) @extern("NSSearchPathForDirectoriesInDomains");
|
||||
extern fn CFArrayRef nsSearchPathForDirectoriesInDomains(NSSearchPathDirectory directory, NSSearchPathDomainMask domainMask, bool expandTilde) @cname("NSSearchPathForDirectoriesInDomains");
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ macro bool ObjcSelector.equals(ObjcSelector a, ObjcSelector b) => a == b;
|
||||
macro bool ObjcClass.equals(ObjcClass a, ObjcClass b) => a == b;
|
||||
|
||||
fn ObjcId alloc(ObjcClass cls) => objc::msg_send(cls, SendVoid, "alloc");
|
||||
fn void release(ObjcId id) => objc::msg_send(id, SendVoid, "release");
|
||||
fn void release(ObjcId id) => objc::msg_send(id, SendVoid, "release");
|
||||
|
||||
alias NSUInteger = $typefrom(env::ARCH_64_BIT ??? ulong : uint);
|
||||
alias NSInteger = $typefrom(env::ARCH_64_BIT ??? long : int);
|
||||
@@ -38,7 +38,7 @@ macro ObjcClass[] class_get_list(Allocator allocator)
|
||||
return entries;
|
||||
}
|
||||
|
||||
extern fn void msgSend(...) @extern("objc_msgSend") @builtin;
|
||||
extern fn void msgSend(...) @cname("objc_msgSend") @builtin;
|
||||
extern fn ObjcSelector sel_getUid(ZString);
|
||||
|
||||
macro msg_send(id, $FunctionType, ZString $selector, ...)
|
||||
@@ -55,9 +55,9 @@ macro void @autoreleasepool(;@body())
|
||||
|
||||
extern fn void* objc_autoreleasePoolPush();
|
||||
extern fn void objc_autoreleasePoolPop(void* context);
|
||||
extern fn ObjcClass getClass(ZString name) @extern("objc_getClass");
|
||||
extern fn int getClassList(ObjcClass* buffer, int buffer_count) @extern("objc_getClassList");
|
||||
extern fn ObjcClass lookUpClass(ZString name) @extern("objc_lookUpClass") @builtin;
|
||||
extern fn ObjcClass getClass(ZString name) @cname("objc_getClass");
|
||||
extern fn int getClassList(ObjcClass* buffer, int buffer_count) @cname("objc_getClassList");
|
||||
extern fn ObjcClass lookUpClass(ZString name) @cname("objc_lookUpClass") @builtin;
|
||||
|
||||
extern fn ZString class_getName(ObjcClass cls);
|
||||
extern fn ObjcClass class_getSuperclass(ObjcClass cls);
|
||||
@@ -67,24 +67,35 @@ extern fn ObjcSelector sel_registerName(ZString str);
|
||||
extern fn bool class_addIvar(ObjcClass cls, ZString name, int size, double alignment, ZString types);
|
||||
extern fn bool class_addMethod(ObjcClass cls, ObjcSelector name, void* imp, ZString types);
|
||||
|
||||
extern fn ObjcIvar getInstanceVariable(ObjcId id, ZString name, void* outValue) @extern("object_getInstanceVariable");
|
||||
extern fn ObjcIvar setInstanceVariable(ObjcId id, ZString name, void* value) @extern("object_setInstanceVariable");
|
||||
extern fn ObjcClass allocateClassPair(ObjcClass cls, ZString name, uint extraBytes) @extern("objc_allocateClassPair");
|
||||
extern fn ObjcIvar getInstanceVariable(ObjcId id, ZString name, void* outValue) @cname("object_getInstanceVariable");
|
||||
extern fn ObjcIvar setInstanceVariable(ObjcId id, ZString name, void* value) @cname("object_setInstanceVariable");
|
||||
extern fn ObjcClass allocateClassPair(ObjcClass cls, ZString name, uint extraBytes) @cname("objc_allocateClassPair");
|
||||
extern fn void registerClassPair(ObjcClass cls) @cname("objc_registerClassPair");
|
||||
|
||||
enum StatusItemLength : (double val)
|
||||
module std::os::macos::objc::ns @if(env::DARWIN) @link(env::DARWIN, "CoreFoundation.framework");
|
||||
import std::os::macos::cf;
|
||||
|
||||
enum StatusItemLength : (double val) @deprecated("Use NSStatusItemLength.")
|
||||
{
|
||||
VARIABLE = -1.0,
|
||||
SQUARE = -2.0,
|
||||
}
|
||||
|
||||
enum ApplicationActivationPolicy : (int val)
|
||||
enum ApplicationActivationPolicy : (int val) @deprecated("Use NSApplicationActivationPolicy.")
|
||||
{
|
||||
REGULAR = 0,
|
||||
ACCESSORY = 1,
|
||||
PROHIBITED = 2,
|
||||
}
|
||||
|
||||
enum WindowStyleMask : (int val)
|
||||
enum NSApplicationActivationPolicy : const inline NSInteger
|
||||
{
|
||||
REGULAR = 0,
|
||||
ACCESSORY = 1,
|
||||
PROHIBITED = 2,
|
||||
}
|
||||
|
||||
enum WindowStyleMask : (int val) @deprecated("Use NSWindowStyleMask.")
|
||||
{
|
||||
BORDERLESS = 0,
|
||||
TITLED = 1 << 0,
|
||||
@@ -101,14 +112,21 @@ enum WindowStyleMask : (int val)
|
||||
HUD_WINDOW = 1 << 13
|
||||
}
|
||||
|
||||
enum BackingStore : (int val)
|
||||
enum BackingStore : (int val) @deprecated("Use NSBackingStoreType.")
|
||||
{
|
||||
RETAINED = 0,
|
||||
NONRETAINED = 1,
|
||||
BUFFERED = 2
|
||||
}
|
||||
|
||||
enum EventType : (long val)
|
||||
enum NSBackingStoreType : const inline NSUInteger
|
||||
{
|
||||
RETAINED = 0,
|
||||
NONRETAINED = 1,
|
||||
BUFFERED = 2
|
||||
}
|
||||
|
||||
enum EventType : (long val) @deprecated("Use NSEventType.")
|
||||
{
|
||||
LEFT_MOUSE_DOWN = 1,
|
||||
LEFT_MOUSE_UP = 2,
|
||||
@@ -146,7 +164,45 @@ enum EventType : (long val)
|
||||
CHANGE_MODE = 38,
|
||||
}
|
||||
|
||||
fn EventType? event_type_from(int val)
|
||||
enum NSEventType : const inline NSUInteger
|
||||
{
|
||||
LEFT_MOUSE_DOWN = 1,
|
||||
LEFT_MOUSE_UP = 2,
|
||||
RIGHT_MOUSE_DOWN = 3,
|
||||
RIGHT_MOUSE_UP = 4,
|
||||
MOUSE_MOVED = 5,
|
||||
LEFT_MOUSE_DRAGGED = 6,
|
||||
RIGHT_MOUSE_DRAGGED = 7,
|
||||
MOUSE_ENTERED = 8,
|
||||
MOUSE_EXITED = 9,
|
||||
KEY_DOWN = 10,
|
||||
KEY_UP = 11,
|
||||
FLAGS_CHANGED = 12,
|
||||
APPKIT_DEFINED = 13,
|
||||
SYSTEM_DEFINED = 14,
|
||||
APPLICATION_DEFINED = 15,
|
||||
PERIODIC = 16,
|
||||
CURSOR_UPDATE = 17,
|
||||
SCROLL_WHEEL = 22,
|
||||
TABLET_POINT = 23,
|
||||
TABLET_PROXIMITY = 24,
|
||||
OTHER_MOUSE_DOWN = 25,
|
||||
OTHER_MOUSE_UP = 26,
|
||||
OTHER_MOUSE_DRAGGED = 27,
|
||||
GESTURE = 29,
|
||||
MAGNIFY = 30,
|
||||
SWIPE = 31,
|
||||
ROTATE = 18,
|
||||
BEGIN_GESTURE = 19,
|
||||
END_GESTURE = 20,
|
||||
SMART_MAGNIFY = 32,
|
||||
QUICK_LOOK = 33,
|
||||
PRESSURE = 34,
|
||||
DIRECT_TOUCH = 37,
|
||||
CHANGE_MODE = 38,
|
||||
}
|
||||
|
||||
fn EventType? event_type_from(int val) @deprecated("Use NSEventType directly.")
|
||||
{
|
||||
switch(val)
|
||||
{
|
||||
@@ -184,11 +240,11 @@ fn EventType? event_type_from(int val)
|
||||
case EventType.PRESSURE.val: return PRESSURE;
|
||||
case EventType.DIRECT_TOUCH.val: return DIRECT_TOUCH;
|
||||
case EventType.CHANGE_MODE.val: return CHANGE_MODE;
|
||||
default: return UNKNOWN_EVENT?;
|
||||
default: return objc::UNKNOWN_EVENT?;
|
||||
}
|
||||
}
|
||||
|
||||
enum EventMask : (long val)
|
||||
enum EventMask : (long val) @deprecated("Use NSEventMask.")
|
||||
{
|
||||
LEFT_MOUSE_DOWN = 1 << EventType.LEFT_MOUSE_DOWN.val,
|
||||
LEFT_MOUSE_UP = 1 << EventType.LEFT_MOUSE_UP.val,
|
||||
@@ -224,7 +280,48 @@ enum EventMask : (long val)
|
||||
ANY = long.max,
|
||||
}
|
||||
|
||||
enum EventModifierFlag : (int val)
|
||||
enum NSEventMask : const inline ulong
|
||||
{
|
||||
LEFT_MOUSE_DOWN = 1ul << NSEventType.LEFT_MOUSE_DOWN,
|
||||
LEFT_MOUSE_UP = 1ul << NSEventType.LEFT_MOUSE_UP,
|
||||
RIGHT_MOUSE_DOWN = 1ul << NSEventType.RIGHT_MOUSE_DOWN,
|
||||
RIGHT_MOUSE_UP = 1ul << NSEventType.RIGHT_MOUSE_UP,
|
||||
MOUSE_MOVED = 1ul << NSEventType.MOUSE_MOVED,
|
||||
LEFT_MOUSE_DRAGGED = 1ul << NSEventType.LEFT_MOUSE_DRAGGED,
|
||||
RIGHT_MOUSE_DRAGGED = 1ul << NSEventType.RIGHT_MOUSE_DRAGGED,
|
||||
MOUSE_ENTERED = 1ul << NSEventType.MOUSE_ENTERED,
|
||||
MOUSE_EXITED = 1ul << NSEventType.MOUSE_EXITED,
|
||||
KEY_DOWN = 1ul << NSEventType.KEY_DOWN,
|
||||
KEY_UP = 1ul << NSEventType.KEY_UP,
|
||||
FLAGS_CHANGED = 1ul << NSEventType.FLAGS_CHANGED,
|
||||
APPKIT_DEFINED = 1ul << NSEventType.APPKIT_DEFINED,
|
||||
SYSTEM_DEFINED = 1ul << NSEventType.SYSTEM_DEFINED,
|
||||
APPLICATION_DEFINED = 1ul << NSEventType.APPLICATION_DEFINED,
|
||||
PERIODIC = 1ul << NSEventType.PERIODIC,
|
||||
CURSOR_UPDATE = 1ul << NSEventType.CURSOR_UPDATE,
|
||||
ROTATE = 1ul << NSEventType.ROTATE,
|
||||
BEGIN_GESTURE = 1ul << NSEventType.BEGIN_GESTURE,
|
||||
END_GESTURE = 1ul << NSEventType.END_GESTURE,
|
||||
SCROLL_WHEEL = 1ul << NSEventType.SCROLL_WHEEL,
|
||||
TABLET_POINT = 1ul << NSEventType.TABLET_POINT,
|
||||
TABLET_PROXIMITY = 1ul << NSEventType.TABLET_PROXIMITY,
|
||||
OTHER_MOUSE_DOWN = 1ul << NSEventType.OTHER_MOUSE_DOWN,
|
||||
OTHER_MOUSE_UP = 1ul << NSEventType.OTHER_MOUSE_UP,
|
||||
OTHER_MOUSE_DRAGGED = 1ul << NSEventType.OTHER_MOUSE_DRAGGED,
|
||||
GESTURE = 1ul << NSEventType.GESTURE,
|
||||
MAGNIFY = 1ul << NSEventType.MAGNIFY,
|
||||
SWIPE = 1ul << NSEventType.SWIPE,
|
||||
SMART_MAGNIFY = 1ul << NSEventType.SMART_MAGNIFY,
|
||||
QUICK_LOOK = 1ul << NSEventType.QUICK_LOOK,
|
||||
PRESSURE = 1ul << NSEventType.PRESSURE,
|
||||
DIRECT_TOUCH = 1ul << NSEventType.DIRECT_TOUCH,
|
||||
CHANGE_MODE = 1ul << NSEventType.CHANGE_MODE,
|
||||
ANY = ulong.max,
|
||||
}
|
||||
|
||||
fn NSEventMask event_mask_from_type(NSEventType type) => (NSEventMask)1ul << type;
|
||||
|
||||
enum EventModifierFlag : (int val) @deprecated("Use NSEventModifierFlags.")
|
||||
{
|
||||
CAPS_LOCK = 1 << 16,
|
||||
SHIFT = 1 << 17,
|
||||
@@ -236,3 +333,85 @@ enum EventModifierFlag : (int val)
|
||||
HELP = 1 << 22,
|
||||
}
|
||||
|
||||
enum NSEventModifierFlags : const inline NSUInteger
|
||||
{
|
||||
CAPS_LOCK = 1 << 16,
|
||||
SHIFT = 1 << 17,
|
||||
CONTROL = 1 << 18,
|
||||
OPTION = 1 << 19,
|
||||
COMMAND = 1 << 20,
|
||||
NUMERIC_PAD = 1 << 21,
|
||||
HELP = 1 << 22,
|
||||
FUNCTION = 1 << 23,
|
||||
DEVICE_INDEPENDENT_FLAGS_MASK = 0xffff0000UL,
|
||||
}
|
||||
|
||||
enum NSWindowCollectionBehavior : const inline NSUInteger
|
||||
{
|
||||
DEFAULT = 0,
|
||||
CAN_JOIN_ALL_SPACES = 1 << 0,
|
||||
MOVE_TO_ACTIVE_SPACE = 1 << 1,
|
||||
MANAGED = 1 << 2,
|
||||
TRANSIENT = 1 << 3,
|
||||
STATIONARY = 1 << 4,
|
||||
PARTICIPATES_IN_CYCLE = 1 << 5,
|
||||
IGNORES_CYCLE = 1 << 6,
|
||||
FULL_SCREEN_PRIMARY = 1 << 7,
|
||||
FULL_SCREEN_AUXILIARY = 1 << 8,
|
||||
FULL_SCREEN_NONE = 1 << 9,
|
||||
FULL_SCREEN_ALLOWS_TILING = 1 << 11,
|
||||
FULL_SCREEN_DISALLOWS_TILING = 1 << 12,
|
||||
PRIMARY = 1 << 16,
|
||||
AUXILIARY = 1 << 17,
|
||||
CAN_JOIN_ALL_APPLICATIONS = 1 << 18,
|
||||
}
|
||||
|
||||
enum NSWindowLevel : const inline NSInteger
|
||||
{
|
||||
NORMAL = 0,
|
||||
FLOATING = 3,
|
||||
SUBMENU = 3,
|
||||
TORN_OFF_MENU = 3,
|
||||
MODAL_PANEL = 8,
|
||||
MAIN_MENU = 24,
|
||||
STATUS = 25,
|
||||
POP_UP_MENU = 101,
|
||||
SCREEN_SAVER = 1000,
|
||||
}
|
||||
|
||||
enum NSWindowStyleMask : const inline NSUInteger
|
||||
{
|
||||
BORDERLESS = 0,
|
||||
TITLED = 1 << 0,
|
||||
CLOSABLE = 1 << 1,
|
||||
MINIATURIZABLE = 1 << 2,
|
||||
RESIZABLE = 1 << 3,
|
||||
TEXTURED_BACKGROUND = 1 << 8,
|
||||
UNIFIED_TITLE_AND_TOOLBAR = 1 << 12,
|
||||
FULL_SCREEN = 1 << 14,
|
||||
FULL_SIZE_CONTENT_VIEW = 1 << 15,
|
||||
UTILITY_WINDOW = 1 << 4,
|
||||
DOC_MODAL_WINDOW = 1 << 6,
|
||||
NONACTIVATING_PANEL = 1 << 7,
|
||||
HUD_WINDOW = 1 << 13
|
||||
}
|
||||
|
||||
enum NSWindowTabbingMode : const inline NSInteger
|
||||
{
|
||||
AUTOMATIC = 0,
|
||||
DISALLOWED = 2,
|
||||
PREFERRED = 1,
|
||||
}
|
||||
|
||||
enum NSStatusItemLength : const inline CGFloat
|
||||
{
|
||||
VARIABLE = -1.0,
|
||||
SQUARE = -2.0
|
||||
}
|
||||
|
||||
enum NSApplicationTerminateReply : const inline NSUInteger
|
||||
{
|
||||
CANCEL = 0,
|
||||
NOW = 1,
|
||||
LATER = 2,
|
||||
}
|
||||
|
||||
44
lib/std/os/macos/process.c3
Normal file
44
lib/std/os/macos/process.c3
Normal file
@@ -0,0 +1,44 @@
|
||||
module std::os::darwin @if(env::DARWIN);
|
||||
|
||||
alias __Darwin_sigset_t = uint;
|
||||
alias __Darwin_size_t = usz;
|
||||
|
||||
struct __Darwin_arm_exception_state64
|
||||
{
|
||||
ulong __far; /* Virtual Fault Address */
|
||||
uint __esr; /* Exception syndrome */
|
||||
uint __exception; /* number of arm exception taken */
|
||||
}
|
||||
|
||||
struct __Darwin_arm_thread_state64
|
||||
{
|
||||
ulong[29] __x; /* General purpose registers x0-x28 */
|
||||
ulong __fp; /* Frame pointer x29 */
|
||||
ulong __lr; /* Link register x30 */
|
||||
ulong __sp; /* Stack pointer x31 */
|
||||
ulong __pc; /* Program counter */
|
||||
ulong __cpsr; /* Current program status register */
|
||||
ulong __pad; /* Same size for 32-bit or 64-bit clients */
|
||||
}
|
||||
|
||||
struct __Darwin_arm_neon_state64
|
||||
{
|
||||
uint128[32] __v;
|
||||
uint __fpsr;
|
||||
uint __fpcr;
|
||||
}
|
||||
|
||||
struct __Darwin_mcontext64
|
||||
{
|
||||
__Darwin_arm_exception_state64 __es;
|
||||
__Darwin_arm_thread_state64 __ss;
|
||||
__Darwin_arm_neon_state64 __ns;
|
||||
}
|
||||
|
||||
struct __Darwin_sigaltstack
|
||||
{
|
||||
void* ss_sp; /* signal stack base */
|
||||
__Darwin_size_t ss_size; /* signal stack length */
|
||||
int ss_flags; /* SA_DISABLE and/or SA_ONSTACK */
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module std::math::nolibc @if(env::NO_LIBC);
|
||||
|
||||
fn void __stack_chk_fail() @extern("__stack_chk_fail") @nostrip @noreturn @weak
|
||||
fn void __stack_chk_fail() @cname("__stack_chk_fail") @nostrip @noreturn @weak
|
||||
{
|
||||
$$trap();
|
||||
}
|
||||
@@ -32,7 +32,7 @@ extern fn ZString getcwd(char* pwd, usz len);
|
||||
extern fn CInt pipe(CInt[2]* pipes);
|
||||
extern fn CFile fdopen(CInt fd, ZString mode);
|
||||
extern fn CInt access(ZString path, CInt mode);
|
||||
extern fn Posix_dirent* readdir(DIRPtr) @extern("readdir") @if(!USE_DARWIN_INODE64) ;
|
||||
extern fn Posix_dirent* readdir(DIRPtr) @cname("readdir") @if(!USE_DARWIN_INODE64) ;
|
||||
extern fn DIRPtr opendir(ZString);
|
||||
extern fn void closedir(DIRPtr);
|
||||
|
||||
@@ -47,4 +47,4 @@ const DT_SOCK = 12;
|
||||
const DT_WHT = 14;
|
||||
|
||||
const USE_DARWIN_INODE64 = env::DARWIN && env::X86_64;
|
||||
extern fn Posix_dirent* readdir(DIRPtr) @extern("readdir$INODE64") @if(USE_DARWIN_INODE64);
|
||||
extern fn Posix_dirent* readdir(DIRPtr) @cname("readdir$INODE64") @if(USE_DARWIN_INODE64);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
module std::os::posix @if(env::POSIX);
|
||||
import libc;
|
||||
import libc, std::os::darwin;
|
||||
|
||||
struct Posix_spawn_file_actions_t
|
||||
{
|
||||
@@ -60,6 +60,15 @@ alias BacktraceFn = fn CInt(void** buffer, CInt size);
|
||||
|
||||
extern fn CInt backtrace(void** buffer, CInt size) @if(env::OPENBSD);
|
||||
|
||||
fn void install_signal_handler(CInt signal, SigActionFunction func)
|
||||
{
|
||||
Sigaction action = {
|
||||
.sa_sigaction = func,
|
||||
};
|
||||
Sigaction old;
|
||||
libc::sigaction(signal, &action, &old);
|
||||
}
|
||||
|
||||
fn CInt backtrace(void** buffer, CInt size) @if(!env::OPENBSD)
|
||||
{
|
||||
if (size < 1) return 0;
|
||||
@@ -75,12 +84,13 @@ fn CInt backtrace(void** buffer, CInt size) @if(!env::OPENBSD)
|
||||
}
|
||||
// Loop through the return addresses until we hit a signal.
|
||||
// This avoids using the frame address.
|
||||
SignalFunction restore_backtrace = fn void(CInt) {
|
||||
libc::longjmp(&backtrace_jmpbuf, 1);
|
||||
};
|
||||
SignalFunction sig_bus = libc::signal(libc::SIGBUS, restore_backtrace);
|
||||
SignalFunction sig_segv = libc::signal(libc::SIGSEGV, restore_backtrace);
|
||||
SignalFunction sig_ill = libc::signal(libc::SIGILL, restore_backtrace);
|
||||
Sigaction restore_backtrace = {
|
||||
.sa_sigaction = fn void(CInt, void*, void*) { libc::longjmp(&backtrace_jmpbuf, 1); },
|
||||
};
|
||||
Sigaction sig_bus, sig_segv, sig_ill;
|
||||
libc::sigaction(libc::SIGBUS, &restore_backtrace, &sig_bus);
|
||||
libc::sigaction(libc::SIGSEGV, &restore_backtrace, &sig_segv);
|
||||
libc::sigaction(libc::SIGILL, &restore_backtrace, &sig_ill);
|
||||
|
||||
void*[128] buffer_first;
|
||||
int i = 0;
|
||||
@@ -90,8 +100,47 @@ fn CInt backtrace(void** buffer, CInt size) @if(!env::OPENBSD)
|
||||
buffer[i] = builtin::get_returnaddress(i);
|
||||
if (!buffer[i]) break;
|
||||
}
|
||||
libc::signal(libc::SIGBUS, sig_bus);
|
||||
libc::signal(libc::SIGSEGV, sig_segv);
|
||||
libc::signal(libc::SIGILL, sig_ill);
|
||||
|
||||
Sigaction old;
|
||||
libc::sigaction(libc::SIGBUS, &sig_bus, &old);
|
||||
libc::sigaction(libc::SIGSEGV, &sig_segv, &old);
|
||||
libc::sigaction(libc::SIGILL, &sig_ill, &old);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
struct PosixUContext_t @if(env::DARWIN)
|
||||
{
|
||||
int uc_onstack;
|
||||
__Darwin_sigset_t uc_sigmask; /* signal mask used by this context */
|
||||
__Darwin_sigaltstack uc_stack; /* stack used by this context */
|
||||
PosixUContext_t* uc_link; /* pointer to resuming context */
|
||||
__Darwin_size_t uc_mcsize; /* size of the machine context passed in */
|
||||
__Darwin_mcontext64* uc_mcontext; /* pointer to machine specific context */
|
||||
}
|
||||
|
||||
alias PosixUContext_t @if(!env::DARWIN) = void;
|
||||
|
||||
macro void* stack_instruction(PosixUContext_t* uc)
|
||||
{
|
||||
$switch:
|
||||
$case env::DARWIN && env::AARCH64:
|
||||
return (void*)uc.uc_mcontext.__ss.__pc + 1;
|
||||
/* $case env::DARWIN && env::X86_64:
|
||||
return uc.uc_mcontext.__ss.__rip;
|
||||
$case env::LINUX && env::X86:
|
||||
return uc.uc_mcontext.gregs[REG_EIP];
|
||||
$case env::LINUX && env::X86_64:
|
||||
return uc.uc_mcontext.gregs[REG_RIP];
|
||||
$case env::LINUX && env::AARCH64:
|
||||
return uc.uc_mcontext.pc;
|
||||
$case env::FREEBSD && env::X86_64:
|
||||
return uc.uc_mcontext.mc_rip;
|
||||
$case env::OPENBSD && env::X86_64:
|
||||
return uc.sc_rip;
|
||||
$case env::NETBSD:
|
||||
uc.uc_mcontext.__gregs[_REG_RIP];*/
|
||||
$default:
|
||||
return null;
|
||||
$endswitch
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module std::os::win32 @if(env::WIN32);
|
||||
import std::math;
|
||||
|
||||
extern fn void getSystemTimeAsFileTime(Win32_FILETIME* time) @extern("GetSystemTimeAsFileTime");
|
||||
extern fn Win32_BOOL queryPerformanceFrequency(Win32_LARGE_INTEGER* lpFrequency) @extern("QueryPerformanceFrequency");
|
||||
extern fn Win32_BOOL queryPerformanceCounter(Win32_LARGE_INTEGER* lpPerformanceCount) @extern("QueryPerformanceCounter");
|
||||
extern fn void getSystemTimeAsFileTime(Win32_FILETIME* time) @cname("GetSystemTimeAsFileTime");
|
||||
extern fn Win32_BOOL queryPerformanceFrequency(Win32_LARGE_INTEGER* lpFrequency) @cname("QueryPerformanceFrequency");
|
||||
extern fn Win32_BOOL queryPerformanceCounter(Win32_LARGE_INTEGER* lpPerformanceCount) @cname("QueryPerformanceCounter");
|
||||
|
||||
188
lib/std/os/win32/exception.c3
Normal file
188
lib/std/os/win32/exception.c3
Normal file
@@ -0,0 +1,188 @@
|
||||
module std::os::win32 @if(env::WIN32);
|
||||
|
||||
import std::io;
|
||||
|
||||
const EXCEPTION_MAXIMUM_PARAMETERS = 15;
|
||||
|
||||
struct ExceptionRecord
|
||||
{
|
||||
Win32_DWORD exception_code;
|
||||
Win32_DWORD exception_flags;
|
||||
ExceptionRecord* exception_record;
|
||||
void* exception_address;
|
||||
Win32_DWORD number_parameters;
|
||||
Win32_ULONG_PTR[EXCEPTION_MAXIMUM_PARAMETERS] exception_information;
|
||||
}
|
||||
|
||||
struct ExceptionContext @align(16)
|
||||
{
|
||||
Win32_DWORD64 p1_home;
|
||||
Win32_DWORD64 p2_home;
|
||||
Win32_DWORD64 p3_home;
|
||||
Win32_DWORD64 p4_home;
|
||||
Win32_DWORD64 p5_home;
|
||||
Win32_DWORD64 p6_home;
|
||||
|
||||
Win32_DWORD context_flags;
|
||||
Win32_DWORD mx_csr;
|
||||
|
||||
Win32_WORD seg_cs;
|
||||
Win32_WORD seg_ds;
|
||||
Win32_WORD seg_es;
|
||||
Win32_WORD seg_fs;
|
||||
Win32_WORD seg_gs;
|
||||
Win32_WORD seg_ss;
|
||||
Win32_DWORD eflags;
|
||||
|
||||
Win32_DWORD64 dr0;
|
||||
Win32_DWORD64 dr1;
|
||||
Win32_DWORD64 dr2;
|
||||
Win32_DWORD64 dr3;
|
||||
Win32_DWORD64 dr6;
|
||||
Win32_DWORD64 dr7;
|
||||
|
||||
Win32_DWORD64 rax;
|
||||
Win32_DWORD64 rcx;
|
||||
Win32_DWORD64 rdx;
|
||||
Win32_DWORD64 rbx;
|
||||
Win32_DWORD64 rsp;
|
||||
Win32_DWORD64 rbp;
|
||||
Win32_DWORD64 rsi;
|
||||
Win32_DWORD64 rdi;
|
||||
Win32_DWORD64 r8;
|
||||
Win32_DWORD64 r9;
|
||||
Win32_DWORD64 r10;
|
||||
Win32_DWORD64 r11;
|
||||
Win32_DWORD64 r12;
|
||||
Win32_DWORD64 r13;
|
||||
Win32_DWORD64 r14;
|
||||
Win32_DWORD64 r15;
|
||||
|
||||
Win32_DWORD64 rip;
|
||||
|
||||
union
|
||||
{
|
||||
struct flt_save @align(16)
|
||||
{
|
||||
Win32_WORD control_word;
|
||||
Win32_WORD status_word;
|
||||
Win32_BYTE tag_word;
|
||||
Win32_BYTE reserved1;
|
||||
Win32_WORD error_opcode;
|
||||
Win32_DWORD error_offset;
|
||||
Win32_WORD error_selector;
|
||||
Win32_WORD reserved2;
|
||||
Win32_DWORD data_offset;
|
||||
Win32_WORD data_selector;
|
||||
Win32_WORD reserved3;
|
||||
Win32_DWORD mx_csr;
|
||||
Win32_DWORD mx_csr_mask;
|
||||
|
||||
Win32_M128A[16] xmm_registers;
|
||||
Win32_BYTE[96] reserved4;
|
||||
}
|
||||
struct
|
||||
{
|
||||
Win32_M128A[2] header;
|
||||
Win32_M128A[8] legacy;
|
||||
Win32_M128A xmm0;
|
||||
Win32_M128A xmm1;
|
||||
Win32_M128A xmm2;
|
||||
Win32_M128A xmm3;
|
||||
Win32_M128A xmm4;
|
||||
Win32_M128A xmm5;
|
||||
Win32_M128A xmm6;
|
||||
Win32_M128A xmm7;
|
||||
Win32_M128A xmm8;
|
||||
Win32_M128A xmm9;
|
||||
Win32_M128A xmm10;
|
||||
Win32_M128A xmm11;
|
||||
Win32_M128A xmm12;
|
||||
Win32_M128A xmm13;
|
||||
Win32_M128A xmm14;
|
||||
Win32_M128A xmm15;
|
||||
}
|
||||
}
|
||||
|
||||
Win32_M128A[26] vector_registers;
|
||||
Win32_DWORD64 vector_control;
|
||||
|
||||
Win32_DWORD64 debug_control;
|
||||
Win32_DWORD64 last_branch_to_rip;
|
||||
Win32_DWORD64 last_branch_from_rip;
|
||||
Win32_DWORD64 last_exception_to_rip;
|
||||
Win32_DWORD64 last_exception_from_rip;
|
||||
}
|
||||
|
||||
struct ExceptionPointers
|
||||
{
|
||||
ExceptionRecord* exception_record;
|
||||
ExceptionContext* context_record;
|
||||
}
|
||||
|
||||
alias UnhandledExceptionFilter = fn Win32_LONG (ExceptionPointers* exception_info);
|
||||
const EXCEPTION_EXECUTE_HANDLER = 1;
|
||||
|
||||
extern fn void debugBreak() @extern("DebugBreak") @if(env::WIN32);
|
||||
extern fn bool isDebuggerPresent() @extern("IsDebuggerPresent") @if(env::WIN32);
|
||||
extern fn UnhandledExceptionFilter setUnhandledExceptionFilter(UnhandledExceptionFilter filter) @extern("SetUnhandledExceptionFilter") @if(env::WIN32);
|
||||
|
||||
UnhandledExceptionFilter previous_filter;
|
||||
PanicFn previous_panic;
|
||||
bool has_panicked;
|
||||
|
||||
fn Win32_LONG exception_handler(ExceptionPointers* exception_info)
|
||||
{
|
||||
if (!has_panicked)
|
||||
{
|
||||
@stack_mem(512; Allocator allocator)
|
||||
{
|
||||
DString s;
|
||||
s.init(allocator: allocator);
|
||||
Win32_DWORD code = exception_info.exception_record.exception_code;
|
||||
void* addr = exception_info.exception_record.exception_address;
|
||||
switch (code)
|
||||
{
|
||||
case 0x80000001: s.appendf("Guard page violation at address %p", addr);
|
||||
case 0x80000002: s.appendf("Datatype misalignment at address %p", addr);
|
||||
case 0xC0000005: s.appendf("Access Violation at address %p", addr);
|
||||
case 0xC0000006: s.appendf("In page error at address %p", addr);
|
||||
case 0xC000001D: s.appendf("Illegal instruction at address %p", addr);
|
||||
case 0xC000008C: s.appendf("Array bounds exceeded at address %p", addr);
|
||||
case 0xC000008D: s.appendf("Flt denormal operand at address %p", addr);
|
||||
case 0xC000008E: s.appendf("Flt divide by zero at address %p", addr);
|
||||
case 0xC0000090: s.appendf("Flt invalid operation at address %p", addr);
|
||||
case 0xC0000094: s.appendf("Integer divide by zero at address %p", addr);
|
||||
case 0xC00000FD: s.appendf("Stack overflow at address %p", addr);
|
||||
case 0xC0000096: s.appendf("Privileged instruction at address %p", addr);
|
||||
case 0xC0000374: s.appendf("Heap corruption detected at address %p", addr);
|
||||
case 0xC0000409: s.appendf("Stack buffer overflow at address %p", addr);
|
||||
case 0xC00004A2: s.appendf("Enclave violation at address %p", addr);
|
||||
default:
|
||||
s.appendf("Unhandled exception (%X) at %p", code, addr);
|
||||
}
|
||||
if (!builtin::print_backtrace(s.str_view(), 8))
|
||||
{
|
||||
io::eprintfn("\nERROR: %s", s.str_view());
|
||||
}
|
||||
};
|
||||
}
|
||||
if (previous_filter)
|
||||
{
|
||||
return previous_filter(exception_info);
|
||||
}
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
|
||||
fn void panic_tracker(String message, String file, String function, uint line)
|
||||
{
|
||||
has_panicked = true;
|
||||
previous_panic(message, file, function, line);
|
||||
}
|
||||
|
||||
fn void init_exception_handler() @init
|
||||
{
|
||||
previous_filter = setUnhandledExceptionFilter(&exception_handler);
|
||||
previous_panic = builtin::panic;
|
||||
builtin::panic = &panic_tracker;
|
||||
}
|
||||
@@ -41,18 +41,18 @@ struct Win32_WIN32_FIND_DATAW
|
||||
|
||||
alias Win32_LPWIN32_FIND_DATAW = Win32_WIN32_FIND_DATAW*;
|
||||
|
||||
extern fn Win32_BOOL closeHandle(Win32_HANDLE) @extern("CloseHandle");
|
||||
extern fn Win32_BOOL createPipe(Win32_PHANDLE hReadPipe, Win32_PHANDLE hWritePipe, Win32_LPSECURITY_ATTRIBUTES lpPipeAttributes, Win32_DWORD nSize) @extern("CreatePipe");
|
||||
extern fn Win32_BOOL getFileAttributesExW(Win32_LPCWSTR, Win32_GET_FILEEX_INFO_LEVELS, Win32_LPVOID) @extern("GetFileAttributesExW");
|
||||
extern fn Win32_BOOL pathFileExistsW(Win32_LPCWSTR) @extern("PathFileExistsW");
|
||||
extern fn Win32_DWORD getTempPathW(Win32_DWORD nBufferLength, Win32_LPWSTR lpBuffer) @extern("GetTempPathW");
|
||||
extern fn Win32_BOOL setCurrentDirectoryW(Win32_LPCTSTR buffer) @extern("SetCurrentDirectoryW");
|
||||
extern fn Win32_BOOL removeDirectoryW(Win32_LPCWSTR lpPathName) @extern("RemoveDirectoryW");
|
||||
extern fn Win32_BOOL createDirectoryW(Win32_LPCWSTR lpPathName, Win32_LPSECURITY_ATTRIBUTES lpPipeAttributes) @extern("CreateDirectoryW");
|
||||
extern fn Win32_BOOL deleteFileW(Win32_LPCWSTR lpFileName) @extern("DeleteFileW");
|
||||
extern fn Win32_HANDLE findFirstFileW(Win32_LPCWSTR lpFileName, Win32_LPWIN32_FIND_DATAW lpFindFileData) @extern("FindFirstFileW");
|
||||
extern fn Win32_BOOL findNextFileW(Win32_HANDLE hFindFile, Win32_LPWIN32_FIND_DATAW lpFindFileData) @extern("FindNextFileW");
|
||||
extern fn Win32_BOOL findClose(Win32_HANDLE hFindFile) @extern("FindClose");
|
||||
extern fn Win32_BOOL closeHandle(Win32_HANDLE) @cname("CloseHandle");
|
||||
extern fn Win32_BOOL createPipe(Win32_PHANDLE hReadPipe, Win32_PHANDLE hWritePipe, Win32_LPSECURITY_ATTRIBUTES lpPipeAttributes, Win32_DWORD nSize) @cname("CreatePipe");
|
||||
extern fn Win32_BOOL getFileAttributesExW(Win32_LPCWSTR, Win32_GET_FILEEX_INFO_LEVELS, Win32_LPVOID) @cname("GetFileAttributesExW");
|
||||
extern fn Win32_BOOL pathFileExistsW(Win32_LPCWSTR) @cname("PathFileExistsW");
|
||||
extern fn Win32_DWORD getTempPathW(Win32_DWORD nBufferLength, Win32_LPWSTR lpBuffer) @cname("GetTempPathW");
|
||||
extern fn Win32_BOOL setCurrentDirectoryW(Win32_LPCTSTR buffer) @cname("SetCurrentDirectoryW");
|
||||
extern fn Win32_BOOL removeDirectoryW(Win32_LPCWSTR lpPathName) @cname("RemoveDirectoryW");
|
||||
extern fn Win32_BOOL createDirectoryW(Win32_LPCWSTR lpPathName, Win32_LPSECURITY_ATTRIBUTES lpPipeAttributes) @cname("CreateDirectoryW");
|
||||
extern fn Win32_BOOL deleteFileW(Win32_LPCWSTR lpFileName) @cname("DeleteFileW");
|
||||
extern fn Win32_HANDLE findFirstFileW(Win32_LPCWSTR lpFileName, Win32_LPWIN32_FIND_DATAW lpFindFileData) @cname("FindFirstFileW");
|
||||
extern fn Win32_BOOL findNextFileW(Win32_HANDLE hFindFile, Win32_LPWIN32_FIND_DATAW lpFindFileData) @cname("FindNextFileW");
|
||||
extern fn Win32_BOOL findClose(Win32_HANDLE hFindFile) @cname("FindClose");
|
||||
|
||||
const Win32_DWORD GENERIC_WRITE = 0x40000000;
|
||||
const Win32_DWORD OPEN_EXISTING = 3;
|
||||
@@ -87,10 +87,10 @@ extern fn Win32_HANDLE createFileA(
|
||||
Win32_DWORD dwCreationDisposition,
|
||||
Win32_DWORD dwFlagsAndAttributes,
|
||||
Win32_HANDLE hTemplateFile
|
||||
) @extern("CreateFileA");
|
||||
) @cname("CreateFileA");
|
||||
extern fn Win32_BOOL readFile(Win32_HANDLE hFile, Win32_LPVOID lpBuffer, Win32_DWORD nNumberOfBytesToRead,
|
||||
Win32_LPDWORD lpNumberOfBytesRead, Win32_LPOVERLAPPED lpOverlapped
|
||||
) @extern("ReadFile");
|
||||
) @cname("ReadFile");
|
||||
|
||||
extern fn WString _wgetcwd(Char16* buffer, int maxlen);
|
||||
extern fn usz wcslen(WString str);
|
||||
@@ -104,8 +104,8 @@ extern fn CInt _waccess(WString path, CInt mode);
|
||||
extern fn WString _wfullpath(WString absPath, WString relPath, usz maxLength);
|
||||
|
||||
/*
|
||||
extern ulong _win32_GetCurrentDirectoryW(ulong, Char16* buffer) @extern("GetCurrentDirectoryW");
|
||||
extern bool _win32_CreateSymbolicLinkW(WString symlink_file, WString target_file, ulong flags) @extern("CreateSymbolicLinkW");
|
||||
extern bool _win32_CopyFileW(WString from_file, WString to_file, bool no_overwrite) @extern("CopyFileW");
|
||||
extern ulong _win32_GetFullPathNameW(WString file_name, ulong buffer_len, Char16* buffer, WString* file_part) @extern("GetFullPathNameW");
|
||||
extern ulong _win32_GetCurrentDirectoryW(ulong, Char16* buffer) @cname("GetCurrentDirectoryW");
|
||||
extern bool _win32_CreateSymbolicLinkW(WString symlink_file, WString target_file, ulong flags) @cname("CreateSymbolicLinkW");
|
||||
extern bool _win32_CopyFileW(WString from_file, WString to_file, bool no_overwrite) @cname("CopyFileW");
|
||||
extern ulong _win32_GetFullPathNameW(WString file_name, ulong buffer_len, Char16* buffer, WString* file_part) @cname("GetFullPathNameW");
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module std::os::win32 @if(env::WIN32);
|
||||
|
||||
extern fn Win32_HBRUSH createSolidBrush(Win32_COLORREF) @extern("CreateSolidBrush");
|
||||
extern fn Win32_COLORREF setTextColor(Win32_HDC, Win32_COLORREF) @extern("SetTextColor");
|
||||
extern fn CInt setBkMode(Win32_HDC, CInt) @extern("SetBkMode");
|
||||
extern fn Win32_BOOL textOut(Win32_HDC, CInt, CInt, Win32_LPCWSTR, CInt) @extern("TextOutW");
|
||||
extern fn Win32_HBRUSH createSolidBrush(Win32_COLORREF) @cname("CreateSolidBrush");
|
||||
extern fn Win32_COLORREF setTextColor(Win32_HDC, Win32_COLORREF) @cname("SetTextColor");
|
||||
extern fn CInt setBkMode(Win32_HDC, CInt) @cname("SetBkMode");
|
||||
extern fn Win32_BOOL textOut(Win32_HDC, CInt, CInt, Win32_LPCWSTR, CInt) @cname("TextOutW");
|
||||
@@ -1,6 +1,6 @@
|
||||
module std::os::win32 @if(env::WIN32);
|
||||
|
||||
extern fn Win32_DWORD getLastError() @extern("GetLastError");
|
||||
extern fn Win32_DWORD getLastError() @cname("GetLastError");
|
||||
|
||||
const Win32_DWORD ERROR_INVALID_FUNCTION = 0x1;
|
||||
const Win32_DWORD ERROR_FILE_NOT_FOUND = 0x2;
|
||||
|
||||
@@ -3,25 +3,25 @@ module std::os::win32 @if(env::WIN32);
|
||||
typedef Win32_DLL_DIRECTORY_COOKIE = void*;
|
||||
alias Win32_PDLL_DIRECTORY_COOKIE = Win32_DLL_DIRECTORY_COOKIE*;
|
||||
|
||||
extern fn Win32_HMODULE loadLibraryA(Win32_LPCSTR lpLibFileName) @extern("LoadLibraryA");
|
||||
extern fn Win32_HMODULE loadLibraryW(Win32_LPCWSTR lpLibFileName) @extern("LoadLibraryW");
|
||||
extern fn Win32_HMODULE loadLibraryExA(Win32_LPCSTR lpLibFileName, Win32_HANDLE hFile, Win32_DWORD dwFlags) @extern("LoadLibraryExA");
|
||||
extern fn Win32_HMODULE loadLibraryExW(Win32_LPCWSTR lpLibFileName, Win32_HANDLE hFile, Win32_DWORD dwFlags) @extern("LoadLibraryExW");
|
||||
extern fn Win32_HMODULE loadLibraryA(Win32_LPCSTR lpLibFileName) @cname("LoadLibraryA");
|
||||
extern fn Win32_HMODULE loadLibraryW(Win32_LPCWSTR lpLibFileName) @cname("LoadLibraryW");
|
||||
extern fn Win32_HMODULE loadLibraryExA(Win32_LPCSTR lpLibFileName, Win32_HANDLE hFile, Win32_DWORD dwFlags) @cname("LoadLibraryExA");
|
||||
extern fn Win32_HMODULE loadLibraryExW(Win32_LPCWSTR lpLibFileName, Win32_HANDLE hFile, Win32_DWORD dwFlags) @cname("LoadLibraryExW");
|
||||
|
||||
extern fn Win32_BOOL freeLibrary(Win32_HMODULE hLibModule) @extern("FreeLibrary");
|
||||
extern fn void freeLibraryAndExitThread(Win32_HMODULE hLibModule, Win32_DWORD dwExitCode) @extern("FreeLibraryAndExitThread");
|
||||
extern fn Win32_BOOL freeLibrary(Win32_HMODULE hLibModule) @cname("FreeLibrary");
|
||||
extern fn void freeLibraryAndExitThread(Win32_HMODULE hLibModule, Win32_DWORD dwExitCode) @cname("FreeLibraryAndExitThread");
|
||||
|
||||
extern fn Win32_DWORD getModuleFileNameA(Win32_HMODULE hModule, Win32_LPSTR lpFilename, Win32_DWORD nSize) @extern("GetModuleFileNameA");
|
||||
extern fn Win32_DWORD getModuleFileNameW(Win32_HMODULE hModule, Win32_LPWSTR lpFilename, Win32_DWORD nSize) @extern("GetModuleFileNameW");
|
||||
extern fn Win32_DWORD getModuleFileNameA(Win32_HMODULE hModule, Win32_LPSTR lpFilename, Win32_DWORD nSize) @cname("GetModuleFileNameA");
|
||||
extern fn Win32_DWORD getModuleFileNameW(Win32_HMODULE hModule, Win32_LPWSTR lpFilename, Win32_DWORD nSize) @cname("GetModuleFileNameW");
|
||||
|
||||
extern fn Win32_HMODULE getModuleHandleA(Win32_LPCSTR lpModuleName) @extern("GetModuleHandleA");
|
||||
extern fn Win32_HMODULE getModuleHandleW(Win32_LPCWSTR lpModuleName) @extern("GetModuleHandleW");
|
||||
extern fn Win32_BOOL getModuleHandleExA(Win32_DWORD dwFlags, Win32_LPCSTR lpModuleName, Win32_HMODULE* phModule) @extern("GetModuleHandleExA");
|
||||
extern fn Win32_BOOL getModuleHandleExW(Win32_DWORD dwFlags, Win32_LPCWSTR lpModuleName, Win32_HMODULE* phModule) @extern("GetModuleHandleExW");
|
||||
extern fn Win32_HMODULE getModuleHandleA(Win32_LPCSTR lpModuleName) @cname("GetModuleHandleA");
|
||||
extern fn Win32_HMODULE getModuleHandleW(Win32_LPCWSTR lpModuleName) @cname("GetModuleHandleW");
|
||||
extern fn Win32_BOOL getModuleHandleExA(Win32_DWORD dwFlags, Win32_LPCSTR lpModuleName, Win32_HMODULE* phModule) @cname("GetModuleHandleExA");
|
||||
extern fn Win32_BOOL getModuleHandleExW(Win32_DWORD dwFlags, Win32_LPCWSTR lpModuleName, Win32_HMODULE* phModule) @cname("GetModuleHandleExW");
|
||||
|
||||
extern fn Win32_BOOL disableThreadLibraryCalls(Win32_HMODULE hLibModule) @extern("DisableThreadLibraryCalls");
|
||||
extern fn Win32_BOOL disableThreadLibraryCalls(Win32_HMODULE hLibModule) @cname("DisableThreadLibraryCalls");
|
||||
|
||||
extern fn Win32_FARPROC getProcAddress(Win32_HMODULE hModule, Win32_LPCSTR lpProcName) @extern("GetProcAddress");
|
||||
extern fn Win32_DLL_DIRECTORY_COOKIE addDllDirectory(Win32_PCWSTR newDirectory) @extern("AddDllDirectory");
|
||||
extern fn Win32_BOOL removeDllDirectory(Win32_DLL_DIRECTORY_COOKIE cookie) @extern("RemoveDllDirectory");
|
||||
extern fn Win32_BOOL setDefaultDllDirectories(Win32_DWORD directoryFlags) @extern("SetDefaultDllDirectories");
|
||||
extern fn Win32_FARPROC getProcAddress(Win32_HMODULE hModule, Win32_LPCSTR lpProcName) @cname("GetProcAddress");
|
||||
extern fn Win32_DLL_DIRECTORY_COOKIE addDllDirectory(Win32_PCWSTR newDirectory) @cname("AddDllDirectory");
|
||||
extern fn Win32_BOOL removeDllDirectory(Win32_DLL_DIRECTORY_COOKIE cookie) @cname("RemoveDllDirectory");
|
||||
extern fn Win32_BOOL setDefaultDllDirectories(Win32_DWORD directoryFlags) @cname("SetDefaultDllDirectories");
|
||||
@@ -36,10 +36,10 @@ enum Win32_FreeType : const Win32_DWORD
|
||||
MEM_COALESCE_PLACEHOLDERS = 0x00000001,
|
||||
MEM_PRESERVE_PLACEHOLDER = 0x00000002,
|
||||
}
|
||||
extern fn Win32_LPVOID virtualAlloc(Win32_LPVOID lpAddress, Win32_SIZE_T dwSize, Win32_AllocationType flAllocationType, Win32_Protect flProtect) @extern("VirtualAlloc");
|
||||
extern fn Win32_PVOID virtualAlloc2(Win32_HANDLE process, Win32_PVOID baseAddress, Win32_SIZE_T size, Win32_AllocationType allocationType, Win32_ULONG pageProtection, Win32_MEM_EXTENDED_PARAMETER* extendedParameters, Win32_ULONG parameterCount) @extern("VirtualAlloc2");
|
||||
extern fn Win32_BOOL virtualFree(Win32_LPVOID lpAddress, Win32_SIZE_T dwSize, Win32_FreeType dwFreeType) @extern("VirtualFree");
|
||||
extern fn Win32_BOOL virtualProtect(Win32_LPVOID lpAddress, Win32_SIZE_T dwSize, Win32_Protect flNewProtect, Win32_Protect* lpflOldProtect) @extern("VirtualProtect");
|
||||
extern fn Win32_LPVOID virtualAlloc(Win32_LPVOID lpAddress, Win32_SIZE_T dwSize, Win32_AllocationType flAllocationType, Win32_Protect flProtect) @cname("VirtualAlloc");
|
||||
extern fn Win32_PVOID virtualAlloc2(Win32_HANDLE process, Win32_PVOID baseAddress, Win32_SIZE_T size, Win32_AllocationType allocationType, Win32_ULONG pageProtection, Win32_MEM_EXTENDED_PARAMETER* extendedParameters, Win32_ULONG parameterCount) @cname("VirtualAlloc2");
|
||||
extern fn Win32_BOOL virtualFree(Win32_LPVOID lpAddress, Win32_SIZE_T dwSize, Win32_FreeType dwFreeType) @cname("VirtualFree");
|
||||
extern fn Win32_BOOL virtualProtect(Win32_LPVOID lpAddress, Win32_SIZE_T dwSize, Win32_Protect flNewProtect, Win32_Protect* lpflOldProtect) @cname("VirtualProtect");
|
||||
|
||||
fn usz allocation_granularity()
|
||||
{
|
||||
|
||||
@@ -48,76 +48,76 @@ const UNDNAME_COMPLETE = 0x0000;
|
||||
|
||||
alias Win32_INIT_ONCE_FN = fn Win32_BOOL(Win32_INIT_ONCE* initOnce, void* parameter, void** context);
|
||||
|
||||
extern fn void initializeCriticalSection(Win32_CRITICAL_SECTION* section) @extern("InitializeCriticalSection");
|
||||
extern fn void deleteCriticalSection(Win32_CRITICAL_SECTION* section) @extern("DeleteCriticalSection");
|
||||
extern fn Win32_HANDLE createMutex(void*, Win32_BOOL, void*) @extern("CreateMutexA");
|
||||
extern fn Win32_BOOL releaseMutex(Win32_HANDLE) @extern("ReleaseMutex");
|
||||
extern fn void enterCriticalSection(Win32_CRITICAL_SECTION* section) @extern("EnterCriticalSection");
|
||||
extern fn void leaveCriticalSection(Win32_CRITICAL_SECTION* section) @extern("LeaveCriticalSection");
|
||||
extern fn Win32_BOOL tryEnterCriticalSection(Win32_CRITICAL_SECTION* section) @extern("TryEnterCriticalSection");
|
||||
extern fn void initializeSRWLock(Win32_SRWLOCK* lock) @extern("InitializeSRWLock");
|
||||
extern fn void acquireSRWLockExclusive(Win32_SRWLOCK* lock) @extern("AcquireSRWLockExclusive");
|
||||
extern fn void acquireSRWLockShared(Win32_SRWLOCK* lock) @extern("AcquireSRWLockShared");
|
||||
extern fn void releaseSRWLockExclusive(Win32_SRWLOCK* lock) @extern("ReleaseSRWLockExclusive");
|
||||
extern fn void releaseSRWLockShared(Win32_SRWLOCK* lock) @extern("ReleaseSRWLockShared");
|
||||
extern fn Win32_BOOL tryAcquireSRWLockExclusive(Win32_SRWLOCK* lock) @extern("TryAcquireSRWLockExclusive");
|
||||
extern fn Win32_BOOL tryAcquireSRWLockShared(Win32_SRWLOCK* lock) @extern("TryAcquireSRWLockShared");
|
||||
extern fn void initializeConditionVariable(Win32_CONDITION_VARIABLE* conditionVariable) @extern("InitializeConditionVariable");
|
||||
extern fn void wakeConditionVariable(Win32_CONDITION_VARIABLE* conditionVariable) @extern("WakeConditionVariable");
|
||||
extern fn void wakeAllConditionVariable(Win32_CONDITION_VARIABLE* conditionVariable) @extern("WakeAllConditionVariable");
|
||||
extern fn Win32_BOOL sleepConditionVariableCS(Win32_CONDITION_VARIABLE* conditionVariable, Win32_CRITICAL_SECTION* section, Win32_DWORD dwMilliseconds) @extern("SleepConditionVariableCS");
|
||||
extern fn Win32_BOOL sleepConditionVariableSRW(Win32_CONDITION_VARIABLE* conditionVariable, Win32_SRWLOCK* lock, Win32_DWORD dwMilliseconds, Win32_ULONG flags) @extern("SleepConditionVariableSRW");
|
||||
extern fn Win32_BOOL initOnceExecuteOnce(Win32_INIT_ONCE* initOnce, Win32_INIT_ONCE_FN initFn, void* parameter, void** context) @extern("InitOnceExecuteOnce");
|
||||
extern fn Win32_DWORD waitForSingleObject(Win32_HANDLE hHandle, Win32_DWORD dwMilliseconds) @extern("WaitForSingleObject");
|
||||
extern fn Win32_DWORD waitForSingleObjectEx(Win32_HANDLE hHandle, Win32_DWORD dwMilliseconds, Win32_BOOL bAlertable) @extern("WaitForSingleObjectEx");
|
||||
extern fn Win32_DWORD waitForMultipleObjects(Win32_DWORD nCount, Win32_HANDLE* lpHandles, Win32_BOOL bWaitAll, Win32_DWORD dwMilliseconds) @extern("WaitForMultipleObjects");
|
||||
extern fn Win32_DWORD waitForMultipleObjectsEx(Win32_DWORD nCount, Win32_HANDLE* lpHandles, Win32_BOOL bWaitAll, Win32_DWORD dwMilliseconds, Win32_BOOL bAlertable) @extern("WaitForMultipleObjectsEx");
|
||||
extern fn void sleep(uint ms) @extern("Sleep");
|
||||
extern fn Win32_BOOL resetEvent(Win32_HANDLE event) @extern("ResetEvent");
|
||||
extern fn Win32_BOOL setEvent(Win32_HANDLE handle) @extern("SetEvent");
|
||||
extern fn long interlockedCompareExchange(int* dest, int exchange, int comperand) @extern("InterlockedCompareExchange");
|
||||
extern fn Win32_DWORD sleepEx(Win32_DWORD ms, Win32_BOOL alertable) @extern("SleepEx");
|
||||
extern fn Win32_HANDLE createThread(void* attributes, usz stack, ThreadFn func, Win32_LPVOID arg, Win32_DWORD flags, Win32_LPDWORD thread_id) @extern("CreateThread");
|
||||
extern fn Win32_BOOL getExitCodeThread(Win32_HANDLE handle, Win32_LPDWORD exit_code) @extern("GetExitCodeThread");
|
||||
extern fn Win32_BOOL getExitCodeProcess(Win32_HANDLE hProcess, Win32_LPDWORD lpExitCode) @extern("GetExitCodeProcess");
|
||||
extern fn Win32_DWORD getThreadId(Win32_HANDLE) @extern("GetThreadId");
|
||||
extern fn void exitThread(Win32_DWORD dwExitCode) @noreturn @extern("ExitThread");
|
||||
extern fn Win32_HANDLE getCurrentThread() @extern("GetCurrentThread");
|
||||
extern fn Win32_BOOL terminateProcess(Win32_HANDLE hProcess, Win32_UINT uExitCode) @extern("TerminateProcess");
|
||||
extern fn Win32_DWORD getCurrentProcessId() @extern("GetCurrentProcessId");
|
||||
extern fn Win32_HANDLE getCurrentProcess() @extern("GetCurrentProcess");
|
||||
extern fn Win32_DWORD getCurrentThreadId() @extern("GetCurrentThreadId");
|
||||
extern fn Win32_BOOL setHandleInformation(Win32_HANDLE hObject, Win32_DWORD dwMask, Win32_DWORD dwFlags) @extern("SetHandleInformation");
|
||||
extern fn Win32_HANDLE createEventA(Win32_LPSECURITY_ATTRIBUTES lpEventAttributes, Win32_BOOL bManualReset, Win32_BOOL bInitialState, Win32_LPCSTR lpName) @extern("CreateEventA");
|
||||
extern fn Win32_BOOL createProcessW(Win32_LPCWSTR lpApplicationName, Win32_LPWSTR lpCommandLine, Win32_LPSECURITY_ATTRIBUTES lpProcessAttributes, Win32_LPSECURITY_ATTRIBUTES lpThreadAttributes, Win32_BOOL bInheritHandles, Win32_DWORD dwCreationFlags, Win32_LPVOID lpEnvironment, Win32_LPCWSTR lpCurrentDirectory, Win32_LPSTARTUPINFOW lpStartupInfo, Win32_LPPROCESS_INFORMATION lpProcessInformation) @extern("CreateProcessW");
|
||||
extern fn Win32_HANDLE createNamedPipeA(Win32_LPCSTR lpName, Win32_DWORD dwOpenMode, Win32_DWORD dwPipeMode, Win32_DWORD nMaxInstances, Win32_DWORD nOutBufferSize, Win32_DWORD nInBufferSize, Win32_DWORD nDefaultTimeOut, Win32_LPSECURITY_ATTRIBUTES lpSecurityAttributes) @extern("CreateNamedPipeA");
|
||||
extern fn Win32_BOOL getOverlappedResult(Win32_HANDLE hFile, Win32_LPOVERLAPPED lpOverlapped, Win32_LPDWORD lpNumberOfBytesTransferred, Win32_BOOL bWait) @extern("GetOverlappedResult");
|
||||
extern fn Win32_DWORD getEnvironmentVariableW(Win32_LPCWSTR lpName, Win32_LPWSTR lpBuffer, Win32_DWORD nSize) @extern("GetEnvironmentVariableW");
|
||||
extern fn Win32_BOOL setEnvironmentVariableW(Win32_LPCWSTR lpName, Win32_LPCWSTR lpValue) @extern("SetEnvironmentVariableW");
|
||||
extern fn void getSystemInfo(Win32_LPSYSTEM_INFO lpSystemInfo) @extern("GetSystemInfo");
|
||||
extern fn Win32_BOOL enumProcessModules(Win32_HANDLE hProcess, Win32_HMODULE* lphModule, Win32_DWORD cb, Win32_LPDWORD lpcbNeeded) @extern("K32EnumProcessModules");
|
||||
extern fn Win32_BOOL getModuleInformation(Win32_HANDLE hProcess, Win32_HMODULE hModule, Win32_LPMODULEINFO lpmodinfo, Win32_DWORD cb) @extern("K32GetModuleInformation");
|
||||
extern fn Win32_DWORD symAddrIncludeInlineTrace(Win32_HANDLE hProcess, Win32_DWORD64 address) @extern("SymAddrIncludeInlineTrace");
|
||||
extern fn Win32_BOOL symQueryInlineTrace(Win32_HANDLE hProcess, Win32_DWORD64 startAddress, Win32_DWORD startContext, Win32_DWORD64 startRetAddress, Win32_DWORD64 curAddress, Win32_LPDWORD curContext, Win32_LPDWORD curFrameIndex) @extern("SymQueryInlineTrace");
|
||||
extern fn Win32_BOOL symFromInlineContext(Win32_HANDLE hProcess, Win32_DWORD64 address, Win32_ULONG inlineContext, Win32_PDWORD64 displacement, Win32_PSYMBOL_INFO symbol) @extern("SymFromInlineContext");
|
||||
extern fn Win32_BOOL symGetLineFromInlineContext(Win32_HANDLE hProcess, Win32_DWORD64 qwAddr, Win32_ULONG inlineContext, Win32_DWORD64 qwModuleBaseAddress, Win32_PDWORD pdwDisplacement, Win32_PIMAGEHLP_LINE64 line64) @extern("SymGetLineFromInlineContext");
|
||||
extern fn Win32_ULONG rtlWalkFrameChain(Win32_PVOID*, Win32_ULONG, Win32_ULONG) @extern("RtlWalkFrameChain");
|
||||
extern fn Win32_BOOL symInitialize(Win32_HANDLE hProcess, Win32_PCSTR userSearchPath, Win32_BOOL fInvadeProcess) @extern("SymInitialize");
|
||||
extern fn Win32_BOOL symCleanup(Win32_HANDLE hProcess) @extern("SymCleanup");
|
||||
extern fn Win32_DWORD64 symLoadModuleEx(Win32_HANDLE hProcess, Win32_HANDLE hFile, Win32_PCSTR imageName, Win32_PCSTR moduleName, Win32_DWORD64 baseOfDll, Win32_DWORD dllSize, Win32_PMODLOAD_DATA data, Win32_DWORD flags) @extern("SymLoadModule");
|
||||
extern fn Win32_BOOL stackWalk64(Win32_DWORD machineType, Win32_HANDLE hProcess, Win32_HANDLE hThread, Win32_LPSTACKFRAME64 stackFrame, Win32_PVOID contextRecord, Win32_PREAD_PROCESS_MEMORY_ROUTINE64 readMemoryRoutine, Win32_PFUNCTION_TABLE_ACCESS_ROUTINE64 functionTableAccessRoutine, Win32_PGET_MODULE_BASE_ROUTINE64 getModuleBaseRoutine, Win32_PTRANSLATE_ADDRESS_ROUTINE64 translateAddress) @extern("StackWalk64");
|
||||
extern fn void rtlCaptureContext(Win32_PCONTEXT contextRecord) @extern("RtlCaptureContext");
|
||||
extern fn void* symFunctionTableAccess64(Win32_HANDLE hProcess, Win32_DWORD64 addrBase) @extern("SymFunctionTableAccess64");
|
||||
extern fn Win32_DWORD64 symGetModuleBase64(Win32_HANDLE hProcess, Win32_DWORD64 qwAddr) @extern("SymGetModuleBase64");
|
||||
extern fn Win32_DWORD getModuleBaseNameA(Win32_HANDLE hProcess, Win32_HMODULE hModule, Win32_LPSTR lpBaseName, Win32_DWORD nSize) @extern("K32GetModuleBaseNameA");
|
||||
extern fn Win32_DWORD symGetOptions() @extern("SymGetOptions");
|
||||
extern fn Win32_DWORD symSetOptions(Win32_DWORD symOptions) @extern("SymSetOptions");
|
||||
extern fn Win32_PIMAGE_NT_HEADERS imageNtHeader(Win32_PVOID base) @extern("ImageNtHeader");
|
||||
extern fn Win32_DWORD unDecorateSymbolName(Win32_PCSTR name, Win32_PSTR outputString, Win32_DWORD maxStringLength, Win32_DWORD flags) @extern("UnDecorateSymbolName");
|
||||
extern fn Win32_BOOL symFromAddr(Win32_HANDLE hProcess, Win32_DWORD64 address, Win32_PDWORD64 displacement, Win32_PSYMBOL_INFO symbol) @extern("SymFromAddr");
|
||||
extern fn Win32_BOOL symGetLineFromAddr64(Win32_HANDLE hProcess, Win32_DWORD64 dwAddr, Win32_PDWORD pdwDisplacement, Win32_PIMAGEHLP_LINE64 line) @extern("SymGetLineFromAddr64");
|
||||
extern fn Win32_WORD rtlCaptureStackBackTrace(Win32_DWORD framesToSkip, Win32_DWORD framesToCapture, Win32_PVOID *backTrace, Win32_PDWORD backTraceHash) @extern("RtlCaptureStackBackTrace");
|
||||
extern fn Win32_BOOL symGetModuleInfo64(Win32_HANDLE hProcess, Win32_DWORD64 qwAddr, Win32_PIMAGEHLP_MODULE64 moduleInfo) @extern("SymGetModuleInfo64");
|
||||
extern fn void initializeCriticalSection(Win32_CRITICAL_SECTION* section) @cname("InitializeCriticalSection");
|
||||
extern fn void deleteCriticalSection(Win32_CRITICAL_SECTION* section) @cname("DeleteCriticalSection");
|
||||
extern fn Win32_HANDLE createMutex(void*, Win32_BOOL, void*) @cname("CreateMutexA");
|
||||
extern fn Win32_BOOL releaseMutex(Win32_HANDLE) @cname("ReleaseMutex");
|
||||
extern fn void enterCriticalSection(Win32_CRITICAL_SECTION* section) @cname("EnterCriticalSection");
|
||||
extern fn void leaveCriticalSection(Win32_CRITICAL_SECTION* section) @cname("LeaveCriticalSection");
|
||||
extern fn Win32_BOOL tryEnterCriticalSection(Win32_CRITICAL_SECTION* section) @cname("TryEnterCriticalSection");
|
||||
extern fn void initializeSRWLock(Win32_SRWLOCK* lock) @cname("InitializeSRWLock");
|
||||
extern fn void acquireSRWLockExclusive(Win32_SRWLOCK* lock) @cname("AcquireSRWLockExclusive");
|
||||
extern fn void acquireSRWLockShared(Win32_SRWLOCK* lock) @cname("AcquireSRWLockShared");
|
||||
extern fn void releaseSRWLockExclusive(Win32_SRWLOCK* lock) @cname("ReleaseSRWLockExclusive");
|
||||
extern fn void releaseSRWLockShared(Win32_SRWLOCK* lock) @cname("ReleaseSRWLockShared");
|
||||
extern fn Win32_BOOL tryAcquireSRWLockExclusive(Win32_SRWLOCK* lock) @cname("TryAcquireSRWLockExclusive");
|
||||
extern fn Win32_BOOL tryAcquireSRWLockShared(Win32_SRWLOCK* lock) @cname("TryAcquireSRWLockShared");
|
||||
extern fn void initializeConditionVariable(Win32_CONDITION_VARIABLE* conditionVariable) @cname("InitializeConditionVariable");
|
||||
extern fn void wakeConditionVariable(Win32_CONDITION_VARIABLE* conditionVariable) @cname("WakeConditionVariable");
|
||||
extern fn void wakeAllConditionVariable(Win32_CONDITION_VARIABLE* conditionVariable) @cname("WakeAllConditionVariable");
|
||||
extern fn Win32_BOOL sleepConditionVariableCS(Win32_CONDITION_VARIABLE* conditionVariable, Win32_CRITICAL_SECTION* section, Win32_DWORD dwMilliseconds) @cname("SleepConditionVariableCS");
|
||||
extern fn Win32_BOOL sleepConditionVariableSRW(Win32_CONDITION_VARIABLE* conditionVariable, Win32_SRWLOCK* lock, Win32_DWORD dwMilliseconds, Win32_ULONG flags) @cname("SleepConditionVariableSRW");
|
||||
extern fn Win32_BOOL initOnceExecuteOnce(Win32_INIT_ONCE* initOnce, Win32_INIT_ONCE_FN initFn, void* parameter, void** context) @cname("InitOnceExecuteOnce");
|
||||
extern fn Win32_DWORD waitForSingleObject(Win32_HANDLE hHandle, Win32_DWORD dwMilliseconds) @cname("WaitForSingleObject");
|
||||
extern fn Win32_DWORD waitForSingleObjectEx(Win32_HANDLE hHandle, Win32_DWORD dwMilliseconds, Win32_BOOL bAlertable) @cname("WaitForSingleObjectEx");
|
||||
extern fn Win32_DWORD waitForMultipleObjects(Win32_DWORD nCount, Win32_HANDLE* lpHandles, Win32_BOOL bWaitAll, Win32_DWORD dwMilliseconds) @cname("WaitForMultipleObjects");
|
||||
extern fn Win32_DWORD waitForMultipleObjectsEx(Win32_DWORD nCount, Win32_HANDLE* lpHandles, Win32_BOOL bWaitAll, Win32_DWORD dwMilliseconds, Win32_BOOL bAlertable) @cname("WaitForMultipleObjectsEx");
|
||||
extern fn void sleep(uint ms) @cname("Sleep");
|
||||
extern fn Win32_BOOL resetEvent(Win32_HANDLE event) @cname("ResetEvent");
|
||||
extern fn Win32_BOOL setEvent(Win32_HANDLE handle) @cname("SetEvent");
|
||||
extern fn long interlockedCompareExchange(int* dest, int exchange, int comperand) @cname("InterlockedCompareExchange");
|
||||
extern fn Win32_DWORD sleepEx(Win32_DWORD ms, Win32_BOOL alertable) @cname("SleepEx");
|
||||
extern fn Win32_HANDLE createThread(void* attributes, usz stack, ThreadFn func, Win32_LPVOID arg, Win32_DWORD flags, Win32_LPDWORD thread_id) @cname("CreateThread");
|
||||
extern fn Win32_BOOL getExitCodeThread(Win32_HANDLE handle, Win32_LPDWORD exit_code) @cname("GetExitCodeThread");
|
||||
extern fn Win32_BOOL getExitCodeProcess(Win32_HANDLE hProcess, Win32_LPDWORD lpExitCode) @cname("GetExitCodeProcess");
|
||||
extern fn Win32_DWORD getThreadId(Win32_HANDLE) @cname("GetThreadId");
|
||||
extern fn void exitThread(Win32_DWORD dwExitCode) @noreturn @cname("ExitThread");
|
||||
extern fn Win32_HANDLE getCurrentThread() @cname("GetCurrentThread");
|
||||
extern fn Win32_BOOL terminateProcess(Win32_HANDLE hProcess, Win32_UINT uExitCode) @cname("TerminateProcess");
|
||||
extern fn Win32_DWORD getCurrentProcessId() @cname("GetCurrentProcessId");
|
||||
extern fn Win32_HANDLE getCurrentProcess() @cname("GetCurrentProcess");
|
||||
extern fn Win32_DWORD getCurrentThreadId() @cname("GetCurrentThreadId");
|
||||
extern fn Win32_BOOL setHandleInformation(Win32_HANDLE hObject, Win32_DWORD dwMask, Win32_DWORD dwFlags) @cname("SetHandleInformation");
|
||||
extern fn Win32_HANDLE createEventA(Win32_LPSECURITY_ATTRIBUTES lpEventAttributes, Win32_BOOL bManualReset, Win32_BOOL bInitialState, Win32_LPCSTR lpName) @cname("CreateEventA");
|
||||
extern fn Win32_BOOL createProcessW(Win32_LPCWSTR lpApplicationName, Win32_LPWSTR lpCommandLine, Win32_LPSECURITY_ATTRIBUTES lpProcessAttributes, Win32_LPSECURITY_ATTRIBUTES lpThreadAttributes, Win32_BOOL bInheritHandles, Win32_DWORD dwCreationFlags, Win32_LPVOID lpEnvironment, Win32_LPCWSTR lpCurrentDirectory, Win32_LPSTARTUPINFOW lpStartupInfo, Win32_LPPROCESS_INFORMATION lpProcessInformation) @cname("CreateProcessW");
|
||||
extern fn Win32_HANDLE createNamedPipeA(Win32_LPCSTR lpName, Win32_DWORD dwOpenMode, Win32_DWORD dwPipeMode, Win32_DWORD nMaxInstances, Win32_DWORD nOutBufferSize, Win32_DWORD nInBufferSize, Win32_DWORD nDefaultTimeOut, Win32_LPSECURITY_ATTRIBUTES lpSecurityAttributes) @cname("CreateNamedPipeA");
|
||||
extern fn Win32_BOOL getOverlappedResult(Win32_HANDLE hFile, Win32_LPOVERLAPPED lpOverlapped, Win32_LPDWORD lpNumberOfBytesTransferred, Win32_BOOL bWait) @cname("GetOverlappedResult");
|
||||
extern fn Win32_DWORD getEnvironmentVariableW(Win32_LPCWSTR lpName, Win32_LPWSTR lpBuffer, Win32_DWORD nSize) @cname("GetEnvironmentVariableW");
|
||||
extern fn Win32_BOOL setEnvironmentVariableW(Win32_LPCWSTR lpName, Win32_LPCWSTR lpValue) @cname("SetEnvironmentVariableW");
|
||||
extern fn void getSystemInfo(Win32_LPSYSTEM_INFO lpSystemInfo) @cname("GetSystemInfo");
|
||||
extern fn Win32_BOOL enumProcessModules(Win32_HANDLE hProcess, Win32_HMODULE* lphModule, Win32_DWORD cb, Win32_LPDWORD lpcbNeeded) @cname("K32EnumProcessModules");
|
||||
extern fn Win32_BOOL getModuleInformation(Win32_HANDLE hProcess, Win32_HMODULE hModule, Win32_LPMODULEINFO lpmodinfo, Win32_DWORD cb) @cname("K32GetModuleInformation");
|
||||
extern fn Win32_DWORD symAddrIncludeInlineTrace(Win32_HANDLE hProcess, Win32_DWORD64 address) @cname("SymAddrIncludeInlineTrace");
|
||||
extern fn Win32_BOOL symQueryInlineTrace(Win32_HANDLE hProcess, Win32_DWORD64 startAddress, Win32_DWORD startContext, Win32_DWORD64 startRetAddress, Win32_DWORD64 curAddress, Win32_LPDWORD curContext, Win32_LPDWORD curFrameIndex) @cname("SymQueryInlineTrace");
|
||||
extern fn Win32_BOOL symFromInlineContext(Win32_HANDLE hProcess, Win32_DWORD64 address, Win32_ULONG inlineContext, Win32_PDWORD64 displacement, Win32_PSYMBOL_INFO symbol) @cname("SymFromInlineContext");
|
||||
extern fn Win32_BOOL symGetLineFromInlineContext(Win32_HANDLE hProcess, Win32_DWORD64 qwAddr, Win32_ULONG inlineContext, Win32_DWORD64 qwModuleBaseAddress, Win32_PDWORD pdwDisplacement, Win32_PIMAGEHLP_LINE64 line64) @cname("SymGetLineFromInlineContext");
|
||||
extern fn Win32_ULONG rtlWalkFrameChain(Win32_PVOID*, Win32_ULONG, Win32_ULONG) @cname("RtlWalkFrameChain");
|
||||
extern fn Win32_BOOL symInitialize(Win32_HANDLE hProcess, Win32_PCSTR userSearchPath, Win32_BOOL fInvadeProcess) @cname("SymInitialize");
|
||||
extern fn Win32_BOOL symCleanup(Win32_HANDLE hProcess) @cname("SymCleanup");
|
||||
extern fn Win32_DWORD64 symLoadModuleEx(Win32_HANDLE hProcess, Win32_HANDLE hFile, Win32_PCSTR imageName, Win32_PCSTR moduleName, Win32_DWORD64 baseOfDll, Win32_DWORD dllSize, Win32_PMODLOAD_DATA data, Win32_DWORD flags) @cname("SymLoadModule");
|
||||
extern fn Win32_BOOL stackWalk64(Win32_DWORD machineType, Win32_HANDLE hProcess, Win32_HANDLE hThread, Win32_LPSTACKFRAME64 stackFrame, Win32_PVOID contextRecord, Win32_PREAD_PROCESS_MEMORY_ROUTINE64 readMemoryRoutine, Win32_PFUNCTION_TABLE_ACCESS_ROUTINE64 functionTableAccessRoutine, Win32_PGET_MODULE_BASE_ROUTINE64 getModuleBaseRoutine, Win32_PTRANSLATE_ADDRESS_ROUTINE64 translateAddress) @cname("StackWalk64");
|
||||
extern fn void rtlCaptureContext(Win32_PCONTEXT contextRecord) @cname("RtlCaptureContext");
|
||||
extern fn void* symFunctionTableAccess64(Win32_HANDLE hProcess, Win32_DWORD64 addrBase) @cname("SymFunctionTableAccess64");
|
||||
extern fn Win32_DWORD64 symGetModuleBase64(Win32_HANDLE hProcess, Win32_DWORD64 qwAddr) @cname("SymGetModuleBase64");
|
||||
extern fn Win32_DWORD getModuleBaseNameA(Win32_HANDLE hProcess, Win32_HMODULE hModule, Win32_LPSTR lpBaseName, Win32_DWORD nSize) @cname("K32GetModuleBaseNameA");
|
||||
extern fn Win32_DWORD symGetOptions() @cname("SymGetOptions");
|
||||
extern fn Win32_DWORD symSetOptions(Win32_DWORD symOptions) @cname("SymSetOptions");
|
||||
extern fn Win32_PIMAGE_NT_HEADERS imageNtHeader(Win32_PVOID base) @cname("ImageNtHeader");
|
||||
extern fn Win32_DWORD unDecorateSymbolName(Win32_PCSTR name, Win32_PSTR outputString, Win32_DWORD maxStringLength, Win32_DWORD flags) @cname("UnDecorateSymbolName");
|
||||
extern fn Win32_BOOL symFromAddr(Win32_HANDLE hProcess, Win32_DWORD64 address, Win32_PDWORD64 displacement, Win32_PSYMBOL_INFO symbol) @cname("SymFromAddr");
|
||||
extern fn Win32_BOOL symGetLineFromAddr64(Win32_HANDLE hProcess, Win32_DWORD64 dwAddr, Win32_PDWORD pdwDisplacement, Win32_PIMAGEHLP_LINE64 line) @cname("SymGetLineFromAddr64");
|
||||
extern fn Win32_WORD rtlCaptureStackBackTrace(Win32_DWORD framesToSkip, Win32_DWORD framesToCapture, Win32_PVOID *backTrace, Win32_PDWORD backTraceHash) @cname("RtlCaptureStackBackTrace");
|
||||
extern fn Win32_BOOL symGetModuleInfo64(Win32_HANDLE hProcess, Win32_DWORD64 qwAddr, Win32_PIMAGEHLP_MODULE64 moduleInfo) @cname("SymGetModuleInfo64");
|
||||
|
||||
fn Win32_DWORD? load_modules()
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@ module std::os::win32 @if(env::WIN32) @link("shell32");
|
||||
|
||||
typedef Win32_REFKNOWNFOLDERID = Win32_KNOWNFOLDERID*;
|
||||
typedef Win32_KNOWNFOLDERID = Win32_GUID;
|
||||
extern fn Win32_HRESULT shGetKnownFolderPath(Win32_REFKNOWNFOLDERID rfid, Win32_DWORD dwFlags, Win32_HANDLE hToken, Win32_PWSTR* ppszPath) @extern("SHGetKnownFolderPath");
|
||||
extern fn Win32_HRESULT shGetKnownFolderPath(Win32_REFKNOWNFOLDERID rfid, Win32_DWORD dwFlags, Win32_HANDLE hToken, Win32_PWSTR* ppszPath) @cname("SHGetKnownFolderPath");
|
||||
|
||||
const Win32_KNOWNFOLDERID FOLDERID_PROFILE = { 0x5E6C858F, 0x0E22, 0x4760, x"9AFEEA3317B67173" };
|
||||
const Win32_KNOWNFOLDERID FOLDERID_DESKTOP = { 0xB4BFCC3A, 0xDB2C, 0x424C, x"B0297FE99A87C641" };
|
||||
|
||||
@@ -110,26 +110,26 @@ const GWLP_HWNDPARENT = -8;
|
||||
const GWLP_USERDATA = -21;
|
||||
const GWLP_ID = -12;
|
||||
|
||||
extern fn Win32_HDC beginPaint(Win32_HWND, Win32_LPPAINTSTRUCT) @extern("BeginPaint");
|
||||
extern fn Win32_LRESULT callWindowProcW(Win32_WNDPROC lpPrevWndFunc, Win32_HWND hWnd, Win32_UINT msg, Win32_WPARAM wParam, Win32_LPARAM lParam) @extern("CallWindowProcW");
|
||||
extern fn Win32_HWND createWindowExW(Win32_DWORD, Win32_LPCWSTR, Win32_LPCWSTR, Win32_DWORD, CInt, CInt, CInt, CInt, Win32_HWND, Win32_HMENU, Win32_HINSTANCE, Win32_LPVOID) @extern("CreateWindowExW");
|
||||
extern fn Win32_LRESULT defWindowProcW(Win32_HWND, Win32_UINT, Win32_WPARAM, Win32_LPARAM) @extern("DefWindowProcW");
|
||||
extern fn Win32_BOOL dispatchMessage(Win32_MSG* lpMsg) @extern("DispatchMessageW");
|
||||
extern fn Win32_BOOL endPaint(Win32_HWND, Win32_LPPAINTSTRUCT) @extern("EndPaint");
|
||||
extern fn Win32_BOOL getMessageW(Win32_LPMSG, Win32_HWND, Win32_UINT, Win32_UINT) @extern("GetMessageW");
|
||||
extern fn Win32_BOOL getUpdateRect(Win32_HWND hWnd, Win32_LPRECT lpRect, Win32_BOOL bErase) @extern("GetUpdateRect");
|
||||
extern fn Win32_LONG_PTR getWindowLongPtrW(Win32_HWND hWnd, CInt nIndex) @extern("GetWindowLongPtrW");
|
||||
extern fn Win32_LONG getWindowLongW(Win32_HWND hWnd, CInt nIndex) @extern("GetWindowLongW");
|
||||
extern fn Win32_HCURSOR loadCursorW(Win32_HINSTANCE instance, Win32_LPCWSTR cursorName) @extern("LoadCursorW");
|
||||
extern fn Win32_HICON loadIconW(Win32_HINSTANCE instance, Win32_LPCWSTR iconName) @extern("LoadIconW");
|
||||
extern fn int messageBoxW(Win32_HWND hWnd, Win32_LPCWSTR lpText, Win32_LPCWSTR lpCaption, Win32_UINT uType) @extern("MessageBoxW");
|
||||
extern fn void postQuitMessage(CInt) @extern("PostQuitMessage");
|
||||
extern fn Win32_ATOM registerClassExW(Win32_WNDCLASSEXW*) @extern("RegisterClassExW");
|
||||
extern fn Win32_LONG_PTR setWindowLongPtrW(Win32_HWND hWnd, CInt nIndex, Win32_LONG_PTR dwNewLong) @extern("SetWindowLongPtrW");
|
||||
extern fn Win32_LONG setWindowLongW(Win32_HWND hWnd, CInt nIndex, Win32_LONG dwNewLong) @extern("SetWindowLongW");
|
||||
extern fn Win32_BOOL showWindow(Win32_HWND, CInt) @extern("ShowWindow");
|
||||
extern fn Win32_BOOL translateMessage(Win32_MSG* lpMsg) @extern("TranslateMessage");
|
||||
extern fn Win32_BOOL updateWindow(Win32_HWND) @extern("UpdateWindow");
|
||||
extern fn Win32_HDC beginPaint(Win32_HWND, Win32_LPPAINTSTRUCT) @cname("BeginPaint");
|
||||
extern fn Win32_LRESULT callWindowProcW(Win32_WNDPROC lpPrevWndFunc, Win32_HWND hWnd, Win32_UINT msg, Win32_WPARAM wParam, Win32_LPARAM lParam) @cname("CallWindowProcW");
|
||||
extern fn Win32_HWND createWindowExW(Win32_DWORD, Win32_LPCWSTR, Win32_LPCWSTR, Win32_DWORD, CInt, CInt, CInt, CInt, Win32_HWND, Win32_HMENU, Win32_HINSTANCE, Win32_LPVOID) @cname("CreateWindowExW");
|
||||
extern fn Win32_LRESULT defWindowProcW(Win32_HWND, Win32_UINT, Win32_WPARAM, Win32_LPARAM) @cname("DefWindowProcW");
|
||||
extern fn Win32_BOOL dispatchMessage(Win32_MSG* lpMsg) @cname("DispatchMessageW");
|
||||
extern fn Win32_BOOL endPaint(Win32_HWND, Win32_LPPAINTSTRUCT) @cname("EndPaint");
|
||||
extern fn Win32_BOOL getMessageW(Win32_LPMSG, Win32_HWND, Win32_UINT, Win32_UINT) @cname("GetMessageW");
|
||||
extern fn Win32_BOOL getUpdateRect(Win32_HWND hWnd, Win32_LPRECT lpRect, Win32_BOOL bErase) @cname("GetUpdateRect");
|
||||
extern fn Win32_LONG_PTR getWindowLongPtrW(Win32_HWND hWnd, CInt nIndex) @cname("GetWindowLongPtrW");
|
||||
extern fn Win32_LONG getWindowLongW(Win32_HWND hWnd, CInt nIndex) @cname("GetWindowLongW");
|
||||
extern fn Win32_HCURSOR loadCursorW(Win32_HINSTANCE instance, Win32_LPCWSTR cursorName) @cname("LoadCursorW");
|
||||
extern fn Win32_HICON loadIconW(Win32_HINSTANCE instance, Win32_LPCWSTR iconName) @cname("LoadIconW");
|
||||
extern fn int messageBoxW(Win32_HWND hWnd, Win32_LPCWSTR lpText, Win32_LPCWSTR lpCaption, Win32_UINT uType) @cname("MessageBoxW");
|
||||
extern fn void postQuitMessage(CInt) @cname("PostQuitMessage");
|
||||
extern fn Win32_ATOM registerClassExW(Win32_WNDCLASSEXW*) @cname("RegisterClassExW");
|
||||
extern fn Win32_LONG_PTR setWindowLongPtrW(Win32_HWND hWnd, CInt nIndex, Win32_LONG_PTR dwNewLong) @cname("SetWindowLongPtrW");
|
||||
extern fn Win32_LONG setWindowLongW(Win32_HWND hWnd, CInt nIndex, Win32_LONG dwNewLong) @cname("SetWindowLongW");
|
||||
extern fn Win32_BOOL showWindow(Win32_HWND, CInt) @cname("ShowWindow");
|
||||
extern fn Win32_BOOL translateMessage(Win32_MSG* lpMsg) @cname("TranslateMessage");
|
||||
extern fn Win32_BOOL updateWindow(Win32_HWND) @cname("UpdateWindow");
|
||||
|
||||
macro getWindowLongPtr(Win32_HWND hWnd, CInt nIndex)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module std::os::win32 @if(env::WIN32);
|
||||
module std::os::win32 @if(env::WIN32) @link("ws2_32");
|
||||
|
||||
// See https://github.com/wine-mirror/wine/blob/master/include/winsock2.h
|
||||
|
||||
@@ -122,11 +122,11 @@ const SD_RECEIVE = 0x00;
|
||||
const SD_SEND = 0x01;
|
||||
const SD_BOTH = 0x02;
|
||||
|
||||
extern fn CInt wsaPoll(Win32_LPWSAPOLLFD fdArray, Win32_ULONG fds, Win32_INT timeout) @extern("WSAPoll");
|
||||
extern fn WSAError wsaGetLastError() @extern("WSAGetLastError");
|
||||
extern fn void wsaSetLastError(WSAError error) @extern("WSASetLastError");
|
||||
extern fn CInt wsaStartup(Win32_WORD, void*) @extern("WSAStartup");
|
||||
extern fn CInt wsaCleanup() @extern("WSACleanup");
|
||||
extern fn CInt wsaPoll(Win32_LPWSAPOLLFD fdArray, Win32_ULONG fds, Win32_INT timeout) @cname("WSAPoll");
|
||||
extern fn WSAError wsaGetLastError() @cname("WSAGetLastError");
|
||||
extern fn void wsaSetLastError(WSAError error) @cname("WSASetLastError");
|
||||
extern fn CInt wsaStartup(Win32_WORD, void*) @cname("WSAStartup");
|
||||
extern fn CInt wsaCleanup() @cname("WSACleanup");
|
||||
|
||||
const int FIONBIO = -2147195266;
|
||||
const int FIONREAD = 1074030207;
|
||||
|
||||
@@ -3,6 +3,8 @@ module std::sort;
|
||||
<*
|
||||
Perform a binary search over the sorted array and return the index
|
||||
in [0, array.len) where x would be inserted or cmp(i) is true and cmp(j) is true for j in [i, array.len).
|
||||
|
||||
@require @list_is_by_ref(list) : "Expected a list passed by reference or a slice"
|
||||
@require @is_sortable(list) : "The list must be sortable"
|
||||
@require @is_valid_cmp_fn(cmp, list, context) : "Expected a comparison function which compares values"
|
||||
@require @is_valid_context(cmp, context) : "Expected a valid context"
|
||||
@@ -10,42 +12,81 @@ in [0, array.len) where x would be inserted or cmp(i) is true and cmp(j) is true
|
||||
macro usz binarysearch(list, x, cmp = EMPTY_MACRO_SLOT, context = EMPTY_MACRO_SLOT) @builtin
|
||||
{
|
||||
usz i;
|
||||
usz len = lengthof(list);
|
||||
var $no_cmp = @is_empty_macro_slot(cmp);
|
||||
var $has_context = @is_valid_macro_slot(context);
|
||||
for (usz j = len; i < j;)
|
||||
{
|
||||
usz half = i + (j - i) / 2;
|
||||
$if $no_cmp:
|
||||
switch
|
||||
{
|
||||
case greater(list[half], x): j = half;
|
||||
case less(list[half], x): i = half + 1;
|
||||
default: return half;
|
||||
}
|
||||
$else
|
||||
|
||||
$switch:
|
||||
$case $defined(cmp(list[0], list[0], context)):
|
||||
int res = cmp(list[half], x, context);
|
||||
$case $defined(cmp(list[0], list[0])):
|
||||
assert(!$has_context);
|
||||
int res = cmp(list[half], x);
|
||||
$case $defined(cmp(&list[0], &list[0], context)):
|
||||
int res = cmp(&list[half], &x, context);
|
||||
$case $defined(cmp(&list[0], &list[0])):
|
||||
assert(!$has_context);
|
||||
int res = cmp(&list[half], &x);
|
||||
$default:
|
||||
assert(false, "Invalid comparison function");
|
||||
$endswitch
|
||||
switch
|
||||
{
|
||||
case res > 0: j = half;
|
||||
case res < 0: i = half + 1;
|
||||
default: return half;
|
||||
}
|
||||
$endif
|
||||
}
|
||||
return i;
|
||||
$if $kindof(list) == SLICE:
|
||||
usz len = lengthof(list);
|
||||
for (usz j = len; i < j;)
|
||||
{
|
||||
usz half = i + (j - i) / 2;
|
||||
$if $no_cmp:
|
||||
switch
|
||||
{
|
||||
case greater(list[half], x): j = half;
|
||||
case less(list[half], x): i = half + 1;
|
||||
default: return half;
|
||||
}
|
||||
$else
|
||||
|
||||
$switch:
|
||||
$case $defined(cmp(list[0], list[0], context)):
|
||||
int res = cmp(list[half], x, context);
|
||||
$case $defined(cmp(list[0], list[0])):
|
||||
assert(!$has_context);
|
||||
int res = cmp(list[half], x);
|
||||
$case $defined(cmp(&list[0], &list[0], context)):
|
||||
int res = cmp(&list[half], &x, context);
|
||||
$case $defined(cmp(&list[0], &list[0])):
|
||||
assert(!$has_context);
|
||||
int res = cmp(&list[half], &x);
|
||||
$default:
|
||||
assert(false, "Invalid comparison function");
|
||||
$endswitch
|
||||
switch
|
||||
{
|
||||
case res > 0: j = half;
|
||||
case res < 0: i = half + 1;
|
||||
default: return half;
|
||||
}
|
||||
$endif
|
||||
}
|
||||
$else
|
||||
usz len = lengthof(*list);
|
||||
for (usz j = len; i < j;)
|
||||
{
|
||||
usz half = i + (j - i) / 2;
|
||||
$if $no_cmp:
|
||||
switch
|
||||
{
|
||||
case greater((*list)[half], x): j = half;
|
||||
case less((*list)[half], x): i = half + 1;
|
||||
default: return half;
|
||||
}
|
||||
$else
|
||||
|
||||
$switch:
|
||||
$case $defined(cmp((*list)[0], (*list)[0], context)):
|
||||
int res = cmp(list[half], x, context);
|
||||
$case $defined(cmp((*list)[0], (*list)[0])):
|
||||
assert(!$has_context);
|
||||
int res = cmp((*list)[half], x);
|
||||
$case $defined(cmp(&(*list)[0], &(*list)[0], context)):
|
||||
int res = cmp(&(*list)[half], &x, context);
|
||||
$case $defined(cmp(&(*list)[0], &(*list)[0])):
|
||||
assert(!$has_context);
|
||||
int res = cmp(&(*list)[half], &x);
|
||||
$default:
|
||||
assert(false, "Invalid comparison function");
|
||||
$endswitch
|
||||
switch
|
||||
{
|
||||
case res > 0: j = half;
|
||||
case res < 0: i = half + 1;
|
||||
default: return half;
|
||||
}
|
||||
$endif
|
||||
}
|
||||
$endif
|
||||
return i;
|
||||
}
|
||||
@@ -4,24 +4,39 @@ import std::sort::cs;
|
||||
import std::sort::qs;
|
||||
|
||||
<*
|
||||
Sort list using the counting sort algorithm.
|
||||
|
||||
Sort list using the counting sort algorithm.
|
||||
|
||||
@require @list_is_by_ref(list) : "Expected the list to be passed by reference"
|
||||
@require @is_sortable(list) : "The list must be indexable and support .len or .len()"
|
||||
@require @is_cmp_key_fn(key_fn, list) : "Expected a transformation function which returns an unsigned integer."
|
||||
*>
|
||||
macro void countingsort(list, key_fn = EMPTY_MACRO_SLOT) @builtin
|
||||
{
|
||||
usz len = lengthof(list);
|
||||
cs::csort{$typeof(list), $typeof(key_fn)}(list, 0, len, key_fn, ~((uint)0));
|
||||
$if $kindof(list) == SLICE:
|
||||
cs::csort{$typeof(list), $typeof(key_fn)}(list, 0, list.len, key_fn, ~((uint)0));
|
||||
$else
|
||||
cs::csort{$typeof(*list), $typeof(key_fn)}(list, 0, lengthof(*list), key_fn, ~((uint)0));
|
||||
$endif
|
||||
}
|
||||
|
||||
macro void insertionsort_indexed(list, start, end, cmp = EMPTY_MACRO_SLOT, context = EMPTY_MACRO_SLOT) @builtin
|
||||
{
|
||||
is::isort{$typeof(list), $typeof(cmp), $typeof(context)}(list, (usz)start, (usz)end, cmp, context);
|
||||
$if $kindof(list) == SLICE:
|
||||
is::isort{$typeof((list)), $typeof(cmp), $typeof(context)}(list, (usz)start, (usz)end, cmp, context);
|
||||
$else
|
||||
is::isort{$typeof((*list)), $typeof(cmp), $typeof(context)}(list, (usz)start, (usz)end, cmp, context);
|
||||
$endif
|
||||
|
||||
}
|
||||
|
||||
macro void quicksort_indexed(list, start, end, cmp = EMPTY_MACRO_SLOT, context = EMPTY_MACRO_SLOT) @builtin
|
||||
{
|
||||
qs::qsort{$typeof(list), $typeof(cmp), $typeof(context)}(list, (isz)start, (isz)(end-1), cmp, context);
|
||||
$if $kindof(list) == SLICE:
|
||||
qs::qsort{$typeof((list)), $typeof(cmp), $typeof(context)}(list, (isz)start, (isz)(end-1), cmp, context);
|
||||
$else
|
||||
qs::qsort{$typeof((*list)), $typeof(cmp), $typeof(context)}(list, (isz)start, (isz)(end-1), cmp, context);
|
||||
$endif
|
||||
}
|
||||
|
||||
module std::sort::cs{Type, KeyFn};
|
||||
@@ -42,7 +57,14 @@ alias CmpCallback @if(!KEY_BY_VALUE && NO_KEY_FN) = fn int(ElementType*, Element
|
||||
alias CmpCallback @if(KEY_BY_VALUE && !NO_KEY_FN) = fn int(ElementType, ElementType, KeyFn);
|
||||
alias CmpCallback @if(!KEY_BY_VALUE && !NO_KEY_FN) = fn int(ElementType*, ElementType*, KeyFn);
|
||||
|
||||
fn void csort(Type list, usz low, usz high, KeyFn key_fn, uint byte_idx)
|
||||
const bool IS_SLICE = Type.kindof == SLICE;
|
||||
alias ListType = $typefrom(IS_SLICE ??? Type : Type*);
|
||||
macro list_get(ListType l, i) @if(!IS_SLICE) => (*l)[i];
|
||||
macro list_get(ListType l, i) @if(IS_SLICE) => l[i];
|
||||
macro list_get_ref(ListType l, i) @if(!IS_SLICE) => &(*l)[i];
|
||||
macro list_get_ref(ListType l, i) @if(IS_SLICE) => &l[i];
|
||||
|
||||
fn void csort(ListType list, usz low, usz high, KeyFn key_fn, uint byte_idx)
|
||||
{
|
||||
if (high <= low) return;
|
||||
$if NO_KEY_FN:
|
||||
@@ -67,13 +89,13 @@ fn void csort(Type list, usz low, usz high, KeyFn key_fn, uint byte_idx)
|
||||
{
|
||||
$switch:
|
||||
$case NO_KEY_FN:
|
||||
KeyFnReturnType k = list[i];
|
||||
KeyFnReturnType k = list_get(list, i);
|
||||
$case KEY_BY_VALUE:
|
||||
KeyFnReturnType k = key_fn(list[i]);
|
||||
KeyFnReturnType k = key_fn(list_get(list, i));
|
||||
$case LIST_HAS_REF:
|
||||
KeyFnReturnType k = key_fn(&list[i]);
|
||||
KeyFnReturnType k = key_fn(list_get_ref(list, i));
|
||||
$default:
|
||||
KeyFnReturnType k = key_fn(&&list[i]);
|
||||
KeyFnReturnType k = key_fn(&&list_get(list, i));
|
||||
$endswitch;
|
||||
|
||||
char key_byte = (char)((k >> (byte_idx * 8)) & 0xff);
|
||||
@@ -131,17 +153,21 @@ fn void csort(Type list, usz low, usz high, KeyFn key_fn, uint byte_idx)
|
||||
{
|
||||
$switch:
|
||||
$case NO_KEY_FN:
|
||||
KeyFnReturnType k = list[low + s];
|
||||
KeyFnReturnType k = list_get(list, low + s);
|
||||
$case KEY_BY_VALUE:
|
||||
KeyFnReturnType k = key_fn(list[low + s]);
|
||||
KeyFnReturnType k = key_fn(list_get(list, low + s));
|
||||
$case LIST_HAS_REF:
|
||||
KeyFnReturnType k = key_fn(&list[low + s]);
|
||||
KeyFnReturnType k = key_fn(list_get_ref(list, low + s));
|
||||
$default:
|
||||
KeyFnReturnType k = key_fn(&&list[low + s]);
|
||||
KeyFnReturnType k = key_fn(&&list_get(list, low + s));
|
||||
$endswitch;
|
||||
char k_idx = (char)(k >> (byte_idx * 8));
|
||||
usz target_idx = counts[k_idx];
|
||||
@swap(list[low + s], list[low + target_idx]);
|
||||
$if IS_SLICE:
|
||||
@swap(list[low + s], list[low + target_idx]);
|
||||
$else
|
||||
@swap((*list)[low + s], (*list)[low + target_idx]);
|
||||
$endif
|
||||
counts[k_idx]++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,38 +4,41 @@ import std::sort::is;
|
||||
<*
|
||||
Sort list using the quick sort algorithm.
|
||||
|
||||
@require @list_is_by_ref(list) : "Expected a list passed by reference, or slice passed by value"
|
||||
@require @is_sortable(list) : "The list must be indexable and support .len or .len()"
|
||||
@require @is_valid_cmp_fn(cmp, list, context) : "Expected a comparison function which compares values"
|
||||
*>
|
||||
macro void insertionsort(list, cmp = EMPTY_MACRO_SLOT, context = EMPTY_MACRO_SLOT) @builtin @safemacro
|
||||
{
|
||||
$if $kindof(list) == POINTER &&& ($kindof(*list) == ARRAY || $kindof(*list) == VECTOR):
|
||||
$typeof((*list)[0])[] list2 = list;
|
||||
is::isort{$typeof(list2), $typeof(cmp), $typeof(context)}(list2, 0, list.len, cmp, context);
|
||||
$if $kindof(list) == SLICE:
|
||||
is::isort{$typeof(list), $typeof(cmp), $typeof(context)}(list, 0, lengthof(list), cmp, context);
|
||||
$else
|
||||
usz len = lengthof(list);
|
||||
is::isort{$typeof(list), $typeof(cmp), $typeof(context)}(list, 0, (isz)len, cmp, context);
|
||||
is::isort{$typeof(*list), $typeof(cmp), $typeof(context)}(list, 0, lengthof(*list), cmp, context);
|
||||
$endif
|
||||
}
|
||||
|
||||
module std::sort::is{Type, CmpFn, Context};
|
||||
|
||||
alias ElementType = $typeof(((Type){})[0]);
|
||||
const bool IS_SLICE = Type.kindof == SLICE;
|
||||
alias ListType = $typefrom(IS_SLICE ??? Type : Type*);
|
||||
macro ElementType list_get(ListType l, i) => IS_SLICE ??? l[i] : (*l)[i];
|
||||
macro ElementType* list_get_ref(ListType l, i) => IS_SLICE ??? &l[i] : &(*l)[i];
|
||||
|
||||
fn void isort(Type list, usz low, usz high, CmpFn comp, Context context)
|
||||
fn void isort(ListType list, usz low, usz high, CmpFn comp, Context context)
|
||||
{
|
||||
var $has_cmp = @is_valid_macro_slot(comp);
|
||||
var $has_context = @is_valid_macro_slot(context);
|
||||
var $cmp_by_value = $has_cmp &&& $defined($typefrom(CmpFn.paramsof[0].type) p = list[0]);
|
||||
var $has_get_ref = $defined(&list[0]);
|
||||
var $cmp_by_value = $has_cmp &&& $defined($typefrom(CmpFn.paramsof[0].type) p = list_get(list, 0));
|
||||
var $has_get_ref = IS_SLICE ||| $defined(&(*list)[0]);
|
||||
for (usz i = low; i < high; ++i)
|
||||
{
|
||||
usz j = i;
|
||||
for (;j > low;)
|
||||
{
|
||||
$if $has_get_ref:
|
||||
ElementType *rhs = &list[j];
|
||||
ElementType *lhs = &list[--j];
|
||||
ElementType *rhs = list_get_ref(list, j);
|
||||
ElementType *lhs = list_get_ref(list, --j);
|
||||
$switch:
|
||||
$case $cmp_by_value && $has_context:
|
||||
if (comp(*rhs, *lhs, context) >= 0) break;
|
||||
@@ -54,17 +57,21 @@ fn void isort(Type list, usz low, usz high, CmpFn comp, Context context)
|
||||
--j;
|
||||
$switch:
|
||||
$case $cmp_by_value && $has_context:
|
||||
if (comp(list[r], list[j], context) >= 0) break;
|
||||
if (comp(list_get(list, r), list_get(j), context) >= 0) break;
|
||||
$case $cmp_by_value:
|
||||
if (comp(list[r], list[j]) >= 0) break;
|
||||
if (comp(list_get(list, r), list_get(j)) >= 0) break;
|
||||
$case $has_cmp && $has_context:
|
||||
if (comp(&list[r], &list[j], context) >= 0) break;
|
||||
if (comp(list_get_ref(list, r), list_get_ref(j), context) >= 0) break;
|
||||
$case $has_cmp:
|
||||
if (comp(&list[r], &list[j]) >= 0) break;
|
||||
if (comp(list_get_ref(list, r), list_get_ref(j)) >= 0) break;
|
||||
$default:
|
||||
if (!less(list[r], list[j])) break;
|
||||
if (!less(list_get(list, r), list_get(j))) break;
|
||||
$endswitch
|
||||
@swap(list[r], list[j]);
|
||||
$if IS_SLICE:
|
||||
@swap(list[r], list[j]);
|
||||
$else
|
||||
@swap((*list)[r], (*list)[j]);
|
||||
$endif
|
||||
$endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,39 +4,50 @@ import std::sort::qs;
|
||||
<*
|
||||
Sort list using the quick sort algorithm.
|
||||
|
||||
@require @list_is_by_ref(list) : "Expected a list passed by reference or be a slice"
|
||||
@require @is_sortable(list) : "The list must be indexable and support .len or .len()"
|
||||
@require @is_valid_cmp_fn(cmp, list, context) : "Expected a comparison function which compares values"
|
||||
@require @is_valid_context(cmp, context) : "Expected a valid context"
|
||||
*>
|
||||
macro void quicksort(list, cmp = EMPTY_MACRO_SLOT, context = EMPTY_MACRO_SLOT) @builtin
|
||||
{
|
||||
$if $kindof(list) == POINTER &&& ($kindof(*list) == ARRAY || $kindof(*list) == VECTOR):
|
||||
$typeof((*list)[0])[] list2 = list;
|
||||
qs::qsort{$typeof(list2), $typeof(cmp), $typeof(context)}(list2, 0, (isz)list.len - 1, cmp, context);
|
||||
$if $kindof(list) == SLICE:
|
||||
qs::qsort{$typeof(list), $typeof(cmp), $typeof(context)}(list, 0, (isz)list.len - 1, cmp, context);
|
||||
$else
|
||||
usz len = lengthof(list);
|
||||
qs::qsort{$typeof(list), $typeof(cmp), $typeof(context)}(list, 0, (isz)len - 1, cmp, context);
|
||||
qs::qsort{$typeof(*list), $typeof(cmp), $typeof(context)}(list, 0, (isz)lengthof(*list) - 1, cmp, context);
|
||||
$endif
|
||||
}
|
||||
|
||||
<*
|
||||
Select the (k+1)th smallest element in an unordered list using Hoare's
|
||||
selection algorithm (Quickselect). k should be between 0 and len-1. The data
|
||||
list will be partially sorted.
|
||||
Select the (k+1)th smallest element in an unordered list using Hoare's
|
||||
selection algorithm (Quickselect). k should be between 0 and len-1. The data
|
||||
list will be partially sorted.
|
||||
|
||||
@require @list_is_by_ref(list) : "Expected a list passed by reference or be a slice"
|
||||
@require @is_sortable(list) : "The list must be indexable and support .len or .len()"
|
||||
@require @is_valid_cmp_fn(cmp, list, context) : "expected a comparison function which compares values"
|
||||
@require @is_valid_context(cmp, context) : "Expected a valid context"
|
||||
*>
|
||||
macro quickselect(list, isz k, cmp = EMPTY_MACRO_SLOT, context = EMPTY_MACRO_SLOT) @builtin
|
||||
{
|
||||
usz len = lengthof(list);
|
||||
return qs::qselect{$typeof(list), $typeof(cmp), $typeof(context)}(list, 0, (isz)len - 1, k, cmp, context);
|
||||
$if $kindof(list) == SLICE:
|
||||
return qs::qselect{$typeof(list), $typeof(cmp), $typeof(context)}(list, 0, (isz)list.len - 1, k, cmp, context);
|
||||
$else
|
||||
return qs::qselect{$typeof(*list), $typeof(cmp), $typeof(context)}(list, 0, (isz)lengthof(*list) - 1, k, cmp, context);
|
||||
$endif
|
||||
}
|
||||
|
||||
module std::sort::qs{Type, CmpFn, Context};
|
||||
|
||||
alias ElementType = $typeof(((Type){})[0]);
|
||||
const bool IS_SLICE = Type.kindof == SLICE;
|
||||
alias ListType = $typefrom(IS_SLICE ??? Type : Type*);
|
||||
macro list_get(ListType l, i) @if(!IS_SLICE) => (*l)[i];
|
||||
macro list_get(ListType l, i) @if(IS_SLICE) => l[i];
|
||||
macro list_get_ref(ListType l, i) @if(!IS_SLICE) => &(*l)[i];
|
||||
macro list_get_ref(ListType l, i) @if(IS_SLICE) => &l[i];
|
||||
macro list_set(ListType l, i, v) @if(!IS_SLICE) => (*l)[i] = v;
|
||||
macro list_set(ListType l, i, v) @if(IS_SLICE) => l[i] = v;
|
||||
|
||||
struct StackElementItem @private
|
||||
{
|
||||
@@ -48,7 +59,7 @@ alias Stack @private = StackElementItem[64];
|
||||
|
||||
// Based on https://alienryderflex.com/quicksort by Darel Rex Finley, Public Domain.
|
||||
|
||||
fn void qsort(Type list, isz low, isz high, CmpFn cmp, Context context)
|
||||
fn void qsort(ListType list, isz low, isz high, CmpFn cmp, Context context)
|
||||
{
|
||||
if (low >= 0 && high >= 0 && low < high)
|
||||
{
|
||||
@@ -86,7 +97,7 @@ fn void qsort(Type list, isz low, isz high, CmpFn cmp, Context context)
|
||||
@require low <= k : "kth smallest element is smaller than lower bounds"
|
||||
@require k <= high : "kth smallest element is larger than upper bounds"
|
||||
*>
|
||||
fn ElementType? qselect(Type list, isz low, isz high, isz k, CmpFn cmp, Context context)
|
||||
fn ElementType? qselect(ListType list, isz low, isz high, isz k, CmpFn cmp, Context context)
|
||||
{
|
||||
if (low >= 0 && high >= 0 && low < high)
|
||||
{
|
||||
@@ -98,7 +109,7 @@ fn ElementType? qselect(Type list, isz low, isz high, isz k, CmpFn cmp, Context
|
||||
while (l <= h && max_retries--)
|
||||
{
|
||||
pivot = @partition(list, l, h, cmp, context);
|
||||
if (k == pivot) return list[k];
|
||||
if (k == pivot) return list_get(list, k);
|
||||
if (k < pivot)
|
||||
{
|
||||
h = pivot - 1;
|
||||
@@ -112,40 +123,40 @@ fn ElementType? qselect(Type list, isz low, isz high, isz k, CmpFn cmp, Context
|
||||
return NOT_FOUND?;
|
||||
}
|
||||
|
||||
macro isz @partition(Type list, isz l, isz h, CmpFn cmp, Context context)
|
||||
macro isz @partition(ListType list, isz l, isz h, CmpFn cmp, Context context)
|
||||
{
|
||||
var $has_cmp = @is_valid_macro_slot(cmp);
|
||||
var $has_context = @is_valid_macro_slot(context);
|
||||
var $cmp_by_value = $has_cmp &&& $defined($typefrom(CmpFn.paramsof[0].type) v = list[0]);
|
||||
var $cmp_by_value = $has_cmp &&& $defined($typefrom(CmpFn.paramsof[0].type) v = list_get(list, 0));
|
||||
|
||||
ElementType pivot = list[l];
|
||||
ElementType pivot = list_get(list, l);
|
||||
while (l < h)
|
||||
{
|
||||
$switch:
|
||||
$case $cmp_by_value && $has_context:
|
||||
while (cmp(list[h], pivot, context) >= 0 && l < h) h--;
|
||||
if (l < h) list[l++] = list[h];
|
||||
while (cmp(list[l], pivot, context) <= 0 && l < h) l++;
|
||||
while (cmp(list_get(list, h), pivot, context) >= 0 && l < h) h--;
|
||||
if (l < h) list_set(list, l++, list_get(list, h));
|
||||
while (cmp(list_get(list, l), pivot, context) <= 0 && l < h) l++;
|
||||
$case $cmp_by_value:
|
||||
while (cmp(list[h], pivot) >= 0 && l < h) h--;
|
||||
if (l < h) list[l++] = list[h];
|
||||
while (cmp(list[l], pivot) <= 0 && l < h) l++;
|
||||
while (cmp(list_get(list, h), pivot) >= 0 && l < h) h--;
|
||||
if (l < h) list_set(list, l++, list_get(list, h));
|
||||
while (cmp(list_get(list, l), pivot) <= 0 && l < h) l++;
|
||||
$case $has_cmp && $has_context:
|
||||
while (cmp(&list[h], &pivot, context) >= 0 && l < h) h--;
|
||||
if (l < h) list[l++] = list[h];
|
||||
while (cmp(&list[l], &pivot, context) <= 0 && l < h) l++;
|
||||
while (cmp(list_get_ref(list, h), &pivot, context) >= 0 && l < h) h--;
|
||||
if (l < h) list_set(list, l++, list_get(list, h));
|
||||
while (cmp(list_get_ref(list, l), &pivot, context) <= 0 && l < h) l++;
|
||||
$case $has_cmp:
|
||||
while (cmp(&list[h], &pivot) >= 0 && l < h) h--;
|
||||
if (l < h) list[l++] = list[h];
|
||||
while (cmp(&list[l], &pivot) <= 0 && l < h) l++;
|
||||
while (cmp(list_get_ref(list, h), &pivot) >= 0 && l < h) h--;
|
||||
if (l < h) list_set(list, l++, list_get(list, h));
|
||||
while (cmp(list_get_ref(list, l), &pivot) <= 0 && l < h) l++;
|
||||
$default:
|
||||
while (greater_eq(list[h], pivot) && l < h) h--;
|
||||
if (l < h) list[l++] = list[h];
|
||||
while (less_eq(list[l], pivot) && l < h) l++;
|
||||
while (greater_eq(list_get(list, h), pivot) && l < h) h--;
|
||||
if (l < h) list_set(list, l++, list_get(list, h));
|
||||
while (less_eq(list_get(list, l), pivot) && l < h) l++;
|
||||
$endswitch
|
||||
if (l < h) list[h--] = list[l];
|
||||
if (l < h) list_set(list, h--, list_get(list, l));
|
||||
}
|
||||
list[l] = pivot;
|
||||
list_set(list, l, pivot);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
@@ -1,50 +1,132 @@
|
||||
module std::sort;
|
||||
|
||||
macro bool @list_is_by_ref(#list) @const
|
||||
{
|
||||
return $kindof(#list) == SLICE ||| ($kindof(#list) == POINTER &&& $kindof(*#list) != SLICE);
|
||||
}
|
||||
|
||||
macro bool @is_sortable(#list)
|
||||
<*
|
||||
@require @list_is_by_ref(#list) : "Expected the list to be passed by ref or be a slice"
|
||||
*>
|
||||
macro bool @is_sortable(#list) @const
|
||||
{
|
||||
$switch:
|
||||
$case !$defined(#list[0]):
|
||||
$case $kindof(#list) == SLICE:
|
||||
return true;
|
||||
$case !$defined(*#list):
|
||||
return false;
|
||||
$case !$defined(#list.len):
|
||||
$case !$defined((*#list)[0]):
|
||||
return false;
|
||||
$case $kindof(#list) == VECTOR || $kindof(#list) == ARRAY:
|
||||
$case !$defined(lengthof(*#list)):
|
||||
return false;
|
||||
$case $defined(&#list[0]) &&& !types::is_same($typeof(&#list[0]), $typeof(#list[0])*):
|
||||
$case $defined(&(*#list)[0]) &&& $typeof(&(*#list)[0]) != $typeof((*#list)[0])*:
|
||||
return false;
|
||||
$default:
|
||||
return true;
|
||||
$endswitch
|
||||
}
|
||||
|
||||
macro bool @is_any_sortable(#list) @const
|
||||
{
|
||||
$switch $kindof(#list):
|
||||
$case SLICE:
|
||||
return true;
|
||||
$case POINTER:
|
||||
return @is_sortable(#list);
|
||||
$default:
|
||||
return $defined(#list[0]) &&& $defined(lengthof(#list))
|
||||
&&& !($defined(&#list[0]) &&& $typeof(&#list[0]) != $typeof(#list[0])*);
|
||||
$endswitch
|
||||
}
|
||||
|
||||
macro bool @is_valid_context(#cmp, #context)
|
||||
{
|
||||
return @is_valid_macro_slot(#cmp) || @is_empty_macro_slot(#context);
|
||||
}
|
||||
|
||||
macro bool @is_valid_cmp_fn(#cmp, #list, #context)
|
||||
|
||||
<*
|
||||
@require @list_is_by_ref(#list) : "Expected the list to be passed by ref or be a slice"
|
||||
*>
|
||||
macro bool @is_valid_cmp_fn(#cmp, #list, #context) @const
|
||||
{
|
||||
var $Type = $typeof(#cmp);
|
||||
var $no_context = @is_empty_macro_slot(#context);
|
||||
$switch:
|
||||
$case @is_empty_macro_slot(#cmp): return true;
|
||||
$case $Type.kindof != FUNC ||| $Type.returns.kindof != SIGNED_INT: return false;
|
||||
$case $defined(#cmp(#list[0], #list[0], #context)): return true;
|
||||
$case $defined(#cmp(#list[0], #list[0])): return $no_context;
|
||||
$case $defined(#cmp(&#list[0], &#list[0], #context)): return true;
|
||||
$case $defined(#cmp(&#list[0], &#list[0])): return $no_context;
|
||||
$default: return false;
|
||||
$default:
|
||||
$if $kindof(#list) == SLICE:
|
||||
$switch:
|
||||
$case $defined(#cmp((#list)[0], (#list)[0], #context)): return true;
|
||||
$case $defined(#cmp((#list)[0], (#list)[0])): return $no_context;
|
||||
$case $defined(#cmp(&(#list)[0], &(#list)[0], #context)): return true;
|
||||
$case $defined(#cmp(&(#list)[0], &(#list)[0])): return $no_context;
|
||||
$default: return false;
|
||||
$endswitch
|
||||
$else
|
||||
$switch:
|
||||
$case $defined(#cmp((*#list)[0], (*#list)[0], #context)): return true;
|
||||
$case $defined(#cmp((*#list)[0], (*#list)[0])): return $no_context;
|
||||
$case $defined(#cmp(&(*#list)[0], &(*#list)[0], #context)): return true;
|
||||
$case $defined(#cmp(&(*#list)[0], &(*#list)[0])): return $no_context;
|
||||
$default: return false;
|
||||
$endswitch
|
||||
$endif
|
||||
$endswitch
|
||||
}
|
||||
|
||||
macro bool @is_cmp_key_fn(#key_fn, #list)
|
||||
macro bool @is_any_valid_cmp_fn(#cmp, #list, #context) @const
|
||||
{
|
||||
var $Type = $typeof(#cmp);
|
||||
var $no_context = @is_empty_macro_slot(#context);
|
||||
$switch:
|
||||
$case @is_empty_macro_slot(#cmp): return true;
|
||||
$case $Type.kindof != FUNC ||| $Type.returns.kindof != SIGNED_INT: return false;
|
||||
$default:
|
||||
$if $kindof(#list) != POINTER:
|
||||
$switch:
|
||||
$case $defined(#cmp((#list)[0], (#list)[0], #context)): return true;
|
||||
$case $defined(#cmp((#list)[0], (#list)[0])): return $no_context;
|
||||
$case $defined(#cmp(&(#list)[0], &(#list)[0], #context)): return true;
|
||||
$case $defined(#cmp(&(#list)[0], &(#list)[0])): return $no_context;
|
||||
$default: return false;
|
||||
$endswitch
|
||||
$else
|
||||
$switch:
|
||||
$case $defined(#cmp((*#list)[0], (*#list)[0], #context)): return true;
|
||||
$case $defined(#cmp((*#list)[0], (*#list)[0])): return $no_context;
|
||||
$case $defined(#cmp(&(*#list)[0], &(*#list)[0], #context)): return true;
|
||||
$case $defined(#cmp(&(*#list)[0], &(*#list)[0])): return $no_context;
|
||||
$default: return false;
|
||||
$endswitch
|
||||
$endif
|
||||
$endswitch
|
||||
}
|
||||
|
||||
<*
|
||||
@require @list_is_by_ref(#list) : "Expected the list to be passed by ref or be a slice"
|
||||
*>
|
||||
macro bool @is_cmp_key_fn(#key_fn, #list) @const
|
||||
{
|
||||
$switch:
|
||||
$case @is_empty_macro_slot(#key_fn): return true;
|
||||
$case $kindof(#key_fn) != FUNC: return false;
|
||||
$case $typeof(#key_fn).returns.kindof != UNSIGNED_INT: return false;
|
||||
$case $defined(#key_fn(#list[0])): return true;
|
||||
$case $defined(#key_fn(&&(#list[0]))): return true;
|
||||
$default: return false;
|
||||
$default:
|
||||
$if $kindof(#list) == SLICE:
|
||||
$switch:
|
||||
$case $defined(#key_fn((#list)[0])): return true;
|
||||
$case $defined(#key_fn(&&((#list)[0]))): return true;
|
||||
$default: return false;
|
||||
$endswitch
|
||||
$else
|
||||
$switch:
|
||||
$case $defined(#key_fn((*#list)[0])): return true;
|
||||
$case $defined(#key_fn(&&((*#list)[0]))): return true;
|
||||
$default: return false;
|
||||
$endswitch
|
||||
$endif
|
||||
$endswitch
|
||||
|
||||
}
|
||||
@@ -1,13 +1,15 @@
|
||||
module std::sort;
|
||||
|
||||
<*
|
||||
Returns true if list is sorted in either ascending or descending order.
|
||||
@require @is_sortable(list) : "The list must be indexable and support .len or .len()"
|
||||
@require @is_valid_cmp_fn(cmp, list, ctx) : "Expected a comparison function which compares values"
|
||||
Returns true if list is sorted in either ascending or descending order.
|
||||
|
||||
@require @is_any_sortable(list) : "The list must be indexable and support .len or .len()"
|
||||
@require @is_any_valid_cmp_fn(cmp, list, ctx) : "Expected a comparison function which compares values"
|
||||
@require @is_valid_context(cmp, ctx) : "Expected a valid context"
|
||||
*>
|
||||
macro bool is_sorted(list, cmp = EMPTY_MACRO_SLOT, ctx = EMPTY_MACRO_SLOT) @builtin
|
||||
{
|
||||
$if ($kindof(list) != POINTER):
|
||||
var $Type = $typeof(list);
|
||||
usz len = lengthof(list);
|
||||
if (len <= 1) return true;
|
||||
@@ -16,6 +18,33 @@ macro bool is_sorted(list, cmp = EMPTY_MACRO_SLOT, ctx = EMPTY_MACRO_SLOT) @buil
|
||||
usz i;
|
||||
int sort_order;
|
||||
|
||||
// determine sort order (ascending or descending)
|
||||
for (i = start; i < end && sort_order == 0; i++)
|
||||
{
|
||||
sort_order = @sort_cmp_slice(list, i, cmp, ctx);
|
||||
}
|
||||
|
||||
// no sort order found, all elements are the same, consider list sorted
|
||||
if (sort_order == 0) return true;
|
||||
|
||||
// compare adjacent elements to the sort order
|
||||
for (; i < end; i++)
|
||||
{
|
||||
if (sort_order * @sort_cmp_slice(list, i, cmp, ctx) < 0) return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
return check_sort(list, 0, len - 1, cmp, ctx);
|
||||
$else
|
||||
var $Type = $typeof(*list);
|
||||
usz len = lengthof(*list);
|
||||
if (len <= 1) return true;
|
||||
var check_sort = fn bool($Type* list, usz start, usz end, $typeof(cmp) cmp, $typeof(ctx) ctx)
|
||||
{
|
||||
usz i;
|
||||
int sort_order;
|
||||
|
||||
// determine sort order (ascending or descending)
|
||||
for (i = start; i < end && sort_order == 0; i++)
|
||||
{
|
||||
@@ -33,9 +62,33 @@ macro bool is_sorted(list, cmp = EMPTY_MACRO_SLOT, ctx = EMPTY_MACRO_SLOT) @buil
|
||||
return true;
|
||||
};
|
||||
return check_sort(list, 0, len - 1, cmp, ctx);
|
||||
$endif
|
||||
}
|
||||
|
||||
macro int @sort_cmp(list, pos, cmp, ctx) @local
|
||||
{
|
||||
var $has_cmp = @is_valid_macro_slot(cmp);
|
||||
var $has_context = @is_valid_macro_slot(ctx);
|
||||
var $cmp_by_value = $has_cmp &&& $defined($typefrom($typeof(cmp).paramsof[0].type) v = (*list)[0]);
|
||||
|
||||
var a = (*list)[pos];
|
||||
var b = (*list)[pos+1];
|
||||
|
||||
$switch:
|
||||
$case $cmp_by_value && $has_context:
|
||||
return cmp(a, b);
|
||||
$case $cmp_by_value:
|
||||
return cmp(a, b);
|
||||
$case $has_cmp && $has_context:
|
||||
return cmp(&a, &b, ctx);
|
||||
$case $has_cmp:
|
||||
return cmp(&a, &b);
|
||||
$default:
|
||||
return compare_to(a,b);
|
||||
$endswitch
|
||||
}
|
||||
|
||||
macro int @sort_cmp_slice(list, pos, cmp, ctx) @local
|
||||
{
|
||||
var $has_cmp = @is_valid_macro_slot(cmp);
|
||||
var $has_context = @is_valid_macro_slot(ctx);
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
rev,
|
||||
debug ? false,
|
||||
checks ? false,
|
||||
}: let
|
||||
}: let
|
||||
inherit (builtins) readFile elemAt;
|
||||
# inherit (lib.sources) cleanSourceWith cleanSource;
|
||||
inherit (lib.lists) findFirst;
|
||||
inherit (lib.asserts) assertMsg;
|
||||
inherit (lib.strings) hasInfix splitString removeSuffix removePrefix optionalString;
|
||||
in llvmPackages.stdenv.mkDerivation (_:
|
||||
in llvmPackages.stdenv.mkDerivation (_:
|
||||
{
|
||||
pname = "c3c${optionalString debug "-debug"}";
|
||||
|
||||
@@ -33,7 +33,7 @@ in llvmPackages.stdenv.mkDerivation (_:
|
||||
# Here we substitute GIT_HASH which is not set for cmake in nix builds.
|
||||
# Similar situation is with __DATE__ and __TIME__ macros, which are
|
||||
# set to "Jan 01 1980 00:00:00" by default.
|
||||
patchPhase = ''
|
||||
postPatch = ''
|
||||
substituteInPlace git_hash.cmake --replace-fail "\''${GIT_HASH}" "${rev}"
|
||||
|
||||
local FILE_NAMES="$(find src -type f)"
|
||||
@@ -49,8 +49,8 @@ in llvmPackages.stdenv.mkDerivation (_:
|
||||
"-DLLVM_CRT_LIBRARY_DIR=${llvmPackages.compiler-rt}/lib/darwin"
|
||||
];
|
||||
|
||||
nativeBuildInputs = [
|
||||
cmake
|
||||
nativeBuildInputs = [
|
||||
cmake
|
||||
llvmPackages.llvm
|
||||
llvmPackages.lld
|
||||
llvmPackages.compiler-rt
|
||||
@@ -71,6 +71,7 @@ in llvmPackages.stdenv.mkDerivation (_:
|
||||
# In check phase we preserve BUILD directory as
|
||||
# we need to return to it before install phase
|
||||
checkPhase = ''
|
||||
runHook preCheck
|
||||
local BUILD_DIR=$(pwd)
|
||||
|
||||
cd ../resources/testproject
|
||||
@@ -80,6 +81,7 @@ in llvmPackages.stdenv.mkDerivation (_:
|
||||
../build/c3c compile-run -O1 src/test_suite_runner.c3 -- ../build/c3c ./test_suite
|
||||
|
||||
cd $BUILD_DIR
|
||||
runHook postCheck
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
|
||||
108
releasenotes.md
108
releasenotes.md
@@ -1,5 +1,113 @@
|
||||
# C3C Release Notes
|
||||
|
||||
## 0.7.8 Change list
|
||||
|
||||
### Changes / improvements
|
||||
- Improve multiline string parser inside compiler #2552.
|
||||
- Missing imports allowed if module `@if` evaluates to false #2251.
|
||||
- Add default exception handler to Win32 #2557.
|
||||
- Accept `"$schema"` as key in `project.json` #2554.
|
||||
- Function referencing in `@return?` for simplified fault declarations. Check `@return?` eagerly #2340.
|
||||
- Enums now work with `membersof` to return the associated values. #2571
|
||||
- Deprecated `SomeEnum.associated` in favour of `SomeEnum.membersof`
|
||||
- Refactored `@simd` implementation.
|
||||
- Improve error message for `Foo{}` when `Foo` is not a generic type #2574.
|
||||
- Support `@param` directives for `...` parameters. #2578
|
||||
- Allow splatting of structs. #2555
|
||||
- Deprecate `--test-nocapture` in favour of `--test-show-output` #2588.
|
||||
- Xtensa target no longer enabled by default on LLVM 22, Compile with `-DXTENSA_ENABLE` to enable it instead
|
||||
- Add `float[<3>] x = { .xy = 1.2, .z = 3.3 }` swizzle initialization for vectors. #2599
|
||||
- Support `int $foo...` arguments. #2601
|
||||
- Add musl support with `--linux-libc=musl`.
|
||||
|
||||
### Fixes
|
||||
- `Foo.is_eq` would return false if the type was a `typedef` and had an overload, but the underlying type was not comparable.
|
||||
- Remove division-by-zero checks for floating point in safe mode #2556.
|
||||
- Fix division-by-zero checks on `a /= 0` and `b /= 0f` #2558.
|
||||
- Fix fmod `a %= 0f`.
|
||||
- Regression vector ABI: initializing a struct containing a NPOT vector with a constant value would crash LLVM. #2559
|
||||
- Error message with hashmap shows "mangled" name instead of original #2562.
|
||||
- Passing a compile time type implicitly converted to a typeid would crash instead of producing an error. #2568
|
||||
- Compiler assert with const enum based on vector #2566
|
||||
- Fix to `Path` handling `c:\foo` and `\home` parent. #2569
|
||||
- Fix appending to `c:\` or `\` #2569.
|
||||
- When encountering a foreach over a `ZString*` it would not properly emit a compilation error, but hit an assert #2573.
|
||||
- Casting a distinct type based on a pointer to an `any` would accidentally be permitted. #2575
|
||||
- `overflow_*` vector ops now correctly return a bool vector.
|
||||
- Regression vector ABI: npot vectors would load incorrectly from pointers and other things. #2576
|
||||
- Using `defer catch` with a (void), would cause an assertion. #2580
|
||||
- Fix decl attribute in the wrong place causing an assertion. #2581
|
||||
- Passing a single value to `@wasm` would ignore the renaming.
|
||||
- `*(int*)1` incorrectly yielded an assert in LLVM IR lowering #2584.
|
||||
- Fix issue when tests encounter a segmentation fault or similar.
|
||||
- With project.json, when overriding with an empty list the base settings would still be used. #2583
|
||||
- Add sigsegv stacktrace in test and regular errors for Darwin Arm64. #1105
|
||||
- Incorrect error message when using generic type that isn't imported #2589
|
||||
- `String.to_integer` does not correctly return in some cases where it should #2590.
|
||||
- Resolving a missing property on a const enum with inline, reached an assert #2597.
|
||||
- Unexpected maybe-deref subscript error with out parameter #2600.
|
||||
- Bug on rethrow in return with defer #2603.
|
||||
- Fix bug when converting from vector to distinct type of wider vector. #2604
|
||||
- `$defined(hashmap.init(mem))` causes compiler segfault #2611.
|
||||
- Reference macro parameters syntax does not error in certain cases. #2612
|
||||
- @param name parsing too lenient #2614.
|
||||
|
||||
### Stdlib changes
|
||||
- Add `CGFloat` `CGPoint` `CGSize` `CGRect` types to core_foundation (macOS).
|
||||
- Add `NSStatusItem` const enum to ns module (macOS).
|
||||
- Add `NSWindowCollectionBehavior` `NSWindowLevel` `NSWindowTabbingMode` to ns module (macOS).
|
||||
- Add `ns::eventmask_from_type` function to objc (macOS).
|
||||
- Deprecate objc enums in favour of const inline enums backed by NS numerical types, and with the NS prefix, to better align with the objc api (macOS).
|
||||
- Deprecate `event_type_from` function in favour of using NSEvent directly, to better align with the objc api (macOS).
|
||||
- Add unit tests for objc and core_foundation (macOS).
|
||||
- Make printing typeids give some helpful typeid data.
|
||||
- Add `NSApplicationTerminateReply` to ns module (macOS).
|
||||
- Add `registerClassPair` function to objc module (macOS).
|
||||
- Somewhat faster BigInt output.
|
||||
- Cache printf output.
|
||||
|
||||
## 0.7.7 Change list
|
||||
|
||||
### Changes / improvements
|
||||
- Error when using $vaarg/$vacount/$vasplat and similar in a macro without vaargs #2510.
|
||||
- Add splat defaults for designated initialization #2441.
|
||||
- Add new builtins `$$str_snakecase` `$$str_replace` and `$$str_pascalcase`.
|
||||
- `"build-dir"` option now available for `project.json`, added to project. #2323
|
||||
- Allow `..` ranges to use "a..a-1" in order to express zero length.
|
||||
- Disallow aliasing of `@local` symbols with a higher visibility in the alias.
|
||||
- Add `--max-macro-iterations` to set macro iteration limit.
|
||||
- Improved generic inference in initializers #2541.
|
||||
- "Maybe-deref" subscripting `foo.[i] += 1` #2540.
|
||||
- ABI change for vectors: store and pass them as arrays #2542.
|
||||
- Add @simd and @align attributes to typedef #2543.
|
||||
- Rename `@extern` to `@cname`, deprecating the old name #2493.
|
||||
- Allow `(Foo)0` bitstruct casts even if type sizes do not match.
|
||||
- The option `--riscvfloat` renamed `--riscv-abi`.
|
||||
- Add initial `--cpu-flags` allowing fine grained control over CPU features.
|
||||
- Add `--riscv-cpu` settings for RISC-V processors #2549.
|
||||
|
||||
### Fixes
|
||||
- Bug in `io::write_using_write_byte`.
|
||||
- Bitstruct value cannot be used to index a const array in compile time. #2512
|
||||
- Compiler fails to stop error print in recursive macro, and also prints unnecessary "inline at" #2513.
|
||||
- Bitstruct truncated constant error escapes `$defined` #2515.
|
||||
- Compiler segfault when accessing member of number cast to bitstruct #2516.
|
||||
- Compiler assert when getting a member of a `bitstruct : char @bigendian` #2517.
|
||||
- Add ??? and +++= to list-precedence.
|
||||
- Fix issues with linking when using symbol aliases. #2519
|
||||
- Splatting optional compile-time macro parameter from inside lambda expression does not work #2532.
|
||||
- Compiler segfault when getting a nonexistant member from an unnamed struct #2533.
|
||||
- Correctly mention aliased type when method is not implemented #2534.
|
||||
- Regression: Not printing backtrace when tests fail for MacOS #2536.
|
||||
- Name property would be used even under `c3c test` #2587.
|
||||
|
||||
### Stdlib changes
|
||||
- Sorting functions correctly took slices by value, but also other types by value. Now, only slices are accepted by value, other containers are always by ref.
|
||||
- Added `@str_snakecase`, `@str_replace` and `@str_pascalcase` builtin compile time macros based on the `$$` builtins.
|
||||
- Add TcpSocketPair to create a bidirectional local socket pair.
|
||||
- Add `extern fn CInt socketpair(AIFamily domain, AISockType type, CInt protocol, NativeSocket[2]* sv)` binding to posix.
|
||||
- Add `extern fn getsockname(NativeSocket socket, SockAddrPtr address, Socklen_t* address_len)` binding to win32.
|
||||
|
||||
## 0.7.6 Change list
|
||||
|
||||
### Changes / improvements
|
||||
|
||||
@@ -6,10 +6,12 @@ hello.a: $(SRCS_C3)
|
||||
$(C3C_PATH)c3c -g --use-stdlib=no --no-entry --target elf-riscv32 static-lib $(SRCS_C3)
|
||||
|
||||
start.o: start.s
|
||||
riscv64-unknown-elf-as -g -march=rv32i -mabi=ilp32 -misa-spec=20191213 -o start.o start.s
|
||||
riscv64-unknown-elf-as -g -march=rv32i -mabi=ilp32 -misa-spec=20191213 -o start.o start.s \
|
||||
|| riscv-none-elf-as -g -march=rv32i -mabi=ilp32 -misa-spec=20191213 -o start.o start.s
|
||||
|
||||
hello.elf: hello.a start.o baremetal.ld
|
||||
riscv64-unknown-elf-ld -T baremetal.ld -m elf32lriscv -o hello.elf hello.a start.o
|
||||
riscv64-unknown-elf-ld -T baremetal.ld -m elf32lriscv -o hello.elf hello.a start.o \
|
||||
|| riscv-none-elf-ld -T baremetal.ld -m elf32lriscv -o hello.elf hello.a start.o
|
||||
|
||||
run: hello.elf
|
||||
qemu-system-riscv32 -nographic -serial mon:stdio -machine virt -semihosting -bios hello.elf
|
||||
|
||||
@@ -1,22 +1,26 @@
|
||||
fn void print(String msg)
|
||||
{
|
||||
$$syscall(1, 1, (uptr)msg.ptr, msg.len); // __NR_write, STDOUT
|
||||
}
|
||||
|
||||
fn void printn(String msg)
|
||||
{
|
||||
print(msg);
|
||||
print("\n");
|
||||
}
|
||||
|
||||
fn void exit(int exit_code)
|
||||
{
|
||||
$$syscall(60, exit_code); // __NR_exit
|
||||
}
|
||||
|
||||
fn int main()
|
||||
{
|
||||
String msg = "Hello, C3 World!\n";
|
||||
$$syscall(1, 1, (uptr)msg.ptr, msg.len); // __NR_write, STDOUT
|
||||
return 0;
|
||||
printn("Hello, C3 World!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn void _start() @export("_start")
|
||||
{
|
||||
int ret = main();
|
||||
$$syscall(60, ret); // __NR_exit
|
||||
}
|
||||
|
||||
module std::core::builtin;
|
||||
|
||||
alias PanicFn = fn void(String message, String file, String function, uint line);
|
||||
|
||||
PanicFn panic = &default_panic;
|
||||
|
||||
fn void default_panic(String message, String file, String function, uint line)
|
||||
{
|
||||
exit(main());
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
"version": "0.1.0",
|
||||
// Sources compiled for all targets.
|
||||
"sources": [ "./**" ],
|
||||
// Test sources compiled for all targets.
|
||||
"test-sources": [ "test/**" ],
|
||||
// C sources if the project also compiles C sources
|
||||
// relative to the project file.
|
||||
// "c-sources": [ "csource/**" ],
|
||||
@@ -24,31 +26,21 @@
|
||||
// Targets.
|
||||
"targets": {
|
||||
"hello_world": {
|
||||
// Executable or library.
|
||||
"type": "executable",
|
||||
"debug-info": "none",
|
||||
"link-libc": false,
|
||||
"opt": "O0",
|
||||
"safe": false,
|
||||
"linker": "builtin",
|
||||
"use-stdlib": false,
|
||||
// Additional libraries, sources
|
||||
// and overrides of global settings here.
|
||||
},
|
||||
},
|
||||
// Global settings.
|
||||
// C compiler if the project also compiles C sources
|
||||
// defaults to 'cc'.
|
||||
"cc": "cc",
|
||||
// CPU name, used for optimizations in the LLVM backend.
|
||||
"cpu": "generic",
|
||||
// Debug information, may be "none", "full" and "line-tables".
|
||||
"debug-info": "full",
|
||||
// FP math behaviour: "strict", "relaxed", "fast".
|
||||
"fp-math": "strict",
|
||||
// Link libc other default libraries.
|
||||
"link-libc": true,
|
||||
"link-libc": false,
|
||||
// Memory environment: "normal", "small", "tiny", "none".
|
||||
"memory-env": "normal",
|
||||
"memory-env": "small",
|
||||
// Optimization: "O0", "O1", "O2", "O3", "O4", "O5", "Os", "Oz".
|
||||
"opt": "O0",
|
||||
"opt": "Os",
|
||||
// Code optimization level: "none", "less", "more", "max".
|
||||
"optlevel": "none",
|
||||
// Code size optimization: "none", "small", "tiny".
|
||||
@@ -58,7 +50,7 @@
|
||||
// Trap on signed and unsigned integer wrapping for testing.
|
||||
"trap-on-wrap": false,
|
||||
// Turn safety (contracts, runtime bounds checking, null pointer checks etc).
|
||||
"safe": true,
|
||||
"safe": false,
|
||||
// Compile all modules together, enables more inlining.
|
||||
"single-module": true,
|
||||
// Use / don't use soft float, value is otherwise target default.
|
||||
@@ -69,11 +61,7 @@
|
||||
// of symbols that can be used. Should usually not be changed.
|
||||
"symtab": 1048576,
|
||||
// Select linker.
|
||||
"linker": "cc",
|
||||
"linker": "builtin",
|
||||
// Include the standard library.
|
||||
"use-stdlib": true,
|
||||
// Set general level of x64 cpu: "baseline", "ssse3", "sse4", "avx1", "avx2-v1", "avx2-v2", "avx512", "native".
|
||||
"x86cpu": "native",
|
||||
// Set max type of vector use: "none", "mmx", "sse", "avx", "avx512", "native".
|
||||
"x86vec": "sse",
|
||||
"use-stdlib": false,
|
||||
}
|
||||
@@ -23,14 +23,14 @@ enum Primitive : int (int value)
|
||||
POLYGON = 9,
|
||||
}
|
||||
|
||||
extern fn void clear(BitField mask) @extern("glClear") @public;
|
||||
extern fn void clear(BitField mask) @cname("glClear") @public;
|
||||
|
||||
extern fn void begin(BitField mask) @extern("glBegin") @public;
|
||||
extern fn void begin(BitField mask) @cname("glBegin") @public;
|
||||
|
||||
extern fn void end() @extern("glEnd") @public;
|
||||
extern fn void end() @cname("glEnd") @public;
|
||||
|
||||
extern fn void flush() @extern("glFlush") @public;
|
||||
extern fn void flush() @cname("glFlush") @public;
|
||||
|
||||
extern fn void color3f(float r, float g, float b) @extern("glColor3f") @public;
|
||||
extern fn void color3f(float r, float g, float b) @cname("glColor3f") @public;
|
||||
|
||||
extern fn void vertex3f(float x, float y, float z) @extern("glVertex3f") @public;
|
||||
extern fn void vertex3f(float x, float y, float z) @cname("glVertex3f") @public;
|
||||
@@ -31,21 +31,21 @@ fn void Window.makeContextCurrent(self) @public
|
||||
return _glfwMakeContextCurrent((_Window*)self);
|
||||
}
|
||||
|
||||
extern fn void initialize() @extern("glfwInit") @public;
|
||||
extern fn void initialize() @cname("glfwInit") @public;
|
||||
|
||||
extern fn void terminate() @extern("glfwTerminate") @public;
|
||||
extern fn void terminate() @cname("glfwTerminate") @public;
|
||||
|
||||
extern fn void pollEvents() @extern("glfwPollEvents") @public;
|
||||
extern fn void pollEvents() @cname("glfwPollEvents") @public;
|
||||
|
||||
typedef _Window @private = void;
|
||||
typedef _Monitor @private = void;
|
||||
|
||||
extern fn _Window* _glfwCreateWindow(int width, int height, char* title, _Monitor* monitor, _Window* share) @extern("glfwCreateWindow") @private;
|
||||
extern fn _Window* _glfwCreateWindow(int width, int height, char* title, _Monitor* monitor, _Window* share) @cname("glfwCreateWindow") @private;
|
||||
|
||||
extern fn bool _glfwWindowShouldClose(_Window* window) @extern("glfwWindowShouldClose") @private;
|
||||
extern fn bool _glfwWindowShouldClose(_Window* window) @cname("glfwWindowShouldClose") @private;
|
||||
|
||||
extern fn void _glfwDestroyWindow(_Window* window) @extern("glfwDestroyWindow") @private;
|
||||
extern fn void _glfwDestroyWindow(_Window* window) @cname("glfwDestroyWindow") @private;
|
||||
|
||||
extern fn void _glfwSwapBuffers(_Window* window) @extern("glfwSwapBuffers") @private;
|
||||
extern fn void _glfwSwapBuffers(_Window* window) @cname("glfwSwapBuffers") @private;
|
||||
|
||||
extern fn void _glfwMakeContextCurrent(_Window* window) @extern("glfwMakeContextCurrent") @private;
|
||||
extern fn void _glfwMakeContextCurrent(_Window* window) @cname("glfwMakeContextCurrent") @private;
|
||||
BIN
resources/examples/raylib/guy.iqm
Normal file
BIN
resources/examples/raylib/guy.iqm
Normal file
Binary file not shown.
BIN
resources/examples/raylib/guyanim.iqm
Normal file
BIN
resources/examples/raylib/guyanim.iqm
Normal file
Binary file not shown.
BIN
resources/examples/raylib/guytex.png
Normal file
BIN
resources/examples/raylib/guytex.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 295 KiB |
BIN
resources/examples/raylib/raybunny.png
Normal file
BIN
resources/examples/raylib/raybunny.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 466 B |
292
resources/examples/raylib/raylib_2d_camera_platformer.c3
Normal file
292
resources/examples/raylib/raylib_2d_camera_platformer.c3
Normal file
@@ -0,0 +1,292 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - 2d camera platformer
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 2.5, last time updated with raylib 3.0
|
||||
*
|
||||
* Example contributed by arvyy (@arvyy) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2019-2025 arvyy (@arvyy)
|
||||
* converted to C3 by Christoffer Lerno
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
module raylib_camera_platformer;
|
||||
import raylib55;
|
||||
|
||||
const G = 400;
|
||||
const float PLAYER_JUMP_SPD = 350;
|
||||
const float PLAYER_HOR_SPD = 200;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
struct Player
|
||||
{
|
||||
RLVector2 position;
|
||||
float speed;
|
||||
bool can_jump;
|
||||
}
|
||||
|
||||
struct EnvItem
|
||||
{
|
||||
RLRectangle rect;
|
||||
int blocking;
|
||||
RLColor color;
|
||||
}
|
||||
|
||||
|
||||
alias CameraUpdateFn = fn void(RLCamera2D* camera, Player* player, EnvItem[] env_items, float delta, int width, int height);
|
||||
|
||||
enum CameraUpdateType : (ZString text, CameraUpdateFn func)
|
||||
{
|
||||
CENTER = { "Follow player center", &update_camera_center },
|
||||
CENTER_INSIDE_MAP = { "Follow player center, but clamp to map edges", &update_camera_center_inside_map },
|
||||
CENTER_SMOOTH_FOLLOW = { "Follow player center; smoothed", &update_camera_center_smooth_follow },
|
||||
EVEN_OUT_ON_LANDING = { "Follow player center horizontally; update player center vertically after landing", &update_camera_even_out_on_landing },
|
||||
PLAYER_BOUNDS_PUSH = { "Player push camera on getting too close to screen edge", &update_camera_player_bounds_push }
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
fn int main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int SCREEN_WIDTH = 800;
|
||||
const int SCREEN_HEIGHT = 450;
|
||||
|
||||
rl::init_window(SCREEN_WIDTH, SCREEN_HEIGHT, "raylib [core] example - 2d camera platformer");
|
||||
|
||||
Player player = {
|
||||
.position = { 400, 280 },
|
||||
.speed = 0,
|
||||
.can_jump = false
|
||||
};
|
||||
EnvItem[*] env_items = {
|
||||
{{ 0, 0, 1000, 400 }, 0, rl::LIGHTGRAY },
|
||||
{{ 0, 400, 1000, 200 }, 1, rl::GRAY },
|
||||
{{ 300, 200, 400, 10 }, 1, rl::GRAY },
|
||||
{{ 250, 300, 100, 10 }, 1, rl::GRAY },
|
||||
{{ 650, 300, 100, 10 }, 1, rl::GRAY }
|
||||
};
|
||||
|
||||
RLCamera2D camera = {
|
||||
.target = player.position,
|
||||
.offset = { SCREEN_WIDTH / 2.0f, SCREEN_HEIGHT / 2.0f },
|
||||
.rotation = 0.0f,
|
||||
.zoom = 1.0f
|
||||
};
|
||||
|
||||
|
||||
CameraUpdateType camera_option = CENTER;
|
||||
|
||||
rl::set_target_fps(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl::window_should_close())
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
float delta_time = rl::get_frame_time();
|
||||
|
||||
update_player(&player, &env_items, delta_time);
|
||||
camera.zoom += ((float)rl::get_mouse_wheel_move() * 0.05f);
|
||||
|
||||
switch
|
||||
{
|
||||
case camera.zoom > 3.0f: camera.zoom = 3.0f;
|
||||
case camera.zoom < 0.25f: camera.zoom = 0.25f;
|
||||
}
|
||||
|
||||
if (rl::is_key_pressed(R))
|
||||
{
|
||||
camera.zoom = 1.0f;
|
||||
player.position = { 400, 280 };
|
||||
}
|
||||
|
||||
if (rl::is_key_pressed(C)) camera_option = CameraUpdateType.from_ordinal(((int)camera_option + 1) % (int)CameraUpdateType.len);
|
||||
|
||||
// Call update camera function by its pointer
|
||||
camera_option.func(&camera, &player, &env_items, delta_time, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl::@drawing()
|
||||
{
|
||||
rl::clear_background(rl::LIGHTGRAY);
|
||||
rl::@mode2d(camera)
|
||||
{
|
||||
foreach (item : env_items) rl::draw_rectangle_rec(item.rect, item.color);
|
||||
RLRectangle player_rect = { player.position.x - 20, player.position.y - 40, 40.0f, 40.0f };
|
||||
rl::draw_rectangle_rec(player_rect, rl::RED);
|
||||
rl::draw_circle_v(player.position, 5.0f, rl::GOLD);
|
||||
};
|
||||
rl::draw_text("Controls:", 20, 20, 10, rl::BLACK);
|
||||
rl::draw_text("- Right/Left to move", 40, 40, 10, rl::DARKGRAY);
|
||||
rl::draw_text("- Space to jump", 40, 60, 10, rl::DARKGRAY);
|
||||
rl::draw_text("- Mouse Wheel to Zoom in-out, R to reset zoom", 40, 80, 10, rl::DARKGRAY);
|
||||
rl::draw_text("- C to change camera mode", 40, 100, 10, rl::DARKGRAY);
|
||||
rl::draw_text("Current camera mode:", 20, 120, 10, rl::BLACK);
|
||||
rl::draw_text(camera_option.text, 40, 140, 10, rl::DARKGRAY);
|
||||
};
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
rl::close_window(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
fn void update_player(Player* player, EnvItem[] env_items, float delta)
|
||||
{
|
||||
if (rl::is_key_down(LEFT)) player.position.x -= PLAYER_HOR_SPD * delta;
|
||||
if (rl::is_key_down(RIGHT)) player.position.x += PLAYER_HOR_SPD * delta;
|
||||
if (rl::is_key_down(SPACE) && player.can_jump)
|
||||
{
|
||||
player.speed = -PLAYER_JUMP_SPD;
|
||||
player.can_jump = false;
|
||||
}
|
||||
|
||||
bool hit_obstacle = false;
|
||||
foreach (item : env_items)
|
||||
{
|
||||
RLVector2* p = &player.position;
|
||||
if (item.blocking
|
||||
&& item.rect.x <= p.x
|
||||
&& item.rect.x + item.rect.width >= p.x
|
||||
&& item.rect.y >= p.y
|
||||
&& item.rect.y <= p.y + player.speed * delta)
|
||||
{
|
||||
hit_obstacle = true;
|
||||
player.speed = 0.0f;
|
||||
p.y = item.rect.y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hit_obstacle)
|
||||
{
|
||||
player.can_jump = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
player.position.y += player.speed * delta;
|
||||
player.speed += G * delta;
|
||||
player.can_jump = false;
|
||||
}
|
||||
}
|
||||
|
||||
fn void update_camera_center(RLCamera2D* camera, Player* player, EnvItem[] env_items, float delta, int width, int height)
|
||||
{
|
||||
camera.offset = { width / 2.0f, height / 2.0f };
|
||||
camera.target = player.position;
|
||||
}
|
||||
|
||||
fn void update_camera_center_inside_map(RLCamera2D* camera, Player* player, EnvItem[] env_items, float delta, int width, int height)
|
||||
{
|
||||
camera.target = player.position;
|
||||
camera.offset = { width / 2.0f, height / 2.0f };
|
||||
float min_x = 1000;
|
||||
float min_y = 1000;
|
||||
float max_x = -1000;
|
||||
float max_y = -1000;
|
||||
|
||||
foreach (item : env_items)
|
||||
{
|
||||
min_x = min(item.rect.x, min_x);
|
||||
max_x = max(item.rect.x + item.rect.width, max_x);
|
||||
min_y = min(item.rect.y, min_y);
|
||||
max_y = max(item.rect.y + item.rect.height, max_y);
|
||||
}
|
||||
|
||||
RLVector2 max = rl::get_world_to_screen2d({ max_x, max_y }, *camera);
|
||||
RLVector2 min = rl::get_world_to_screen2d({ min_x, min_y }, *camera);
|
||||
|
||||
if (max.x < width) camera.offset.x = width - (max.x - width / 2.0f);
|
||||
if (max.y < height) camera.offset.y = height - (max.y - height / 2.0f);
|
||||
if (min.x > 0) camera.offset.x = width / 2.0f - min.x;
|
||||
if (min.y > 0) camera.offset.y = height / 2.0f - min.y;
|
||||
}
|
||||
|
||||
fn void update_camera_center_smooth_follow(RLCamera2D* camera, Player* player, EnvItem[] env_items, float delta, int width, int height)
|
||||
{
|
||||
const float MIN_SPEED = 30;
|
||||
const float MIN_EFFECT_LENGTH = 10;
|
||||
const float FRACTION_SPEED = 0.8f;
|
||||
|
||||
camera.offset = { width / 2.0f, height / 2.0f };
|
||||
float length = player.position.distance(camera.target);
|
||||
|
||||
if (length > MIN_EFFECT_LENGTH)
|
||||
{
|
||||
float speed = max(FRACTION_SPEED * length, MIN_SPEED);
|
||||
camera.target += (player.position - camera.target) * speed * delta / length;
|
||||
}
|
||||
}
|
||||
|
||||
fn void update_camera_even_out_on_landing(RLCamera2D* camera, Player* player, EnvItem[] env_items, float delta, int width, int height)
|
||||
{
|
||||
const float EVEN_OUT_SPEED = 700;
|
||||
static bool evening_out = false;
|
||||
static float even_out_target;
|
||||
|
||||
camera.offset = { width / 2.0f, height / 2.0f };
|
||||
camera.target.x = player.position.x;
|
||||
|
||||
if (evening_out)
|
||||
{
|
||||
if (even_out_target > camera.target.y)
|
||||
{
|
||||
camera.target.y += EVEN_OUT_SPEED * delta;
|
||||
|
||||
if (camera.target.y > even_out_target)
|
||||
{
|
||||
camera.target.y = even_out_target;
|
||||
evening_out = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
camera.target.y -= EVEN_OUT_SPEED * delta;
|
||||
|
||||
if (camera.target.y < even_out_target)
|
||||
{
|
||||
camera.target.y = even_out_target;
|
||||
evening_out = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (player.can_jump && player.speed == 0 && player.position.y != camera.target.y)
|
||||
{
|
||||
evening_out = true;
|
||||
even_out_target = player.position.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn void update_camera_player_bounds_push(RLCamera2D* camera, Player* player, EnvItem[] env_items, float delta, int width, int height)
|
||||
{
|
||||
const RLVector2 BBOX = { 0.2f, 0.2f };
|
||||
|
||||
RLVector2 bboxWorldMin = rl::get_screen_to_world2d({ (1 - BBOX.x) * 0.5f * width, (1 - BBOX.y) * 0.5f*height }, *camera);
|
||||
RLVector2 bboxWorldMax = rl::get_screen_to_world2d({ (1 + BBOX.x) * 0.5f * width, (1 + BBOX.y) * 0.5f*height }, *camera);
|
||||
camera.offset = { (1 - BBOX.x) * 0.5f * width, (1 - BBOX.y) * 0.5f * height };
|
||||
|
||||
if (player.position.x < bboxWorldMin.x) camera.target.x = player.position.x;
|
||||
if (player.position.y < bboxWorldMin.y) camera.target.y = player.position.y;
|
||||
if (player.position.x > bboxWorldMax.x) camera.target.x = bboxWorldMin.x + (player.position.x - bboxWorldMax.x);
|
||||
if (player.position.y > bboxWorldMax.y) camera.target.y = bboxWorldMin.y + (player.position.y - bboxWorldMax.y);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user