Compare commits

..

22 Commits

Author SHA1 Message Date
David Mak 2244f347c3 flake: Remove standalone execution of test cases
This is now executed as part of cargo test.
2023-12-11 15:17:26 +08:00
David Mak ad183ae21c standalone: Add cargo test cases for demos 2023-12-11 15:17:26 +08:00
David Mak f97ce5aacb core: Emit dead code warning via stderr 2023-12-11 15:17:26 +08:00
Sebastien Bourdeauducq 68556da5fd update ARTIQ version used for PGO profiling 2023-12-11 09:37:03 +08:00
David Mak 983f080ea7 artiq: Implement handling for const generic variables 2023-12-08 18:02:14 +08:00
David Mak 031e660f18 core: Initial implementation for const generics 2023-12-08 18:02:11 +08:00
David Mak b6dfcfcc38 core: Move some SymbolValue functions to symbol_resolver.rs 2023-12-08 18:00:51 +08:00
David Mak c93ad152d7 core: Codegen for ellipsis expression as NotImplemented
A lot of refactoring was performed, specifically with relaxing
expression codegen to return Option in case where ellipsis are used
within a subexpression.
2023-12-08 18:00:51 +08:00
David Mak 68b97347b1 core: Infer builtins name list using builtin declaration list 2023-12-08 17:29:34 +08:00
David Mak 875d534de4 ast: Use `{filename}:{row}:{col}` for location output 2023-12-08 15:48:54 +08:00
Sebastien Bourdeauducq adadf56e2b nac3standalone: generate PIC 2023-12-04 19:09:50 +08:00
Sebastien Bourdeauducq 9f610745b7 cargo: update dependencies 2023-12-04 18:51:06 +08:00
Sebastien Bourdeauducq 98199768e3 demo: fix 64-bit format strings 2023-12-04 18:51:06 +08:00
Sebastien Bourdeauducq bfa9ceaae3 switch to new nixpkgs release 2023-12-03 10:31:05 +08:00
Sebastien Bourdeauducq 120f8da5c7 fix compilation warnings 2023-11-26 09:09:24 +08:00
Sebastien Bourdeauducq cee62aa6c5 pin down LLVM used for IRRT 2023-11-25 20:15:29 +08:00
Sebastien Bourdeauducq fcda360ad6 flake: update dependencies 2023-11-24 18:11:25 +08:00
Sebastien Bourdeauducq 87c20ada48 windows: switch to CLANG64 MSYS2
For compatibility with MSVC (Anaconda and others).
2023-11-24 18:10:00 +08:00
Sebastien Bourdeauducq 38e968cff6 gitignore: fix msys2 path 2023-11-24 17:18:17 +08:00
David Mak 5c5620692f core: Add np_{round,floor,ceil}
These functions are NumPy variants of round/floor/ceil, which returns
floats instead of ints.
2023-11-23 13:45:07 +08:00
David Mak 0af1e37e99 core: Prefix all NumPy/SciPy functions with np_/sp_spec 2023-11-23 13:35:23 +08:00
David Mak 854e33ed48 meta: Update cargo dependencies 2023-11-23 13:31:24 +08:00
34 changed files with 1613 additions and 916 deletions

2
.gitignore vendored
View File

@ -1,3 +1,3 @@
__pycache__ __pycache__
/target /target
windows/msys2 nix/windows/msys2

124
Cargo.lock generated
View File

@ -148,9 +148,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.4.7" version = "4.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" checksum = "41fffed7514f420abec6d183b1d3acfd9099c79c3a10a06ade4f8203f1411272"
dependencies = [ dependencies = [
"clap_builder", "clap_builder",
"clap_derive", "clap_derive",
@ -158,9 +158,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_builder" name = "clap_builder"
version = "4.4.7" version = "4.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" checksum = "63361bae7eef3771745f02d8d892bec2fee5f6e34af316ba556e7f97a7069ff1"
dependencies = [ dependencies = [
"anstream", "anstream",
"anstyle", "anstyle",
@ -333,12 +333,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]] [[package]]
name = "errno" name = "errno"
version = "0.3.6" version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c18ee0ed65a5f1f81cac6b1d213b69c35fa47d4252ad41f1486dbd8226fe36e" checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
dependencies = [ dependencies = [
"libc", "libc",
"windows-sys 0.48.0", "windows-sys 0.52.0",
] ]
[[package]] [[package]]
@ -399,9 +399,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.14.2" version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
[[package]] [[package]]
name = "heck" name = "heck"
@ -432,7 +432,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
dependencies = [ dependencies = [
"equivalent", "equivalent",
"hashbrown 0.14.2", "hashbrown 0.14.3",
] ]
[[package]] [[package]]
@ -588,15 +588,15 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
[[package]] [[package]]
name = "linux-raw-sys" name = "linux-raw-sys"
version = "0.4.11" version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456"
[[package]] [[package]]
name = "llvm-sys" name = "llvm-sys"
version = "140.1.2" version = "140.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69b285f8682531b9b394dd9891977a2a28c47006e491bda944e1ca62ebab2664" checksum = "e3dc78e9857c0231ec11e3bdccf63870493fdc7d0570b0ea7d50bf5df0cb1a0c"
dependencies = [ dependencies = [
"cc", "cc",
"lazy_static", "lazy_static",
@ -835,9 +835,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.69" version = "1.0.70"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@ -1026,15 +1026,15 @@ dependencies = [
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.38.21" version = "0.38.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" checksum = "9470c4bf8246c8daf25f9598dca807fb6510347b1e1cfa55749113850c79d88a"
dependencies = [ dependencies = [
"bitflags 2.4.1", "bitflags 2.4.1",
"errno", "errno",
"libc", "libc",
"linux-raw-sys", "linux-raw-sys",
"windows-sys 0.48.0", "windows-sys 0.52.0",
] ]
[[package]] [[package]]
@ -1063,18 +1063,18 @@ checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.192" version = "1.0.193"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.192" version = "1.0.193"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1118,9 +1118,9 @@ checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.11.1" version = "1.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
[[package]] [[package]]
name = "string-interner" name = "string-interner"
@ -1419,6 +1419,15 @@ dependencies = [
"windows-targets 0.48.5", "windows-targets 0.48.5",
] ]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets 0.52.0",
]
[[package]] [[package]]
name = "windows-targets" name = "windows-targets"
version = "0.42.2" version = "0.42.2"
@ -1449,6 +1458,21 @@ dependencies = [
"windows_x86_64_msvc 0.48.5", "windows_x86_64_msvc 0.48.5",
] ]
[[package]]
name = "windows-targets"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
dependencies = [
"windows_aarch64_gnullvm 0.52.0",
"windows_aarch64_msvc 0.52.0",
"windows_i686_gnu 0.52.0",
"windows_i686_msvc 0.52.0",
"windows_x86_64_gnu 0.52.0",
"windows_x86_64_gnullvm 0.52.0",
"windows_x86_64_msvc 0.52.0",
]
[[package]] [[package]]
name = "windows_aarch64_gnullvm" name = "windows_aarch64_gnullvm"
version = "0.42.2" version = "0.42.2"
@ -1461,6 +1485,12 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.42.2" version = "0.42.2"
@ -1473,6 +1503,12 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.42.2" version = "0.42.2"
@ -1485,6 +1521,12 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_gnu"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.42.2" version = "0.42.2"
@ -1497,6 +1539,12 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_i686_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.42.2" version = "0.42.2"
@ -1509,6 +1557,12 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
version = "0.42.2" version = "0.42.2"
@ -1521,6 +1575,12 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.42.2" version = "0.42.2"
@ -1533,6 +1593,12 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
[[package]] [[package]]
name = "yaml-rust" name = "yaml-rust"
version = "0.4.5" version = "0.4.5"
@ -1544,18 +1610,18 @@ dependencies = [
[[package]] [[package]]
name = "zerocopy" name = "zerocopy"
version = "0.7.25" version = "0.7.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cd369a67c0edfef15010f980c3cbe45d7f651deac2cd67ce097cd801de16557" checksum = "7d6f15f7ade05d2a4935e34a457b936c23dc70a05cc1d97133dc99e7a3fe0f0e"
dependencies = [ dependencies = [
"zerocopy-derive", "zerocopy-derive",
] ]
[[package]] [[package]]
name = "zerocopy-derive" name = "zerocopy-derive"
version = "0.7.25" version = "0.7.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2f140bda219a26ccc0cdb03dba58af72590c53b22642577d88a927bc5c87d6b" checksum = "dbbad221e3f78500350ecbd7dfa4e63ef945c05f4c61cb7f4d3f84cd0bba649b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

View File

@ -23,7 +23,7 @@ After setting up Nix as above, use ``nix shell git+https://github.com/m-labs/art
### Windows ### Windows
Install [MSYS2](https://www.msys2.org/), and open "MSYS2 MinGW x64". Edit ``/etc/pacman.conf`` to add: Install [MSYS2](https://www.msys2.org/), and open "MSYS2 CLANG64". Edit ``/etc/pacman.conf`` to add:
``` ```
[artiq] [artiq]
SigLevel = Optional TrustAll SigLevel = Optional TrustAll
@ -33,11 +33,9 @@ Server = https://msys2.m-labs.hk/artiq-nac3
Then run the following commands: Then run the following commands:
``` ```
pacman -Syu pacman -Syu
pacman -S mingw-w64-x86_64-artiq pacman -S mingw-w64-clang-x86_64-artiq
``` ```
Note: This build of NAC3 cannot be used with Anaconda Python nor the python.org binaries for Windows. Those Python versions are compiled with Visual Studio (MSVC) and their ABI is incompatible with the GNU ABI used in this build. We have no plans to support Visual Studio nor the MSVC ABI. If you need a MSVC build, please install the requisite bloated spyware from Microsoft and compile NAC3 yourself.
## For developers ## For developers
This repository contains: This repository contains:

View File

@ -2,16 +2,16 @@
"nodes": { "nodes": {
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1699343069, "lastModified": 1701389149,
"narHash": "sha256-s7BBhyLA6MI6FuJgs4F/SgpntHBzz40/qV0xLPW6A1Q=", "narHash": "sha256-rU1suTIEd5DGCaAXKW6yHoCfR1mnYjOXQFOaH7M23js=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "ec750fd01963ab6b20ee1f0cb488754e8036d89d", "rev": "5de0b32be6e85dc1a9404c75131316e4ffbc634c",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "NixOS", "owner": "NixOS",
"ref": "nixpkgs-unstable", "ref": "nixos-23.11",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }

View File

@ -1,7 +1,7 @@
{ {
description = "The third-generation ARTIQ compiler"; description = "The third-generation ARTIQ compiler";
inputs.nixpkgs.url = github:NixOS/nixpkgs/nixpkgs-unstable; inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-23.11;
outputs = { self, nixpkgs }: outputs = { self, nixpkgs }:
let let
@ -9,7 +9,12 @@
in rec { in rec {
packages.x86_64-linux = rec { packages.x86_64-linux = rec {
llvm-nac3 = pkgs.callPackage ./nix/llvm {}; llvm-nac3 = pkgs.callPackage ./nix/llvm {};
clang-unwrapped = pkgs.runCommandNoCC "clang-unwrapped" {} "mkdir -p $out/bin; ln -s ${pkgs.llvmPackages_14.clang-unwrapped}/bin/clang $out/bin/clang-unwrapped"; llvm-tools-irrt = pkgs.runCommandNoCC "llvm-tools-irrt" {}
''
mkdir -p $out/bin
ln -s ${pkgs.llvmPackages_14.clang-unwrapped}/bin/clang $out/bin/clang-irrt
ln -s ${pkgs.llvmPackages_14.llvm.out}/bin/llvm-as $out/bin/llvm-as-irrt
'';
nac3artiq = pkgs.python3Packages.toPythonModule ( nac3artiq = pkgs.python3Packages.toPythonModule (
pkgs.rustPlatform.buildRustPackage rec { pkgs.rustPlatform.buildRustPackage rec {
name = "nac3artiq"; name = "nac3artiq";
@ -19,7 +24,7 @@
lockFile = ./Cargo.lock; lockFile = ./Cargo.lock;
}; };
passthru.cargoLock = cargoLock; passthru.cargoLock = cargoLock;
nativeBuildInputs = [ pkgs.python3 pkgs.llvmPackages_14.clang packages.x86_64-linux.clang-unwrapped pkgs.llvmPackages_14.llvm.out llvm-nac3 ]; nativeBuildInputs = [ pkgs.python3 pkgs.llvmPackages_14.clang llvm-tools-irrt pkgs.llvmPackages_14.llvm.out llvm-nac3 ];
buildInputs = [ pkgs.python3 llvm-nac3 ]; buildInputs = [ pkgs.python3 llvm-nac3 ];
checkInputs = [ (pkgs.python3.withPackages(ps: [ ps.numpy ps.scipy ])) ]; checkInputs = [ (pkgs.python3.withPackages(ps: [ ps.numpy ps.scipy ])) ];
checkPhase = checkPhase =
@ -59,7 +64,7 @@
name = "nac3artiq-instrumented"; name = "nac3artiq-instrumented";
src = self; src = self;
inherit (nac3artiq) cargoLock; inherit (nac3artiq) cargoLock;
nativeBuildInputs = [ pkgs.python3 packages.x86_64-linux.clang-unwrapped pkgs.llvmPackages_14.llvm.out llvm-nac3-instrumented ]; nativeBuildInputs = [ pkgs.python3 packages.x86_64-linux.llvm-tools-irrt llvm-nac3-instrumented ];
buildInputs = [ pkgs.python3 llvm-nac3-instrumented ]; buildInputs = [ pkgs.python3 llvm-nac3-instrumented ];
cargoBuildFlags = [ "--package" "nac3artiq" "--features" "init-llvm-profile" ]; cargoBuildFlags = [ "--package" "nac3artiq" "--features" "init-llvm-profile" ];
doCheck = false; doCheck = false;
@ -87,8 +92,8 @@
(pkgs.fetchFromGitHub { (pkgs.fetchFromGitHub {
owner = "m-labs"; owner = "m-labs";
repo = "artiq"; repo = "artiq";
rev = "5bbac04bef170cddb608b5dc8d9e6778cc7b31e8"; rev = "4c189f8c0576111733bb6ff934035c080c8ccc58";
sha256 = "sha256-TnRS2NrQaDiDzUsmfjkZh69xi2XC9v+4hnkedycAo0k="; sha256 = "sha256-gYGzmfaIoftKFDwn8AybUenYtIpux+tHGMu51WgwA8A=";
}) })
]; ];
buildInputs = [ buildInputs = [
@ -121,7 +126,7 @@
name = "nac3artiq-pgo"; name = "nac3artiq-pgo";
src = self; src = self;
inherit (nac3artiq) cargoLock; inherit (nac3artiq) cargoLock;
nativeBuildInputs = [ pkgs.python3 packages.x86_64-linux.clang-unwrapped pkgs.llvmPackages_14.llvm.out llvm-nac3-pgo ]; nativeBuildInputs = [ pkgs.python3 packages.x86_64-linux.llvm-tools-irrt llvm-nac3-pgo ];
buildInputs = [ pkgs.python3 llvm-nac3-pgo ]; buildInputs = [ pkgs.python3 llvm-nac3-pgo ];
cargoBuildFlags = [ "--package" "nac3artiq" ]; cargoBuildFlags = [ "--package" "nac3artiq" ];
cargoTestFlags = [ "--package" "nac3ast" "--package" "nac3parser" "--package" "nac3core" "--package" "nac3artiq" ]; cargoTestFlags = [ "--package" "nac3ast" "--package" "nac3parser" "--package" "nac3core" "--package" "nac3artiq" ];
@ -143,8 +148,7 @@
# build dependencies # build dependencies
packages.x86_64-linux.llvm-nac3 packages.x86_64-linux.llvm-nac3
llvmPackages_14.clang # demo llvmPackages_14.clang # demo
packages.x86_64-linux.clang-unwrapped # IRRT packages.x86_64-linux.llvm-tools-irrt
pkgs.llvmPackages_14.llvm.out # IRRT
cargo cargo
rustc rustc
# runtime dependencies # runtime dependencies

View File

@ -10,7 +10,7 @@ from embedding_map import EmbeddingMap
__all__ = [ __all__ = [
"Kernel", "KernelInvariant", "virtual", "Kernel", "KernelInvariant", "virtual", "ConstGeneric",
"Option", "Some", "none", "UnwrapNoneError", "Option", "Some", "none", "UnwrapNoneError",
"round64", "floor64", "ceil64", "round64", "floor64", "ceil64",
"extern", "kernel", "portable", "nac3", "extern", "kernel", "portable", "nac3",
@ -67,6 +67,12 @@ def Some(v: T) -> Option[T]:
none = Option(None) none = Option(None)
class _ConstGenericMarker:
pass
def ConstGeneric(name, constraint):
return TypeVar(name, _ConstGenericMarker, constraint)
def round64(x): def round64(x):
return round(x) return round(x)

View File

@ -145,7 +145,8 @@ impl<'a> ArtiqCodeGenerator<'a> {
let end_store = self.gen_store_target( let end_store = self.gen_store_target(
ctx, ctx,
&end, &end,
store_name.map(|name| format!("{name}.addr")).as_deref())?; store_name.map(|name| format!("{name}.addr")).as_deref())?
.unwrap();
ctx.builder.build_store(end_store, max); ctx.builder.build_store(end_store, max);
} }
@ -261,7 +262,9 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> {
node: ExprKind::Name { id: start, ctx: name_ctx.clone() }, node: ExprKind::Name { id: start, ctx: name_ctx.clone() },
custom: Some(ctx.primitives.int64), custom: Some(ctx.primitives.int64),
}; };
let start = self.gen_store_target(ctx, &start_expr, Some("start.addr"))?; let start = self
.gen_store_target(ctx, &start_expr, Some("start.addr"))?
.unwrap();
ctx.builder.build_store(start, now); ctx.builder.build_store(start, now);
Ok(Some(start_expr)) as Result<_, String> Ok(Some(start_expr)) as Result<_, String>
}, },
@ -274,7 +277,9 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> {
node: ExprKind::Name { id: end, ctx: name_ctx.clone() }, node: ExprKind::Name { id: end, ctx: name_ctx.clone() },
custom: Some(ctx.primitives.int64), custom: Some(ctx.primitives.int64),
}; };
let end = self.gen_store_target(ctx, &end_expr, Some("end.addr"))?; let end = self
.gen_store_target(ctx, &end_expr, Some("end.addr"))?
.unwrap();
ctx.builder.build_store(end, now); ctx.builder.build_store(end, now);
self.end = Some(end_expr); self.end = Some(end_expr);
self.name_counter += 1; self.name_counter += 1;

View File

@ -75,6 +75,7 @@ pub struct PrimitivePythonId {
list: u64, list: u64,
tuple: u64, tuple: u64,
typevar: u64, typevar: u64,
const_generic_dummy: u64,
none: u64, none: u64,
exception: u64, exception: u64,
generic_alias: (u64, u64), generic_alias: (u64, u64),
@ -877,6 +878,15 @@ impl Nac3 {
.extract() .extract()
.unwrap(), .unwrap(),
typevar: get_attr_id(typing_mod, "TypeVar"), typevar: get_attr_id(typing_mod, "TypeVar"),
const_generic_dummy: id_fn
.call1((
builtins_mod.getattr("globals")
.and_then(|v| v.call0())
.and_then(|v| v.get_item("_ConstGenericMarker"))
.unwrap(),
))
.and_then(|v| v.extract())
.unwrap(),
int: get_attr_id(builtins_mod, "int"), int: get_attr_id(builtins_mod, "int"),
int32: get_attr_id(numpy_mod, "int32"), int32: get_attr_id(numpy_mod, "int32"),
int64: get_attr_id(numpy_mod, "int64"), int64: get_attr_id(numpy_mod, "int64"),

View File

@ -266,10 +266,12 @@ impl InnerResolver {
Ok(Ok(ty)) Ok(Ok(ty))
} }
// handle python objects that represent types themselves /// handle python objects that represent types themselves
// primitives and class types should be themselves, use `ty_id` to check, ///
// TypeVars and GenericAlias(`A[int, bool]`) should use `ty_ty_id` to check /// primitives and class types should be themselves, use `ty_id` to check,
// the `bool` value returned indicates whether they are instantiated or not /// TypeVars and GenericAlias(`A[int, bool]`) should use `ty_ty_id` to check
///
/// the `bool` value returned indicates whether they are instantiated or not
fn get_pyty_obj_type( fn get_pyty_obj_type(
&self, &self,
py: Python, py: Python,
@ -345,13 +347,21 @@ impl InnerResolver {
} }
} else if ty_ty_id == self.primitive_ids.typevar { } else if ty_ty_id == self.primitive_ids.typevar {
let name: &str = pyty.getattr("__name__").unwrap().extract().unwrap(); let name: &str = pyty.getattr("__name__").unwrap().extract().unwrap();
let constraint_types = { let (constraint_types, is_const_generic) = {
let constraints = pyty.getattr("__constraints__").unwrap(); let constraints = pyty.getattr("__constraints__").unwrap();
let mut result: Vec<Type> = vec![]; let mut result: Vec<Type> = vec![];
let needs_defer = self.deferred_eval_store.needs_defer.load(Relaxed); let needs_defer = self.deferred_eval_store.needs_defer.load(Relaxed);
let mut is_const_generic = false;
for i in 0usize.. { for i in 0usize.. {
if let Ok(constr) = constraints.get_item(i) { if let Ok(constr) = constraints.get_item(i) {
if needs_defer { let constr_id: u64 = self.helper.id_fn.call1(py, (constr,))?.extract(py)?;
if constr_id == self.primitive_ids.const_generic_dummy {
is_const_generic = true;
continue
}
if !is_const_generic && needs_defer {
result.push(unifier.get_dummy_var().0); result.push(unifier.get_dummy_var().0);
} else { } else {
result.push({ result.push({
@ -375,17 +385,28 @@ impl InnerResolver {
break; break;
} }
} }
if needs_defer {
if !is_const_generic && needs_defer {
self.deferred_eval_store.store.write() self.deferred_eval_store.store.write()
.push((result.clone(), .push((result.clone(),
constraints.extract()?, constraints.extract()?,
pyty.getattr("__name__")?.extract::<String>()? pyty.getattr("__name__")?.extract::<String>()?
)) ))
} }
result
(result, is_const_generic)
}; };
let res =
unifier.get_fresh_var_with_range(&constraint_types, Some(name.into()), None).0; let res = if is_const_generic {
if constraint_types.len() != 1 {
return Ok(Err(format!("ConstGeneric expects 1 argument, got {}", constraint_types.len())))
}
unifier.get_fresh_const_generic_var(constraint_types[0], Some(name.into()), None).0
} else {
unifier.get_fresh_var_with_range(&constraint_types, Some(name.into()), None).0
};
Ok(Ok((res, true))) Ok(Ok((res, true)))
} else if ty_ty_id == self.primitive_ids.generic_alias.0 } else if ty_ty_id == self.primitive_ids.generic_alias.0
|| ty_ty_id == self.primitive_ids.generic_alias.1 || ty_ty_id == self.primitive_ids.generic_alias.1

View File

@ -26,7 +26,7 @@ pub struct Location {
impl fmt::Display for Location { impl fmt::Display for Location {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}: line {} column {}", self.file.0, self.row, self.column) write!(f, "{}:{}:{}", self.file.0, self.row, self.column)
} }
} }

View File

@ -29,7 +29,7 @@ fn main() {
"-o", "-o",
"-", "-",
]; ];
let output = Command::new("clang-unwrapped") let output = Command::new("clang-irrt")
.args(FLAG) .args(FLAG)
.output() .output()
.map(|o| { .map(|o| {
@ -61,7 +61,7 @@ fn main() {
file.write_all(filtered_output.as_bytes()).unwrap(); file.write_all(filtered_output.as_bytes()).unwrap();
} }
let mut llvm_as = Command::new("llvm-as") let mut llvm_as = Command::new("llvm-as-irrt")
.stdin(Stdio::piped()) .stdin(Stdio::piped())
.arg("-o") .arg("-o")
.arg(out_path.join("irrt.bc")) .arg(out_path.join("irrt.bc"))

View File

@ -207,12 +207,12 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
generator: &mut dyn CodeGenerator, generator: &mut dyn CodeGenerator,
value: &Constant, value: &Constant,
ty: Type, ty: Type,
) -> BasicValueEnum<'ctx> { ) -> Option<BasicValueEnum<'ctx>> {
match value { match value {
Constant::Bool(v) => { Constant::Bool(v) => {
assert!(self.unifier.unioned(ty, self.primitives.bool)); assert!(self.unifier.unioned(ty, self.primitives.bool));
let ty = self.ctx.i8_type(); let ty = self.ctx.i8_type();
ty.const_int(if *v { 1 } else { 0 }, false).into() Some(ty.const_int(if *v { 1 } else { 0 }, false).into())
} }
Constant::Int(val) => { Constant::Int(val) => {
let ty = if self.unifier.unioned(ty, self.primitives.int32) let ty = if self.unifier.unioned(ty, self.primitives.int32)
@ -226,28 +226,33 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
} else { } else {
unreachable!(); unreachable!();
}; };
ty.const_int(*val as u64, false).into() Some(ty.const_int(*val as u64, false).into())
} }
Constant::Float(v) => { Constant::Float(v) => {
assert!(self.unifier.unioned(ty, self.primitives.float)); assert!(self.unifier.unioned(ty, self.primitives.float));
let ty = self.ctx.f64_type(); let ty = self.ctx.f64_type();
ty.const_float(*v).into() Some(ty.const_float(*v).into())
} }
Constant::Tuple(v) => { Constant::Tuple(v) => {
let ty = self.unifier.get_ty(ty); let ty = self.unifier.get_ty(ty);
let types = let types =
if let TypeEnum::TTuple { ty } = &*ty { ty.clone() } else { unreachable!() }; if let TypeEnum::TTuple { ty } = &*ty { ty.clone() } else { unreachable!() };
let values = zip(types.into_iter(), v.iter()) let values = zip(types.into_iter(), v.iter())
.map(|(ty, v)| self.gen_const(generator, v, ty)) .map_while(|(ty, v)| self.gen_const(generator, v, ty))
.collect_vec(); .collect_vec();
let types = values.iter().map(BasicValueEnum::get_type).collect_vec();
let ty = self.ctx.struct_type(&types, false); if values.len() == v.len() {
ty.const_named_struct(&values).into() let types = values.iter().map(BasicValueEnum::get_type).collect_vec();
let ty = self.ctx.struct_type(&types, false);
Some(ty.const_named_struct(&values).into())
} else {
None
}
} }
Constant::Str(v) => { Constant::Str(v) => {
assert!(self.unifier.unioned(ty, self.primitives.str)); assert!(self.unifier.unioned(ty, self.primitives.str));
if let Some(v) = self.const_strings.get(v) { if let Some(v) = self.const_strings.get(v) {
*v Some(*v)
} else { } else {
let str_ptr = let str_ptr =
self.builder.build_global_string_ptr(v, "const").as_pointer_value().into(); self.builder.build_global_string_ptr(v, "const").as_pointer_value().into();
@ -256,9 +261,22 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
let val = let val =
ty.into_struct_type().const_named_struct(&[str_ptr, size.into()]).into(); ty.into_struct_type().const_named_struct(&[str_ptr, size.into()]).into();
self.const_strings.insert(v.to_string(), val); self.const_strings.insert(v.to_string(), val);
val Some(val)
} }
} }
Constant::Ellipsis => {
let msg = self.gen_string(generator, "NotImplementedError");
self.raise_exn(
generator,
"0:NotImplementedError",
msg,
[None, None, None],
self.current_loc,
);
None
}
_ => unreachable!(), _ => unreachable!(),
} }
} }
@ -481,7 +499,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
generator: &mut dyn CodeGenerator, generator: &mut dyn CodeGenerator,
s: S, s: S,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
self.gen_const(generator, &nac3parser::ast::Constant::Str(s.into()), self.primitives.str) self.gen_const(generator, &nac3parser::ast::Constant::Str(s.into()), self.primitives.str).unwrap()
} }
pub fn raise_exn( pub fn raise_exn(
@ -935,7 +953,7 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>(
generator: &mut G, generator: &mut G,
ctx: &mut CodeGenContext<'ctx, 'a>, ctx: &mut CodeGenContext<'ctx, 'a>,
expr: &Expr<Option<Type>>, expr: &Expr<Option<Type>>,
) -> Result<BasicValueEnum<'ctx>, String> { ) -> Result<Option<BasicValueEnum<'ctx>>, String> {
if let ExprKind::ListComp { elt, generators } = &expr.node { if let ExprKind::ListComp { elt, generators } = &expr.node {
let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap(); let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap();
@ -949,9 +967,16 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>(
ctx.builder.position_at_end(init_bb); ctx.builder.position_at_end(init_bb);
let Comprehension { target, iter, ifs, .. } = &generators[0]; let Comprehension { target, iter, ifs, .. } = &generators[0];
let iter_val = generator.gen_expr(ctx, iter)? let iter_val = if let Some(v) = generator.gen_expr(ctx, iter)? {
.unwrap() v.to_basic_value_enum(ctx, generator, iter.custom.unwrap())?
.to_basic_value_enum(ctx, generator, iter.custom.unwrap())?; } else {
for bb in [test_bb, body_bb, cont_bb] {
ctx.builder.position_at_end(bb);
ctx.builder.build_unreachable();
}
return Ok(None)
};
let int32 = ctx.ctx.i32_type(); let int32 = ctx.ctx.i32_type();
let size_t = generator.get_size_type(ctx.ctx); let size_t = generator.get_size_type(ctx.ctx);
let zero_size_t = size_t.const_zero(); let zero_size_t = size_t.const_zero();
@ -994,7 +1019,7 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>(
list_content = ctx.build_gep_and_load(list, &[zero_size_t, zero_32], Some("listcomp.data.addr")) list_content = ctx.build_gep_and_load(list, &[zero_size_t, zero_32], Some("listcomp.data.addr"))
.into_pointer_value(); .into_pointer_value();
let i = generator.gen_store_target(ctx, target, Some("i.addr"))?; let i = generator.gen_store_target(ctx, target, Some("i.addr"))?.unwrap();
ctx.builder.build_store(i, ctx.builder.build_int_sub(start, step, "start_init")); ctx.builder.build_store(i, ctx.builder.build_int_sub(start, step, "start_init"));
ctx.builder.build_conditional_branch( ctx.builder.build_conditional_branch(
@ -1049,12 +1074,25 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>(
generator.gen_assign(ctx, target, val.into())?; generator.gen_assign(ctx, target, val.into())?;
} }
// Emits the content of `cont_bb`
let emit_cont_bb = |ctx: &CodeGenContext| {
ctx.builder.position_at_end(cont_bb);
let len_ptr = unsafe {
ctx.builder.build_gep(list, &[zero_size_t, int32.const_int(1, false)], "length")
};
ctx.builder.build_store(len_ptr, ctx.builder.build_load(index, "index"));
};
for cond in ifs.iter() { for cond in ifs.iter() {
let result = generator let result = if let Some(v) = generator.gen_expr(ctx, cond)? {
.gen_expr(ctx, cond)? v.to_basic_value_enum(ctx, generator, cond.custom.unwrap())?.into_int_value()
.unwrap() } else {
.to_basic_value_enum(ctx, generator, cond.custom.unwrap())? // Bail if the predicate is an ellipsis - Emit cont_bb contents in case the
.into_int_value(); // no element matches the predicate
emit_cont_bb(ctx);
return Ok(None)
};
let result = generator.bool_to_i1(ctx, result); let result = generator.bool_to_i1(ctx, result);
let succ = ctx.ctx.append_basic_block(current, "then"); let succ = ctx.ctx.append_basic_block(current, "then");
ctx.builder.build_conditional_branch(result, succ, test_bb); ctx.builder.build_conditional_branch(result, succ, test_bb);
@ -1062,7 +1100,12 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>(
ctx.builder.position_at_end(succ); ctx.builder.position_at_end(succ);
} }
let elem = generator.gen_expr(ctx, elt)?.unwrap(); let Some(elem) = generator.gen_expr(ctx, elt)? else {
// Similarly, bail if the generator expression is an ellipsis, but keep cont_bb contents
emit_cont_bb(ctx);
return Ok(None)
};
let i = ctx.builder.build_load(index, "i").into_int_value(); let i = ctx.builder.build_load(index, "i").into_int_value();
let elem_ptr = unsafe { ctx.builder.build_gep(list_content, &[i], "elem_ptr") }; let elem_ptr = unsafe { ctx.builder.build_gep(list_content, &[i], "elem_ptr") };
let val = elem.to_basic_value_enum(ctx, generator, elt.custom.unwrap())?; let val = elem.to_basic_value_enum(ctx, generator, elt.custom.unwrap())?;
@ -1071,13 +1114,9 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>(
.build_store(index, ctx.builder.build_int_add(i, size_t.const_int(1, false), "inc")); .build_store(index, ctx.builder.build_int_add(i, size_t.const_int(1, false), "inc"));
ctx.builder.build_unconditional_branch(test_bb); ctx.builder.build_unconditional_branch(test_bb);
ctx.builder.position_at_end(cont_bb); emit_cont_bb(ctx);
let len_ptr = unsafe {
ctx.builder.build_gep(list, &[zero_size_t, int32.const_int(1, false)], "length")
};
ctx.builder.build_store(len_ptr, ctx.builder.build_load(index, "index"));
Ok(list.into()) Ok(Some(list.into()))
} else { } else {
unreachable!() unreachable!()
} }
@ -1101,14 +1140,16 @@ pub fn gen_binop_expr<'ctx, 'a, G: CodeGenerator>(
) -> Result<Option<ValueEnum<'ctx>>, String> { ) -> Result<Option<ValueEnum<'ctx>>, String> {
let ty1 = ctx.unifier.get_representative(left.custom.unwrap()); let ty1 = ctx.unifier.get_representative(left.custom.unwrap());
let ty2 = ctx.unifier.get_representative(right.custom.unwrap()); let ty2 = ctx.unifier.get_representative(right.custom.unwrap());
let left_val = generator let left_val = if let Some(v) = generator.gen_expr(ctx, left)? {
.gen_expr(ctx, left)? v.to_basic_value_enum(ctx, generator, left.custom.unwrap())?
.unwrap() } else {
.to_basic_value_enum(ctx, generator, left.custom.unwrap())?; return Ok(None)
let right_val = generator };
.gen_expr(ctx, right)? let right_val = if let Some(v) = generator.gen_expr(ctx, right)? {
.unwrap() v.to_basic_value_enum(ctx, generator, right.custom.unwrap())?
.to_basic_value_enum(ctx, generator, right.custom.unwrap())?; } else {
return Ok(None)
};
// we can directly compare the types, because we've got their representatives // we can directly compare the types, because we've got their representatives
// which would be unchanged until further unification, which we would never do // which would be unchanged until further unification, which we would never do
@ -1211,7 +1252,10 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
Ok(Some(match &expr.node { Ok(Some(match &expr.node {
ExprKind::Constant { value, .. } => { ExprKind::Constant { value, .. } => {
let ty = expr.custom.unwrap(); let ty = expr.custom.unwrap();
ctx.gen_const(generator, value, ty).into() let Some(const_val) = ctx.gen_const(generator, value, ty) else {
return Ok(None)
};
const_val.into()
} }
ExprKind::Name { id, .. } if id == &"none".into() => { ExprKind::Name { id, .. } if id == &"none".into() => {
match ( match (
@ -1242,15 +1286,17 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
// we should use memcpy for that instead of generating thousands of stores // we should use memcpy for that instead of generating thousands of stores
let elements = elts let elements = elts
.iter() .iter()
.map(|x| { .map(|x| generator.gen_expr(ctx, x))
generator .take_while(|v| !matches!(v, Ok(None)))
.gen_expr(ctx, x)
.map_or_else(
Err,
|v| v.unwrap().to_basic_value_enum(ctx, generator, x.custom.unwrap())
)
})
.collect::<Result<Vec<_>, _>>()?; .collect::<Result<Vec<_>, _>>()?;
let elements = elements.into_iter().zip(elts)
.map(|(v, x)| v.unwrap().to_basic_value_enum(ctx, generator, x.custom.unwrap()))
.collect::<Result<Vec<_>, _>>()?;
if elements.len() < elts.len() {
return Ok(None)
}
let ty = if elements.is_empty() { let ty = if elements.is_empty() {
if let TypeEnum::TList { ty } = &*ctx.unifier.get_ty(expr.custom.unwrap()) { if let TypeEnum::TList { ty } = &*ctx.unifier.get_ty(expr.custom.unwrap()) {
ctx.get_llvm_type(generator, *ty) ctx.get_llvm_type(generator, *ty)
@ -1277,14 +1323,19 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
arr_str_ptr.into() arr_str_ptr.into()
} }
ExprKind::Tuple { elts, .. } => { ExprKind::Tuple { elts, .. } => {
let element_val = elts let elements_val = elts
.iter() .iter()
.map(|x| { .map(|x| generator.gen_expr(ctx, x))
generator .take_while(|v| !matches!(v, Ok(None)))
.gen_expr(ctx, x)
.map_or_else(Err, |v| v.unwrap().to_basic_value_enum(ctx, generator, x.custom.unwrap()))
})
.collect::<Result<Vec<_>, _>>()?; .collect::<Result<Vec<_>, _>>()?;
let element_val = elements_val.into_iter().zip(elts)
.map(|(v, x)| v.unwrap().to_basic_value_enum(ctx, generator, x.custom.unwrap()))
.collect::<Result<Vec<_>, _>>()?;
if element_val.len() < elts.len() {
return Ok(None)
}
let element_ty = element_val.iter().map(BasicValueEnum::get_type).collect_vec(); let element_ty = element_val.iter().map(BasicValueEnum::get_type).collect_vec();
let tuple_ty = ctx.ctx.struct_type(&element_ty, false); let tuple_ty = ctx.ctx.struct_type(&element_ty, false);
let tuple_ptr = ctx.builder.build_alloca(tuple_ty, "tuple"); let tuple_ptr = ctx.builder.build_alloca(tuple_ty, "tuple");
@ -1302,8 +1353,8 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
} }
ExprKind::Attribute { value, attr, .. } => { ExprKind::Attribute { value, attr, .. } => {
// note that we would handle class methods directly in calls // note that we would handle class methods directly in calls
match generator.gen_expr(ctx, value)?.unwrap() { match generator.gen_expr(ctx, value)? {
ValueEnum::Static(v) => v.get_field(*attr, ctx).map_or_else(|| { Some(ValueEnum::Static(v)) => v.get_field(*attr, ctx).map_or_else(|| {
let v = v.to_basic_value_enum(ctx, generator, value.custom.unwrap())?; let v = v.to_basic_value_enum(ctx, generator, value.custom.unwrap())?;
let index = ctx.get_attr_index(value.custom.unwrap(), *attr); let index = ctx.get_attr_index(value.custom.unwrap(), *attr);
Ok(ValueEnum::Dynamic(ctx.build_gep_and_load( Ok(ValueEnum::Dynamic(ctx.build_gep_and_load(
@ -1312,7 +1363,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
None, None,
))) as Result<_, String> ))) as Result<_, String>
}, Ok)?, }, Ok)?,
ValueEnum::Dynamic(v) => { Some(ValueEnum::Dynamic(v)) => {
let index = ctx.get_attr_index(value.custom.unwrap(), *attr); let index = ctx.get_attr_index(value.custom.unwrap(), *attr);
ValueEnum::Dynamic(ctx.build_gep_and_load( ValueEnum::Dynamic(ctx.build_gep_and_load(
v.into_pointer_value(), v.into_pointer_value(),
@ -1320,15 +1371,16 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
None, None,
)) ))
} }
None => return Ok(None),
} }
} }
ExprKind::BoolOp { op, values } => { ExprKind::BoolOp { op, values } => {
// requires conditional branches for short-circuiting... // requires conditional branches for short-circuiting...
let left = generator let left = if let Some(v) = generator.gen_expr(ctx, &values[0])? {
.gen_expr(ctx, &values[0])? v.to_basic_value_enum(ctx, generator, values[0].custom.unwrap())?.into_int_value()
.unwrap() } else {
.to_basic_value_enum(ctx, generator, values[0].custom.unwrap())? return Ok(None)
.into_int_value(); };
let left = generator.bool_to_i1(ctx, left); let left = generator.bool_to_i1(ctx, left);
let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap(); let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap();
let a_bb = ctx.ctx.append_basic_block(current, "a"); let a_bb = ctx.ctx.append_basic_block(current, "a");
@ -1340,45 +1392,62 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
ctx.builder.position_at_end(a_bb); ctx.builder.position_at_end(a_bb);
let a = ctx.ctx.i8_type().const_int(1, false); let a = ctx.ctx.i8_type().const_int(1, false);
ctx.builder.build_unconditional_branch(cont_bb); ctx.builder.build_unconditional_branch(cont_bb);
ctx.builder.position_at_end(b_bb); ctx.builder.position_at_end(b_bb);
let b = generator let b = if let Some(v) = generator.gen_expr(ctx, &values[1])? {
.gen_expr(ctx, &values[1])? let b = v.to_basic_value_enum(ctx, generator, values[1].custom.unwrap())?.into_int_value();
.unwrap() let b = generator.bool_to_i8(ctx, b);
.to_basic_value_enum(ctx, generator, values[1].custom.unwrap())? ctx.builder.build_unconditional_branch(cont_bb);
.into_int_value();
let b = generator.bool_to_i8(ctx, b); Some(b)
ctx.builder.build_unconditional_branch(cont_bb); } else {
(a, b) None
};
(Some(a), b)
} }
Boolop::And => { Boolop::And => {
ctx.builder.position_at_end(a_bb); ctx.builder.position_at_end(a_bb);
let a = generator let a = if let Some(v) = generator.gen_expr(ctx, &values[1])? {
.gen_expr(ctx, &values[1])? let a = v.to_basic_value_enum(ctx, generator, values[1].custom.unwrap())?.into_int_value();
.unwrap() let a = generator.bool_to_i8(ctx, a);
.to_basic_value_enum(ctx, generator, values[1].custom.unwrap())? ctx.builder.build_unconditional_branch(cont_bb);
.into_int_value();
let a = generator.bool_to_i8(ctx, a); Some(a)
ctx.builder.build_unconditional_branch(cont_bb); } else {
None
};
ctx.builder.position_at_end(b_bb); ctx.builder.position_at_end(b_bb);
let b = ctx.ctx.i8_type().const_zero(); let b = ctx.ctx.i8_type().const_zero();
ctx.builder.build_unconditional_branch(cont_bb); ctx.builder.build_unconditional_branch(cont_bb);
(a, b)
(a, Some(b))
} }
}; };
ctx.builder.position_at_end(cont_bb); ctx.builder.position_at_end(cont_bb);
let phi = ctx.builder.build_phi(ctx.ctx.i8_type(), ""); match (a, b) {
phi.add_incoming(&[(&a, a_bb), (&b, b_bb)]); (Some(a), Some(b)) => {
phi.as_basic_value().into() let phi = ctx.builder.build_phi(ctx.ctx.i8_type(), "");
phi.add_incoming(&[(&a, a_bb), (&b, b_bb)]);
phi.as_basic_value().into()
}
(Some(a), None) => a.into(),
(None, Some(b)) => b.into(),
(None, None) => unreachable!(),
}
} }
ExprKind::BinOp { op, left, right } => { ExprKind::BinOp { op, left, right } => {
return gen_binop_expr(generator, ctx, left, op, right, expr.location, false); return gen_binop_expr(generator, ctx, left, op, right, expr.location, false);
} }
ExprKind::UnaryOp { op, operand } => { ExprKind::UnaryOp { op, operand } => {
let ty = ctx.unifier.get_representative(operand.custom.unwrap()); let ty = ctx.unifier.get_representative(operand.custom.unwrap());
let val = let val = if let Some(v) = generator.gen_expr(ctx, operand)? {
generator.gen_expr(ctx, operand)? v.to_basic_value_enum(ctx, generator, operand.custom.unwrap())?
.unwrap() } else {
.to_basic_value_enum(ctx, generator, operand.custom.unwrap())?; return Ok(None)
};
if ty == ctx.primitives.bool { if ty == ctx.primitives.bool {
let val = val.into_int_value(); let val = val.into_int_value();
match op { match op {
@ -1415,7 +1484,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
} }
} }
ExprKind::Compare { left, ops, comparators } => { ExprKind::Compare { left, ops, comparators } => {
izip!(chain(once(left.as_ref()), comparators.iter()), comparators.iter(), ops.iter(),) let cmp_val = izip!(chain(once(left.as_ref()), comparators.iter()), comparators.iter(), ops.iter(),)
.fold(Ok(None), |prev: Result<Option<_>, String>, (lhs, rhs, op)| { .fold(Ok(None), |prev: Result<Option<_>, String>, (lhs, rhs, op)| {
let ty = ctx.unifier.get_representative(lhs.custom.unwrap()); let ty = ctx.unifier.get_representative(lhs.custom.unwrap());
let current = let current =
@ -1427,23 +1496,15 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
ctx.primitives.uint64, ctx.primitives.uint64,
].contains(&ty); ].contains(&ty);
let (lhs, rhs) = if let ( let BasicValueEnum::IntValue(lhs) = (match generator.gen_expr(ctx, lhs)? {
BasicValueEnum::IntValue(lhs), Some(v) => v.to_basic_value_enum(ctx, generator, lhs.custom.unwrap())?,
BasicValueEnum::IntValue(rhs), None => return Ok(None),
) = ( }) else { unreachable!() };
generator
.gen_expr(ctx, lhs)? let BasicValueEnum::IntValue(rhs) = (match generator.gen_expr(ctx, rhs)? {
.unwrap() Some(v) => v.to_basic_value_enum(ctx, generator, rhs.custom.unwrap())?,
.to_basic_value_enum(ctx, generator, lhs.custom.unwrap())?, None => return Ok(None),
generator }) else { unreachable!() };
.gen_expr(ctx, rhs)?
.unwrap()
.to_basic_value_enum(ctx, generator, rhs.custom.unwrap())?,
) {
(lhs, rhs)
} else {
unreachable!()
};
let op = match op { let op = match op {
ast::Cmpop::Eq | ast::Cmpop::Is => IntPredicate::EQ, ast::Cmpop::Eq | ast::Cmpop::Is => IntPredicate::EQ,
@ -1474,23 +1535,16 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
ctx.builder.build_int_compare(op, lhs, rhs, "cmp") ctx.builder.build_int_compare(op, lhs, rhs, "cmp")
} else if ty == ctx.primitives.float { } else if ty == ctx.primitives.float {
let (lhs, rhs) = if let ( let BasicValueEnum::FloatValue(lhs) = (match generator.gen_expr(ctx, lhs)? {
BasicValueEnum::FloatValue(lhs), Some(v) => v.to_basic_value_enum(ctx, generator, lhs.custom.unwrap())?,
BasicValueEnum::FloatValue(rhs), None => return Ok(None),
) = ( }) else { unreachable!() };
generator
.gen_expr(ctx, lhs)? let BasicValueEnum::FloatValue(rhs) = (match generator.gen_expr(ctx, rhs)? {
.unwrap() Some(v) => v.to_basic_value_enum(ctx, generator, rhs.custom.unwrap())?,
.to_basic_value_enum(ctx, generator, lhs.custom.unwrap())?, None => return Ok(None),
generator }) else { unreachable!() };
.gen_expr(ctx, rhs)?
.unwrap()
.to_basic_value_enum(ctx, generator, rhs.custom.unwrap())?,
) {
(lhs, rhs)
} else {
unreachable!()
};
let op = match op { let op = match op {
ast::Cmpop::Eq | ast::Cmpop::Is => inkwell::FloatPredicate::OEQ, ast::Cmpop::Eq | ast::Cmpop::Is => inkwell::FloatPredicate::OEQ,
ast::Cmpop::NotEq => inkwell::FloatPredicate::ONE, ast::Cmpop::NotEq => inkwell::FloatPredicate::ONE,
@ -1505,16 +1559,18 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
unimplemented!() unimplemented!()
}; };
Ok(prev?.map(|v| ctx.builder.build_and(v, current, "cmp")).or(Some(current))) Ok(prev?.map(|v| ctx.builder.build_and(v, current, "cmp")).or(Some(current)))
})? })?;
.unwrap()
.into() // as there should be at least 1 element, it should never be none match cmp_val {
Some(v) => v.into(),
None => return Ok(None),
}
} }
ExprKind::IfExp { test, body, orelse } => { ExprKind::IfExp { test, body, orelse } => {
let test = generator let test = match generator.gen_expr(ctx, test)? {
.gen_expr(ctx, test)? Some(v) => v.to_basic_value_enum(ctx, generator, test.custom.unwrap())?.into_int_value(),
.unwrap() None => return Ok(None),
.to_basic_value_enum(ctx, generator, test.custom.unwrap())? };
.into_int_value();
let test = generator.bool_to_i1(ctx, test); let test = generator.bool_to_i1(ctx, test);
let body_ty = body.custom.unwrap(); let body_ty = body.custom.unwrap();
let is_none = ctx.unifier.get_representative(body_ty) == ctx.primitives.none; let is_none = ctx.unifier.get_representative(body_ty) == ctx.primitives.none;
@ -1529,37 +1585,52 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
let else_bb = ctx.ctx.append_basic_block(current, "else"); let else_bb = ctx.ctx.append_basic_block(current, "else");
let cont_bb = ctx.ctx.append_basic_block(current, "cont"); let cont_bb = ctx.ctx.append_basic_block(current, "cont");
ctx.builder.build_conditional_branch(test, then_bb, else_bb); ctx.builder.build_conditional_branch(test, then_bb, else_bb);
ctx.builder.position_at_end(then_bb); ctx.builder.position_at_end(then_bb);
let a = generator.gen_expr(ctx, body)?; let a = generator.gen_expr(ctx, body)?;
match result { if let Some(a) = a {
None => None, match result {
Some(v) => { None => None,
let a = a.unwrap().to_basic_value_enum(ctx, generator, body.custom.unwrap())?; Some(v) => {
Some(ctx.builder.build_store(v, a)) let a = a.to_basic_value_enum(ctx, generator, body.custom.unwrap())?;
} Some(ctx.builder.build_store(v, a))
}; }
ctx.builder.build_unconditional_branch(cont_bb); };
ctx.builder.build_unconditional_branch(cont_bb);
}
ctx.builder.position_at_end(else_bb); ctx.builder.position_at_end(else_bb);
let b = generator.gen_expr(ctx, orelse)?; let b = generator.gen_expr(ctx, orelse)?;
match result { if let Some(b) = b {
None => None, match result {
Some(v) => { None => None,
let b = b.unwrap().to_basic_value_enum(ctx, generator, orelse.custom.unwrap())?; Some(v) => {
Some(ctx.builder.build_store(v, b)) let b = b.to_basic_value_enum(ctx, generator, orelse.custom.unwrap())?;
} Some(ctx.builder.build_store(v, b))
}; }
ctx.builder.build_unconditional_branch(cont_bb); };
ctx.builder.build_unconditional_branch(cont_bb);
}
ctx.builder.position_at_end(cont_bb); ctx.builder.position_at_end(cont_bb);
match result { if let Some(v) = result {
None => return Ok(None), ctx.builder.build_load(v, "if_exp_val_load").into()
Some(v) => return Ok(Some(ctx.builder.build_load(v, "if_exp_val_load").into())) } else {
return Ok(None)
} }
} }
ExprKind::Call { func, args, keywords } => { ExprKind::Call { func, args, keywords } => {
let mut params = args let mut params = args
.iter() .iter()
.map(|arg| Ok((None, generator.gen_expr(ctx, arg)?.unwrap())) as Result<_, String>) .map(|arg| generator.gen_expr(ctx, arg))
.take_while(|expr| !matches!(expr, Ok(None)))
.map(|expr| Ok((None, expr?.unwrap())) as Result<_, String>)
.collect::<Result<Vec<_>, _>>()?; .collect::<Result<Vec<_>, _>>()?;
if params.len() < args.len() {
return Ok(None)
}
let kw_iter = keywords.iter().map(|kw| { let kw_iter = keywords.iter().map(|kw| {
Ok(( Ok((
Some(*kw.node.arg.as_ref().unwrap()), Some(*kw.node.arg.as_ref().unwrap()),
@ -1593,7 +1664,11 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
.map(|v| v.into())); .map(|v| v.into()));
} }
ExprKind::Attribute { value, attr, .. } => { ExprKind::Attribute { value, attr, .. } => {
let val = generator.gen_expr(ctx, value)?.unwrap(); let val = match generator.gen_expr(ctx, value)? {
Some(v) => v,
None => return Ok(None),
};
let id = if let TypeEnum::TObj { obj_id, .. } = let id = if let TypeEnum::TObj { obj_id, .. } =
&*ctx.unifier.get_ty(value.custom.unwrap()) &*ctx.unifier.get_ty(value.custom.unwrap())
{ {
@ -1691,18 +1766,20 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
} }
ExprKind::Subscript { value, slice, .. } => { ExprKind::Subscript { value, slice, .. } => {
if let TypeEnum::TList { ty } = &*ctx.unifier.get_ty(value.custom.unwrap()) { if let TypeEnum::TList { ty } = &*ctx.unifier.get_ty(value.custom.unwrap()) {
let v = generator let v = if let Some(v) = generator.gen_expr(ctx, value)? {
.gen_expr(ctx, value)? v.to_basic_value_enum(ctx, generator, value.custom.unwrap())?.into_pointer_value()
.unwrap() } else {
.to_basic_value_enum(ctx, generator, value.custom.unwrap())? return Ok(None)
.into_pointer_value(); };
let ty = ctx.get_llvm_type(generator, *ty); let ty = ctx.get_llvm_type(generator, *ty);
let arr_ptr = ctx.build_gep_and_load(v, &[zero, zero], Some("arr.addr")) let arr_ptr = ctx.build_gep_and_load(v, &[zero, zero], Some("arr.addr"))
.into_pointer_value(); .into_pointer_value();
if let ExprKind::Slice { lower, upper, step } = &slice.node { if let ExprKind::Slice { lower, upper, step } = &slice.node {
let one = int32.const_int(1, false); let one = int32.const_int(1, false);
let (start, end, step) = let Some((start, end, step)) =
handle_slice_indices(lower, upper, step, ctx, generator, v)?; handle_slice_indices(lower, upper, step, ctx, generator, v)? else {
return Ok(None)
};
let length = calculate_len_for_slice_range( let length = calculate_len_for_slice_range(
generator, generator,
ctx, ctx,
@ -1723,8 +1800,10 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
step, step,
); );
let res_array_ret = allocate_list(generator, ctx, ty, length, Some("ret")); let res_array_ret = allocate_list(generator, ctx, ty, length, Some("ret"));
let res_ind = let Some(res_ind) =
handle_slice_indices(&None, &None, &None, ctx, generator, res_array_ret)?; handle_slice_indices(&None, &None, &None, ctx, generator, res_array_ret)? else {
return Ok(None)
};
list_slice_assignment( list_slice_assignment(
generator, generator,
ctx, ctx,
@ -1739,11 +1818,11 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
let len = ctx let len = ctx
.build_gep_and_load(v, &[zero, int32.const_int(1, false)], Some("len")) .build_gep_and_load(v, &[zero, int32.const_int(1, false)], Some("len"))
.into_int_value(); .into_int_value();
let raw_index = generator let raw_index = if let Some(v) = generator.gen_expr(ctx, slice)? {
.gen_expr(ctx, slice)? v.to_basic_value_enum(ctx, generator, slice.custom.unwrap())?.into_int_value()
.unwrap() } else {
.to_basic_value_enum(ctx, generator, slice.custom.unwrap())? return Ok(None)
.into_int_value(); };
let raw_index = ctx.builder.build_int_s_extend( let raw_index = ctx.builder.build_int_s_extend(
raw_index, raw_index,
generator.get_size_type(ctx.ctx), generator.get_size_type(ctx.ctx),
@ -1786,15 +1865,12 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
} else { } else {
unreachable!("tuple subscript must be const int after type check"); unreachable!("tuple subscript must be const int after type check");
}; };
let v = generator match generator.gen_expr(ctx, value)? {
.gen_expr(ctx, value)? Some(ValueEnum::Dynamic(v)) => {
.unwrap();
match v {
ValueEnum::Dynamic(v) => {
let v = v.into_struct_value(); let v = v.into_struct_value();
ctx.builder.build_extract_value(v, index, "tup_elem").unwrap().into() ctx.builder.build_extract_value(v, index, "tup_elem").unwrap().into()
} }
ValueEnum::Static(v) => { Some(ValueEnum::Static(v)) => {
match v.get_tuple_element(index) { match v.get_tuple_element(index) {
Some(v) => v, Some(v) => v,
None => { None => {
@ -1805,12 +1881,19 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
} }
} }
} }
None => return Ok(None),
} }
} else { } else {
unreachable!("should not be other subscriptable types after type check"); unreachable!("should not be other subscriptable types after type check");
} }
}, },
ExprKind::ListComp { .. } => gen_comprehension(generator, ctx, expr)?.into(), ExprKind::ListComp { .. } => {
if let Some(v) = gen_comprehension(generator, ctx, expr)? {
v.into()
} else {
return Ok(None)
}
}
_ => unimplemented!(), _ => unimplemented!(),
})) }))
} }

View File

@ -98,7 +98,7 @@ pub trait CodeGenerator {
ctx: &mut CodeGenContext<'ctx, 'a>, ctx: &mut CodeGenContext<'ctx, 'a>,
pattern: &Expr<Option<Type>>, pattern: &Expr<Option<Type>>,
name: Option<&str>, name: Option<&str>,
) -> Result<PointerValue<'ctx>, String> ) -> Result<Option<PointerValue<'ctx>>, String>
where where
Self: Sized, Self: Sized,
{ {

View File

@ -158,33 +158,41 @@ pub fn handle_slice_indices<'a, 'ctx, G: CodeGenerator>(
ctx: &mut CodeGenContext<'ctx, 'a>, ctx: &mut CodeGenContext<'ctx, 'a>,
generator: &mut G, generator: &mut G,
list: PointerValue<'ctx>, list: PointerValue<'ctx>,
) -> Result<(IntValue<'ctx>, IntValue<'ctx>, IntValue<'ctx>), String> { ) -> Result<Option<(IntValue<'ctx>, IntValue<'ctx>, IntValue<'ctx>)>, String> {
let int32 = ctx.ctx.i32_type(); let int32 = ctx.ctx.i32_type();
let zero = int32.const_zero(); let zero = int32.const_zero();
let one = int32.const_int(1, false); let one = int32.const_int(1, false);
let length = ctx.build_gep_and_load(list, &[zero, one], Some("length")).into_int_value(); let length = ctx.build_gep_and_load(list, &[zero, one], Some("length")).into_int_value();
let length = ctx.builder.build_int_truncate_or_bit_cast(length, int32, "leni32"); let length = ctx.builder.build_int_truncate_or_bit_cast(length, int32, "leni32");
Ok(match (start, end, step) { Ok(Some(match (start, end, step) {
(s, e, None) => ( (s, e, None) => (
s.as_ref().map_or_else( if let Some(s) = s.as_ref() {
|| Ok(int32.const_zero()), match handle_slice_index_bound(s, ctx, generator, length)? {
|s| handle_slice_index_bound(s, ctx, generator, length), Some(v) => v,
)?, None => return Ok(None),
}
} else {
int32.const_zero()
},
{ {
let e = e.as_ref().map_or_else( let e = if let Some(s) = e.as_ref() {
|| Ok(length), match handle_slice_index_bound(s, ctx, generator, length)? {
|e| handle_slice_index_bound(e, ctx, generator, length), Some(v) => v,
)?; None => return Ok(None),
}
} else {
length
};
ctx.builder.build_int_sub(e, one, "final_end") ctx.builder.build_int_sub(e, one, "final_end")
}, },
one, one,
), ),
(s, e, Some(step)) => { (s, e, Some(step)) => {
let step = generator let step = if let Some(v) = generator.gen_expr(ctx, step)? {
.gen_expr(ctx, step)? v.to_basic_value_enum(ctx, generator, ctx.primitives.int32)?.into_int_value()
.unwrap() } else {
.to_basic_value_enum(ctx, generator, ctx.primitives.int32)? return Ok(None)
.into_int_value(); };
// assert step != 0, throw exception if not // assert step != 0, throw exception if not
let not_zero = ctx.builder.build_int_compare( let not_zero = ctx.builder.build_int_compare(
IntPredicate::NE, IntPredicate::NE,
@ -205,7 +213,9 @@ pub fn handle_slice_indices<'a, 'ctx, G: CodeGenerator>(
( (
match s { match s {
Some(s) => { Some(s) => {
let s = handle_slice_index_bound(s, ctx, generator, length)?; let Some(s) = handle_slice_index_bound(s, ctx, generator, length)? else {
return Ok(None)
};
ctx.builder ctx.builder
.build_select( .build_select(
ctx.builder.build_and( ctx.builder.build_and(
@ -228,7 +238,9 @@ pub fn handle_slice_indices<'a, 'ctx, G: CodeGenerator>(
}, },
match e { match e {
Some(e) => { Some(e) => {
let e = handle_slice_index_bound(e, ctx, generator, length)?; let Some(e) = handle_slice_index_bound(e, ctx, generator, length)? else {
return Ok(None)
};
ctx.builder ctx.builder
.build_select( .build_select(
neg, neg,
@ -243,7 +255,7 @@ pub fn handle_slice_indices<'a, 'ctx, G: CodeGenerator>(
step, step,
) )
} }
}) }))
} }
/// this function allows index out of range, since python /// this function allows index out of range, since python
@ -253,7 +265,7 @@ pub fn handle_slice_index_bound<'a, 'ctx, G: CodeGenerator>(
ctx: &mut CodeGenContext<'ctx, 'a>, ctx: &mut CodeGenContext<'ctx, 'a>,
generator: &mut G, generator: &mut G,
length: IntValue<'ctx>, length: IntValue<'ctx>,
) -> Result<IntValue<'ctx>, String> { ) -> Result<Option<IntValue<'ctx>>, String> {
const SYMBOL: &str = "__nac3_slice_index_bound"; const SYMBOL: &str = "__nac3_slice_index_bound";
let func = ctx.module.get_function(SYMBOL).unwrap_or_else(|| { let func = ctx.module.get_function(SYMBOL).unwrap_or_else(|| {
let i32_t = ctx.ctx.i32_type(); let i32_t = ctx.ctx.i32_type();
@ -261,14 +273,18 @@ pub fn handle_slice_index_bound<'a, 'ctx, G: CodeGenerator>(
ctx.module.add_function(SYMBOL, fn_t, None) ctx.module.add_function(SYMBOL, fn_t, None)
}); });
let i = generator.gen_expr(ctx, i)?.unwrap().to_basic_value_enum(ctx, generator, i.custom.unwrap())?; let i = if let Some(v) = generator.gen_expr(ctx, i)? {
Ok(ctx v.to_basic_value_enum(ctx, generator, i.custom.unwrap())?
} else {
return Ok(None)
};
Ok(Some(ctx
.builder .builder
.build_call(func, &[i.into(), length.into()], "bounded_ind") .build_call(func, &[i.into(), length.into()], "bounded_ind")
.try_as_basic_value() .try_as_basic_value()
.left() .left()
.unwrap() .unwrap()
.into_int_value()) .into_int_value()))
} }
/// This function handles 'end' **inclusively**. /// This function handles 'end' **inclusively**.

View File

@ -60,10 +60,10 @@ pub fn gen_store_target<'ctx, 'a, G: CodeGenerator>(
ctx: &mut CodeGenContext<'ctx, 'a>, ctx: &mut CodeGenContext<'ctx, 'a>,
pattern: &Expr<Option<Type>>, pattern: &Expr<Option<Type>>,
name: Option<&str>, name: Option<&str>,
) -> Result<PointerValue<'ctx>, String> { ) -> Result<Option<PointerValue<'ctx>>, String> {
// very similar to gen_expr, but we don't do an extra load at the end // very similar to gen_expr, but we don't do an extra load at the end
// and we flatten nested tuples // and we flatten nested tuples
Ok(match &pattern.node { Ok(Some(match &pattern.node {
ExprKind::Name { id, .. } => match ctx.var_assignment.get(id) { ExprKind::Name { id, .. } => match ctx.var_assignment.get(id) {
None => { None => {
let ptr_ty = ctx.get_llvm_type(generator, pattern.custom.unwrap()); let ptr_ty = ctx.get_llvm_type(generator, pattern.custom.unwrap());
@ -79,11 +79,11 @@ pub fn gen_store_target<'ctx, 'a, G: CodeGenerator>(
} }
ExprKind::Attribute { value, attr, .. } => { ExprKind::Attribute { value, attr, .. } => {
let index = ctx.get_attr_index(value.custom.unwrap(), *attr); let index = ctx.get_attr_index(value.custom.unwrap(), *attr);
let val = generator.gen_expr(ctx, value)?.unwrap().to_basic_value_enum( let val = if let Some(v) = generator.gen_expr(ctx, value)? {
ctx, v.to_basic_value_enum(ctx, generator, value.custom.unwrap())?
generator, } else {
value.custom.unwrap(), return Ok(None)
)?; };
let ptr = if let BasicValueEnum::PointerValue(v) = val { let ptr = if let BasicValueEnum::PointerValue(v) = val {
v v
} else { } else {
@ -107,19 +107,19 @@ pub fn gen_store_target<'ctx, 'a, G: CodeGenerator>(
)); ));
let i32_type = ctx.ctx.i32_type(); let i32_type = ctx.ctx.i32_type();
let zero = i32_type.const_zero(); let zero = i32_type.const_zero();
let v = generator let v = if let Some(v) = generator.gen_expr(ctx, value)? {
.gen_expr(ctx, value)? v.to_basic_value_enum(ctx, generator, value.custom.unwrap())?.into_pointer_value()
.unwrap() } else {
.to_basic_value_enum(ctx, generator, value.custom.unwrap())? return Ok(None)
.into_pointer_value(); };
let len = ctx let len = ctx
.build_gep_and_load(v, &[zero, i32_type.const_int(1, false)], Some("len")) .build_gep_and_load(v, &[zero, i32_type.const_int(1, false)], Some("len"))
.into_int_value(); .into_int_value();
let raw_index = generator let raw_index = if let Some(v) = generator.gen_expr(ctx, slice)? {
.gen_expr(ctx, slice)? v.to_basic_value_enum(ctx, generator, slice.custom.unwrap())?.into_int_value()
.unwrap() } else {
.to_basic_value_enum(ctx, generator, slice.custom.unwrap())? return Ok(None)
.into_int_value(); };
let raw_index = ctx.builder.build_int_s_extend( let raw_index = ctx.builder.build_int_s_extend(
raw_index, raw_index,
generator.get_size_type(ctx.ctx), generator.get_size_type(ctx.ctx),
@ -161,7 +161,7 @@ pub fn gen_store_target<'ctx, 'a, G: CodeGenerator>(
} }
} }
_ => unreachable!(), _ => unreachable!(),
}) }))
} }
/// See [CodeGenerator::gen_assign]. /// See [CodeGenerator::gen_assign].
@ -196,8 +196,10 @@ pub fn gen_assign<'ctx, 'a, G: CodeGenerator>(
.unwrap() .unwrap()
.to_basic_value_enum(ctx, generator, ls.custom.unwrap())? .to_basic_value_enum(ctx, generator, ls.custom.unwrap())?
.into_pointer_value(); .into_pointer_value();
let (start, end, step) = let Some((start, end, step)) =
handle_slice_indices(lower, upper, step, ctx, generator, ls)?; handle_slice_indices(lower, upper, step, ctx, generator, ls)? else {
return Ok(())
};
let value = value let value = value
.to_basic_value_enum(ctx, generator, target.custom.unwrap())? .to_basic_value_enum(ctx, generator, target.custom.unwrap())?
.into_pointer_value(); .into_pointer_value();
@ -207,7 +209,9 @@ pub fn gen_assign<'ctx, 'a, G: CodeGenerator>(
} else { } else {
unreachable!() unreachable!()
}; };
let src_ind = handle_slice_indices(&None, &None, &None, ctx, generator, value)?; let Some(src_ind) = handle_slice_indices(&None, &None, &None, ctx, generator, value)? else {
return Ok(())
};
list_slice_assignment(generator, ctx, ty, ls, (start, end, step), value, src_ind) list_slice_assignment(generator, ctx, ty, ls, (start, end, step), value, src_ind)
} else { } else {
unreachable!() unreachable!()
@ -219,7 +223,9 @@ pub fn gen_assign<'ctx, 'a, G: CodeGenerator>(
} else { } else {
String::from("target.addr") String::from("target.addr")
}; };
let ptr = generator.gen_store_target(ctx, target, Some(name.as_str()))?; let Some(ptr) = generator.gen_store_target(ctx, target, Some(name.as_str()))? else {
return Ok(())
};
if let ExprKind::Name { id, .. } = &target.node { if let ExprKind::Name { id, .. } = &target.node {
let (_, static_value, counter) = ctx.var_assignment.get_mut(id).unwrap(); let (_, static_value, counter) = ctx.var_assignment.get_mut(id).unwrap();
@ -270,17 +276,23 @@ pub fn gen_for<'ctx, 'a, G: CodeGenerator>(
// store loop bb information and restore it later // store loop bb information and restore it later
let loop_bb = ctx.loop_target.replace((incr_bb, cont_bb)); let loop_bb = ctx.loop_target.replace((incr_bb, cont_bb));
let iter_val = generator.gen_expr(ctx, iter)?.unwrap().to_basic_value_enum( let iter_val = if let Some(v) = generator.gen_expr(ctx, iter)? {
ctx, v.to_basic_value_enum(
generator, ctx,
iter.custom.unwrap(), generator,
)?; iter.custom.unwrap(),
)?
} else {
return Ok(())
};
if is_iterable_range_expr { if is_iterable_range_expr {
let iter_val = iter_val.into_pointer_value(); let iter_val = iter_val.into_pointer_value();
// Internal variable for loop; Cannot be assigned // Internal variable for loop; Cannot be assigned
let i = generator.gen_var_alloc(ctx, int32.into(), Some("for.i.addr"))?; let i = generator.gen_var_alloc(ctx, int32.into(), Some("for.i.addr"))?;
// Variable declared in "target" expression of the loop; Can be reassigned *or* shadowed // Variable declared in "target" expression of the loop; Can be reassigned *or* shadowed
let target_i = generator.gen_store_target(ctx, target, Some("for.target.addr"))?; let Some(target_i) = generator.gen_store_target(ctx, target, Some("for.target.addr"))? else {
unreachable!()
};
let (start, stop, step) = destructure_range(ctx, iter_val); let (start, stop, step) = destructure_range(ctx, iter_val);
ctx.builder.build_store(i, start); ctx.builder.build_store(i, start);
@ -412,11 +424,16 @@ pub fn gen_while<'ctx, 'a, G: CodeGenerator>(
let loop_bb = ctx.loop_target.replace((test_bb, cont_bb)); let loop_bb = ctx.loop_target.replace((test_bb, cont_bb));
ctx.builder.build_unconditional_branch(test_bb); ctx.builder.build_unconditional_branch(test_bb);
ctx.builder.position_at_end(test_bb); ctx.builder.position_at_end(test_bb);
let test = generator.gen_expr(ctx, test)?.unwrap().to_basic_value_enum( let test = if let Some(v) = generator.gen_expr(ctx, test)? {
ctx, v.to_basic_value_enum(ctx, generator, test.custom.unwrap())?
generator, } else {
test.custom.unwrap(), for bb in [body_bb, cont_bb] {
)?; ctx.builder.position_at_end(bb);
ctx.builder.build_unreachable();
}
return Ok(())
};
if let BasicValueEnum::IntValue(test) = test { if let BasicValueEnum::IntValue(test) = test {
ctx.builder.build_conditional_branch(generator.bool_to_i1(ctx, test), body_bb, orelse_bb); ctx.builder.build_conditional_branch(generator.bool_to_i1(ctx, test), body_bb, orelse_bb);
} else { } else {
@ -478,13 +495,11 @@ pub fn gen_if<'ctx, 'a, G: CodeGenerator>(
}; };
ctx.builder.build_unconditional_branch(test_bb); ctx.builder.build_unconditional_branch(test_bb);
ctx.builder.position_at_end(test_bb); ctx.builder.position_at_end(test_bb);
let test = generator.gen_expr(ctx, test)? let test = generator
.unwrap() .gen_expr(ctx, test)
.to_basic_value_enum(ctx, generator, test.custom.unwrap())?; .and_then(|v| v.map(|v| v.to_basic_value_enum(ctx, generator, test.custom.unwrap())).transpose())?;
if let BasicValueEnum::IntValue(test) = test { if let Some(BasicValueEnum::IntValue(test)) = test {
ctx.builder.build_conditional_branch(generator.bool_to_i1(ctx, test), body_bb, orelse_bb); ctx.builder.build_conditional_branch(generator.bool_to_i1(ctx, test), body_bb, orelse_bb);
} else {
unreachable!()
}; };
ctx.builder.position_at_end(body_bb); ctx.builder.position_at_end(body_bb);
generator.gen_block(ctx, body.iter())?; generator.gen_block(ctx, body.iter())?;
@ -604,7 +619,7 @@ pub fn exn_constructor<'ctx, 'a>(
let msg = if !args.is_empty() { let msg = if !args.is_empty() {
args.remove(0).1.to_basic_value_enum(ctx, generator, ctx.primitives.str)? args.remove(0).1.to_basic_value_enum(ctx, generator, ctx.primitives.str)?
} else { } else {
empty_string empty_string.unwrap()
}; };
ctx.builder.build_store(ptr, msg); ctx.builder.build_store(ptr, msg);
for i in [6, 7, 8].iter() { for i in [6, 7, 8].iter() {
@ -627,7 +642,7 @@ pub fn exn_constructor<'ctx, 'a>(
&[zero, int32.const_int(*i, false)], &[zero, int32.const_int(*i, false)],
"exn.str", "exn.str",
); );
ctx.builder.build_store(ptr, empty_string); ctx.builder.build_store(ptr, empty_string.unwrap());
} }
// set ints to zero // set ints to zero
for i in [2, 3].iter() { for i in [2, 3].iter() {
@ -1036,14 +1051,17 @@ pub fn gen_return<'ctx, 'a, G: CodeGenerator>(
value: &Option<Box<Expr<Option<Type>>>>, value: &Option<Box<Expr<Option<Type>>>>,
) -> Result<(), String> { ) -> Result<(), String> {
let func = ctx.builder.get_insert_block().and_then(|bb| bb.get_parent()).unwrap(); let func = ctx.builder.get_insert_block().and_then(|bb| bb.get_parent()).unwrap();
let value = value let value = if let Some(v_expr) = value.as_ref() {
.as_ref() if let Some(v) = generator.gen_expr(ctx, v_expr).transpose() {
.map(|v_expr| { Some(
generator.gen_expr(ctx, v_expr).and_then(|v| { v.and_then(|v| v.to_basic_value_enum(ctx, generator, v_expr.custom.unwrap()))?
v.unwrap().to_basic_value_enum(ctx, generator, v_expr.custom.unwrap()) )
}) } else {
}) return Ok(())
.transpose()?; }
} else {
None
};
if let Some(return_target) = ctx.return_target { if let Some(return_target) = ctx.return_target {
if let Some(value) = value { if let Some(value) = value {
ctx.builder.build_store(ctx.return_buffer.unwrap(), value); ctx.builder.build_store(ctx.return_buffer.unwrap(), value);
@ -1105,12 +1123,16 @@ pub fn gen_stmt<'ctx, 'a, G: CodeGenerator>(
} }
StmtKind::AnnAssign { target, value, .. } => { StmtKind::AnnAssign { target, value, .. } => {
if let Some(value) = value { if let Some(value) = value {
let value = generator.gen_expr(ctx, value)?.unwrap(); let Some(value) = generator.gen_expr(ctx, value)? else {
return Ok(())
};
generator.gen_assign(ctx, target, value)?; generator.gen_assign(ctx, target, value)?;
} }
} }
StmtKind::Assign { targets, value, .. } => { StmtKind::Assign { targets, value, .. } => {
let value = generator.gen_expr(ctx, value)?.unwrap(); let Some(value) = generator.gen_expr(ctx, value)? else {
return Ok(())
};
for target in targets.iter() { for target in targets.iter() {
generator.gen_assign(ctx, target, value.clone())?; generator.gen_assign(ctx, target, value.clone())?;
} }
@ -1132,28 +1154,28 @@ pub fn gen_stmt<'ctx, 'a, G: CodeGenerator>(
StmtKind::Try { .. } => gen_try(generator, ctx, stmt)?, StmtKind::Try { .. } => gen_try(generator, ctx, stmt)?,
StmtKind::Raise { exc, .. } => { StmtKind::Raise { exc, .. } => {
if let Some(exc) = exc { if let Some(exc) = exc {
let exc = generator.gen_expr(ctx, exc)?.unwrap().to_basic_value_enum( let exc = if let Some(v) = generator.gen_expr(ctx, exc)? {
ctx, v.to_basic_value_enum(ctx, generator, exc.custom.unwrap())?
generator, } else {
exc.custom.unwrap(), return Ok(())
)?; };
gen_raise(generator, ctx, Some(&exc), stmt.location); gen_raise(generator, ctx, Some(&exc), stmt.location);
} else { } else {
gen_raise(generator, ctx, None, stmt.location); gen_raise(generator, ctx, None, stmt.location);
} }
} }
StmtKind::Assert { test, msg, .. } => { StmtKind::Assert { test, msg, .. } => {
let test = generator.gen_expr(ctx, test)?.unwrap().to_basic_value_enum( let test = if let Some(v) = generator.gen_expr(ctx, test)? {
ctx, v.to_basic_value_enum(ctx, generator, test.custom.unwrap())?
generator, } else {
test.custom.unwrap(), return Ok(())
)?; };
let err_msg = match msg { let err_msg = match msg {
Some(msg) => generator.gen_expr(ctx, msg)?.unwrap().to_basic_value_enum( Some(msg) => if let Some(v) = generator.gen_expr(ctx, msg)? {
ctx, v.to_basic_value_enum(ctx, generator, msg.custom.unwrap())?
generator, } else {
msg.custom.unwrap(), return Ok(())
)?, },
None => ctx.gen_string(generator, ""), None => ctx.gen_string(generator, ""),
}; };
ctx.make_assert_impl( ctx.make_assert_impl(

View File

@ -1,11 +1,12 @@
use std::fmt::Debug; use std::fmt::Debug;
use std::sync::Arc; use std::sync::Arc;
use std::{collections::HashMap, fmt::Display}; use std::{collections::HashMap, fmt::Display};
use std::rc::Rc;
use crate::typecheck::typedef::TypeEnum; use crate::typecheck::typedef::TypeEnum;
use crate::{ use crate::{
codegen::CodeGenContext, codegen::CodeGenContext,
toplevel::{DefinitionId, TopLevelDef}, toplevel::{DefinitionId, TopLevelDef, type_annotation::TypeAnnotation},
}; };
use crate::{ use crate::{
codegen::CodeGenerator, codegen::CodeGenerator,
@ -16,7 +17,7 @@ use crate::{
}; };
use inkwell::values::{BasicValueEnum, FloatValue, IntValue, PointerValue, StructValue}; use inkwell::values::{BasicValueEnum, FloatValue, IntValue, PointerValue, StructValue};
use itertools::{chain, izip}; use itertools::{chain, izip};
use nac3parser::ast::{Expr, Location, StrRef}; use nac3parser::ast::{Constant, Expr, Location, StrRef};
use parking_lot::RwLock; use parking_lot::RwLock;
#[derive(Clone, PartialEq, Debug)] #[derive(Clone, PartialEq, Debug)]
@ -33,6 +34,147 @@ pub enum SymbolValue {
OptionNone, OptionNone,
} }
impl SymbolValue {
/// Creates a [SymbolValue] from a [Constant].
///
/// * `constant` - The constant to create the value from.
/// * `expected_ty` - The expected type of the [SymbolValue].
pub fn from_constant(
constant: &Constant,
expected_ty: Type,
primitives: &PrimitiveStore,
unifier: &mut Unifier
) -> Result<Self, String> {
match constant {
Constant::None => {
if unifier.unioned(expected_ty, primitives.option) {
Ok(SymbolValue::OptionNone)
} else {
Err(format!("Expected {:?}, but got Option", expected_ty))
}
}
Constant::Bool(b) => {
if unifier.unioned(expected_ty, primitives.bool) {
Ok(SymbolValue::Bool(*b))
} else {
Err(format!("Expected {:?}, but got bool", expected_ty))
}
}
Constant::Str(s) => {
if unifier.unioned(expected_ty, primitives.str) {
Ok(SymbolValue::Str(s.to_string()))
} else {
Err(format!("Expected {:?}, but got str", expected_ty))
}
},
Constant::Int(i) => {
if unifier.unioned(expected_ty, primitives.int32) {
i32::try_from(*i)
.map(|val| SymbolValue::I32(val))
.map_err(|e| e.to_string())
} else if unifier.unioned(expected_ty, primitives.int64) {
i64::try_from(*i)
.map(|val| SymbolValue::I64(val))
.map_err(|e| e.to_string())
} else if unifier.unioned(expected_ty, primitives.uint32) {
u32::try_from(*i)
.map(|val| SymbolValue::U32(val))
.map_err(|e| e.to_string())
} else if unifier.unioned(expected_ty, primitives.uint64) {
u64::try_from(*i)
.map(|val| SymbolValue::U64(val))
.map_err(|e| e.to_string())
} else {
Err(format!("Expected {}, but got int", unifier.stringify(expected_ty)))
}
}
Constant::Tuple(t) => {
let expected_ty = unifier.get_ty(expected_ty);
let TypeEnum::TTuple { ty } = expected_ty.as_ref() else {
return Err(format!("Expected {:?}, but got Tuple", expected_ty.get_type_name()))
};
assert_eq!(ty.len(), t.len());
let elems = t.into_iter()
.zip(ty)
.map(|(constant, ty)| Self::from_constant(constant, *ty, primitives, unifier))
.collect::<Result<Vec<SymbolValue>, _>>()?;
Ok(SymbolValue::Tuple(elems))
}
Constant::Float(f) => {
if unifier.unioned(expected_ty, primitives.float) {
Ok(SymbolValue::Double(*f))
} else {
Err(format!("Expected {:?}, but got float", expected_ty))
}
},
_ => Err(format!("Unsupported value type {:?}", constant)),
}
}
/// Returns the [Type] representing the data type of this value.
pub fn get_type(&self, primitives: &PrimitiveStore, unifier: &mut Unifier) -> Type {
match self {
SymbolValue::I32(_) => primitives.int32,
SymbolValue::I64(_) => primitives.int64,
SymbolValue::U32(_) => primitives.uint32,
SymbolValue::U64(_) => primitives.uint64,
SymbolValue::Str(_) => primitives.str,
SymbolValue::Double(_) => primitives.float,
SymbolValue::Bool(_) => primitives.bool,
SymbolValue::Tuple(vs) => {
let vs_tys = vs
.iter()
.map(|v| v.get_type(primitives, unifier))
.collect::<Vec<_>>();
unifier.add_ty(TypeEnum::TTuple {
ty: vs_tys,
})
}
SymbolValue::OptionSome(_) => primitives.option,
SymbolValue::OptionNone => primitives.option,
}
}
/// Returns the [TypeAnnotation] representing the data type of this value.
pub fn get_type_annotation(&self, primitives: &PrimitiveStore, unifier: &mut Unifier) -> TypeAnnotation {
match self {
SymbolValue::Bool(..) => TypeAnnotation::Primitive(primitives.bool),
SymbolValue::Double(..) => TypeAnnotation::Primitive(primitives.float),
SymbolValue::I32(..) => TypeAnnotation::Primitive(primitives.int32),
SymbolValue::I64(..) => TypeAnnotation::Primitive(primitives.int64),
SymbolValue::U32(..) => TypeAnnotation::Primitive(primitives.uint32),
SymbolValue::U64(..) => TypeAnnotation::Primitive(primitives.uint64),
SymbolValue::Str(..) => TypeAnnotation::Primitive(primitives.str),
SymbolValue::Tuple(vs) => {
let vs_tys = vs
.iter()
.map(|v| v.get_type_annotation(primitives, unifier))
.collect::<Vec<_>>();
TypeAnnotation::Tuple(vs_tys)
}
SymbolValue::OptionNone => TypeAnnotation::CustomClass {
id: primitives.option.get_obj_id(unifier),
params: Default::default(),
},
SymbolValue::OptionSome(v) => {
let ty = v.get_type_annotation(primitives, unifier);
TypeAnnotation::CustomClass {
id: primitives.option.get_obj_id(unifier),
params: vec![ty],
}
}
}
}
/// Returns the [TypeEnum] representing the data type of this value.
pub fn get_type_enum(&self, primitives: &PrimitiveStore, unifier: &mut Unifier) -> Rc<TypeEnum> {
let ty = self.get_type(primitives, unifier);
unifier.get_ty(ty)
}
}
impl Display for SymbolValue { impl Display for SymbolValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {

View File

@ -22,7 +22,7 @@ use inkwell::{
IntPredicate IntPredicate
}; };
type BuiltinInfo = (Vec<(Arc<RwLock<TopLevelDef>>, Option<Stmt>)>, &'static [&'static str]); type BuiltinInfo = Vec<(Arc<RwLock<TopLevelDef>>, Option<Stmt>)>;
pub fn get_exn_constructor( pub fn get_exn_constructor(
name: &str, name: &str,
@ -881,6 +881,33 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
Ok(Some(val_toint.into())) Ok(Some(val_toint.into()))
}), }),
), ),
create_fn_by_codegen(
primitives,
&var_map,
"np_round",
float,
&[(float, "n")],
Box::new(|ctx, _, _, args, generator| {
let llvm_f64 = ctx.ctx.f64_type();
let arg = args[0].1.clone()
.to_basic_value_enum(ctx, generator, ctx.primitives.float)?;
let intrinsic_fn = ctx.module.get_function("llvm.roundeven.f64").unwrap_or_else(|| {
let fn_type = llvm_f64.fn_type(&[llvm_f64.into()], false);
ctx.module.add_function("llvm.roundeven.f64", fn_type, None)
});
let val = ctx
.builder
.build_call(intrinsic_fn, &[arg.into()], "")
.try_as_basic_value()
.left()
.unwrap();
Ok(Some(val.into()))
}),
),
Arc::new(RwLock::new(TopLevelDef::Function { Arc::new(RwLock::new(TopLevelDef::Function {
name: "range".into(), name: "range".into(),
simple_name: "range".into(), simple_name: "range".into(),
@ -1123,6 +1150,33 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
Ok(Some(val_toint.into())) Ok(Some(val_toint.into()))
}), }),
), ),
create_fn_by_codegen(
primitives,
&var_map,
"np_floor",
float,
&[(float, "n")],
Box::new(|ctx, _, _, args, generator| {
let llvm_f64 = ctx.ctx.f64_type();
let arg = args[0].1.clone()
.to_basic_value_enum(ctx, generator, ctx.primitives.float)?;
let intrinsic_fn = ctx.module.get_function("llvm.floor.f64").unwrap_or_else(|| {
let fn_type = llvm_f64.fn_type(&[llvm_f64.into()], false);
ctx.module.add_function("llvm.floor.f64", fn_type, None)
});
let val = ctx
.builder
.build_call(intrinsic_fn, &[arg.into()], "")
.try_as_basic_value()
.left()
.unwrap();
Ok(Some(val.into()))
}),
),
create_fn_by_codegen( create_fn_by_codegen(
primitives, primitives,
&var_map, &var_map,
@ -1183,6 +1237,33 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
Ok(Some(val_toint.into())) Ok(Some(val_toint.into()))
}), }),
), ),
create_fn_by_codegen(
primitives,
&var_map,
"np_ceil",
float,
&[(float, "n")],
Box::new(|ctx, _, _, args, generator| {
let llvm_f64 = ctx.ctx.f64_type();
let arg = args[0].1.clone()
.to_basic_value_enum(ctx, generator, ctx.primitives.float)?;
let intrinsic_fn = ctx.module.get_function("llvm.ceil.f64").unwrap_or_else(|| {
let fn_type = llvm_f64.fn_type(&[llvm_f64.into()], false);
ctx.module.add_function("llvm.ceil.f64", fn_type, None)
});
let val = ctx
.builder
.build_call(intrinsic_fn, &[arg.into()], "")
.try_as_basic_value()
.left()
.unwrap();
Ok(Some(val.into()))
}),
),
Arc::new(RwLock::new({ Arc::new(RwLock::new({
let list_var = primitives.1.get_fresh_var(Some("L".into()), None); let list_var = primitives.1.get_fresh_var(Some("L".into()), None);
let list = primitives.1.add_ty(TypeEnum::TList { ty: list_var.0 }); let list = primitives.1.add_ty(TypeEnum::TList { ty: list_var.0 });
@ -1431,7 +1512,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_codegen( create_fn_by_codegen(
primitives, primitives,
&var_map, &var_map,
"isnan", "np_isnan",
boolean, boolean,
&[(float, "x")], &[(float, "x")],
Box::new(|ctx, _, fun, args, generator| { Box::new(|ctx, _, fun, args, generator| {
@ -1451,7 +1532,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_codegen( create_fn_by_codegen(
primitives, primitives,
&var_map, &var_map,
"isinf", "np_isinf",
boolean, boolean,
&[(float, "x")], &[(float, "x")],
Box::new(|ctx, _, fun, args, generator| { Box::new(|ctx, _, fun, args, generator| {
@ -1471,7 +1552,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_intrinsic( create_fn_by_intrinsic(
primitives, primitives,
&var_map, &var_map,
"sin", "np_sin",
float, float,
&[(float, "x")], &[(float, "x")],
"llvm.sin.f64", "llvm.sin.f64",
@ -1479,7 +1560,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_intrinsic( create_fn_by_intrinsic(
primitives, primitives,
&var_map, &var_map,
"cos", "np_cos",
float, float,
&[(float, "x")], &[(float, "x")],
"llvm.cos.f64", "llvm.cos.f64",
@ -1487,7 +1568,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_intrinsic( create_fn_by_intrinsic(
primitives, primitives,
&var_map, &var_map,
"exp", "np_exp",
float, float,
&[(float, "x")], &[(float, "x")],
"llvm.exp.f64", "llvm.exp.f64",
@ -1495,7 +1576,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_intrinsic( create_fn_by_intrinsic(
primitives, primitives,
&var_map, &var_map,
"exp2", "np_exp2",
float, float,
&[(float, "x")], &[(float, "x")],
"llvm.exp2.f64", "llvm.exp2.f64",
@ -1503,7 +1584,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_intrinsic( create_fn_by_intrinsic(
primitives, primitives,
&var_map, &var_map,
"log", "np_log",
float, float,
&[(float, "x")], &[(float, "x")],
"llvm.log.f64", "llvm.log.f64",
@ -1511,7 +1592,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_intrinsic( create_fn_by_intrinsic(
primitives, primitives,
&var_map, &var_map,
"log10", "np_log10",
float, float,
&[(float, "x")], &[(float, "x")],
"llvm.log10.f64", "llvm.log10.f64",
@ -1519,7 +1600,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_intrinsic( create_fn_by_intrinsic(
primitives, primitives,
&var_map, &var_map,
"log2", "np_log2",
float, float,
&[(float, "x")], &[(float, "x")],
"llvm.log2.f64", "llvm.log2.f64",
@ -1527,7 +1608,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_intrinsic( create_fn_by_intrinsic(
primitives, primitives,
&var_map, &var_map,
"fabs", "np_fabs",
float, float,
&[(float, "x")], &[(float, "x")],
"llvm.fabs.f64", "llvm.fabs.f64",
@ -1535,7 +1616,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_intrinsic( create_fn_by_intrinsic(
primitives, primitives,
&var_map, &var_map,
"sqrt", "np_sqrt",
float, float,
&[(float, "x")], &[(float, "x")],
"llvm.sqrt.f64", "llvm.sqrt.f64",
@ -1543,7 +1624,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_intrinsic( create_fn_by_intrinsic(
primitives, primitives,
&var_map, &var_map,
"rint", "np_rint",
float, float,
&[(float, "x")], &[(float, "x")],
"llvm.roundeven.f64", "llvm.roundeven.f64",
@ -1551,7 +1632,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern( create_fn_by_extern(
primitives, primitives,
&var_map, &var_map,
"tan", "np_tan",
float, float,
&[(float, "x")], &[(float, "x")],
"tan", "tan",
@ -1560,7 +1641,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern( create_fn_by_extern(
primitives, primitives,
&var_map, &var_map,
"arcsin", "np_arcsin",
float, float,
&[(float, "x")], &[(float, "x")],
"asin", "asin",
@ -1569,7 +1650,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern( create_fn_by_extern(
primitives, primitives,
&var_map, &var_map,
"arccos", "np_arccos",
float, float,
&[(float, "x")], &[(float, "x")],
"acos", "acos",
@ -1578,7 +1659,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern( create_fn_by_extern(
primitives, primitives,
&var_map, &var_map,
"arctan", "np_arctan",
float, float,
&[(float, "x")], &[(float, "x")],
"atan", "atan",
@ -1587,7 +1668,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern( create_fn_by_extern(
primitives, primitives,
&var_map, &var_map,
"sinh", "np_sinh",
float, float,
&[(float, "x")], &[(float, "x")],
"sinh", "sinh",
@ -1596,7 +1677,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern( create_fn_by_extern(
primitives, primitives,
&var_map, &var_map,
"cosh", "np_cosh",
float, float,
&[(float, "x")], &[(float, "x")],
"cosh", "cosh",
@ -1605,7 +1686,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern( create_fn_by_extern(
primitives, primitives,
&var_map, &var_map,
"tanh", "np_tanh",
float, float,
&[(float, "x")], &[(float, "x")],
"tanh", "tanh",
@ -1614,7 +1695,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern( create_fn_by_extern(
primitives, primitives,
&var_map, &var_map,
"arcsinh", "np_arcsinh",
float, float,
&[(float, "x")], &[(float, "x")],
"asinh", "asinh",
@ -1623,7 +1704,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern( create_fn_by_extern(
primitives, primitives,
&var_map, &var_map,
"arccosh", "np_arccosh",
float, float,
&[(float, "x")], &[(float, "x")],
"acosh", "acosh",
@ -1632,7 +1713,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern( create_fn_by_extern(
primitives, primitives,
&var_map, &var_map,
"arctanh", "np_arctanh",
float, float,
&[(float, "x")], &[(float, "x")],
"atanh", "atanh",
@ -1641,7 +1722,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern( create_fn_by_extern(
primitives, primitives,
&var_map, &var_map,
"expm1", "np_expm1",
float, float,
&[(float, "x")], &[(float, "x")],
"expm1", "expm1",
@ -1650,7 +1731,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern( create_fn_by_extern(
primitives, primitives,
&var_map, &var_map,
"cbrt", "np_cbrt",
float, float,
&[(float, "x")], &[(float, "x")],
"cbrt", "cbrt",
@ -1659,7 +1740,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern( create_fn_by_extern(
primitives, primitives,
&var_map, &var_map,
"erf", "sp_spec_erf",
float, float,
&[(float, "z")], &[(float, "z")],
"erf", "erf",
@ -1668,7 +1749,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern( create_fn_by_extern(
primitives, primitives,
&var_map, &var_map,
"erfc", "sp_spec_erfc",
float, float,
&[(float, "x")], &[(float, "x")],
"erfc", "erfc",
@ -1677,7 +1758,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_codegen( create_fn_by_codegen(
primitives, primitives,
&var_map, &var_map,
"gamma", "sp_spec_gamma",
float, float,
&[(float, "z")], &[(float, "z")],
Box::new(|ctx, _, fun, args, generator| { Box::new(|ctx, _, fun, args, generator| {
@ -1695,7 +1776,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_codegen( create_fn_by_codegen(
primitives, primitives,
&var_map, &var_map,
"gammaln", "sp_spec_gammaln",
float, float,
&[(float, "x")], &[(float, "x")],
Box::new(|ctx, _, fun, args, generator| { Box::new(|ctx, _, fun, args, generator| {
@ -1713,7 +1794,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_codegen( create_fn_by_codegen(
primitives, primitives,
&var_map, &var_map,
"j0", "sp_spec_j0",
float, float,
&[(float, "x")], &[(float, "x")],
Box::new(|ctx, _, fun, args, generator| { Box::new(|ctx, _, fun, args, generator| {
@ -1731,7 +1812,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern( create_fn_by_extern(
primitives, primitives,
&var_map, &var_map,
"j1", "sp_spec_j1",
float, float,
&[(float, "x")], &[(float, "x")],
"j1", "j1",
@ -1741,7 +1822,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern( create_fn_by_extern(
primitives, primitives,
&var_map, &var_map,
"arctan2", "np_arctan2",
float, float,
&[(float, "x1"), (float, "x2")], &[(float, "x1"), (float, "x2")],
"atan2", "atan2",
@ -1750,7 +1831,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_intrinsic( create_fn_by_intrinsic(
primitives, primitives,
&var_map, &var_map,
"copysign", "np_copysign",
float, float,
&[(float, "x1"), (float, "x2")], &[(float, "x1"), (float, "x2")],
"llvm.copysign.f64", "llvm.copysign.f64",
@ -1758,7 +1839,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_intrinsic( create_fn_by_intrinsic(
primitives, primitives,
&var_map, &var_map,
"fmax", "np_fmax",
float, float,
&[(float, "x1"), (float, "x2")], &[(float, "x1"), (float, "x2")],
"llvm.maxnum.f64", "llvm.maxnum.f64",
@ -1766,7 +1847,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_intrinsic( create_fn_by_intrinsic(
primitives, primitives,
&var_map, &var_map,
"fmin", "np_fmin",
float, float,
&[(float, "x1"), (float, "x2")], &[(float, "x1"), (float, "x2")],
"llvm.minnum.f64", "llvm.minnum.f64",
@ -1774,7 +1855,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern( create_fn_by_extern(
primitives, primitives,
&var_map, &var_map,
"ldexp", "np_ldexp",
float, float,
&[(float, "x1"), (int32, "x2")], &[(float, "x1"), (int32, "x2")],
"ldexp", "ldexp",
@ -1783,7 +1864,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern( create_fn_by_extern(
primitives, primitives,
&var_map, &var_map,
"hypot", "np_hypot",
float, float,
&[(float, "x1"), (float, "x2")], &[(float, "x1"), (float, "x2")],
"hypot", "hypot",
@ -1792,7 +1873,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern( create_fn_by_extern(
primitives, primitives,
&var_map, &var_map,
"nextafter", "np_nextafter",
float, float,
&[(float, "x1"), (float, "x2")], &[(float, "x1"), (float, "x2")],
"nextafter", "nextafter",
@ -1825,65 +1906,6 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
let ast_list: Vec<Option<ast::Stmt<()>>> = let ast_list: Vec<Option<ast::Stmt<()>>> =
(0..top_level_def_list.len()).map(|_| None).collect(); (0..top_level_def_list.len()).map(|_| None).collect();
(
izip!(top_level_def_list, ast_list).collect_vec(), izip!(top_level_def_list, ast_list).collect_vec()
&[
"int32",
"int64",
"uint32",
"uint64",
"float",
"round",
"round64",
"range",
"str",
"bool",
"floor",
"floor64",
"ceil",
"ceil64",
"len",
"min",
"max",
"abs",
"isnan",
"isinf",
"sin",
"cos",
"exp",
"exp2",
"log",
"log10",
"log2",
"fabs",
"sqrt",
"rint",
"tan",
"arcsin",
"arccos",
"arctan",
"sinh",
"cosh",
"tanh",
"arcsinh",
"arccosh",
"arctanh",
"expm1",
"cbrt",
"erf",
"erfc",
"gamma",
"gammaln",
"j0",
"j1",
"arctan2",
"copysign",
"fmax",
"fmin",
"ldexp",
"hypot",
"nextafter",
"Some",
],
)
} }

View File

@ -53,7 +53,7 @@ impl TopLevelComposer {
core_config: ComposerConfig, core_config: ComposerConfig,
) -> (Self, HashMap<StrRef, DefinitionId>, HashMap<StrRef, Type>) { ) -> (Self, HashMap<StrRef, DefinitionId>, HashMap<StrRef, Type>) {
let mut primitives = Self::make_primitives(); let mut primitives = Self::make_primitives();
let (mut definition_ast_list, builtin_name_list) = builtins::get_builtins(&mut primitives); let mut definition_ast_list = builtins::get_builtins(&mut primitives);
let primitives_ty = primitives.0; let primitives_ty = primitives.0;
let mut unifier = primitives.1; let mut unifier = primitives.1;
let mut keyword_list: HashSet<StrRef> = HashSet::from_iter(vec![ let mut keyword_list: HashSet<StrRef> = HashSet::from_iter(vec![
@ -83,12 +83,26 @@ impl TopLevelComposer {
let mut builtin_id: HashMap<StrRef, DefinitionId> = Default::default(); let mut builtin_id: HashMap<StrRef, DefinitionId> = Default::default();
let mut builtin_ty: HashMap<StrRef, Type> = Default::default(); let mut builtin_ty: HashMap<StrRef, Type> = Default::default();
for (id, name) in builtin_name_list.iter().rev().enumerate() { let builtin_name_list = definition_ast_list.iter()
.map(|def_ast| match *def_ast.0.read() {
TopLevelDef::Class { name, .. } => name.to_string(),
TopLevelDef::Function { simple_name, .. } => simple_name.to_string(),
})
.collect_vec();
for (id, name) in builtin_name_list.iter().enumerate() {
let name = (**name).into(); let name = (**name).into();
let id = definition_ast_list.len() - id - 1;
let def = definition_ast_list[id].0.read(); let def = definition_ast_list[id].0.read();
if let TopLevelDef::Function { simple_name, signature, .. } = &*def { if let TopLevelDef::Function { name: func_name, simple_name, signature, .. } = &*def {
assert!(name == *simple_name); assert_eq!(name, *simple_name, "Simple name of builtin function should match builtin name list");
// Do not add member functions into the list of builtin IDs;
// Here we assume that all builtin top-level functions have the same name and simple
// name, and all member functions have something prefixed to its name
if *func_name != simple_name.to_string() {
continue
}
builtin_ty.insert(name, *signature); builtin_ty.insert(name, *signature);
builtin_id.insert(name, DefinitionId(id)); builtin_id.insert(name, DefinitionId(id));
} else if let TopLevelDef::Class { name, constructor, object_id, .. } = &*def } else if let TopLevelDef::Class { name, constructor, object_id, .. } = &*def
@ -546,6 +560,7 @@ impl TopLevelComposer {
&primitive_types, &primitive_types,
b, b,
vec![(*class_def_id, class_type_vars.clone())].into_iter().collect(), vec![(*class_def_id, class_type_vars.clone())].into_iter().collect(),
None,
)?; )?;
if let TypeAnnotation::CustomClass { .. } = &base_ty { if let TypeAnnotation::CustomClass { .. } = &base_ty {
@ -880,6 +895,7 @@ impl TopLevelComposer {
// NOTE: since only class need this, for function // NOTE: since only class need this, for function
// it should be fine to be empty map // it should be fine to be empty map
HashMap::new(), HashMap::new(),
None,
)?; )?;
let type_vars_within = let type_vars_within =
@ -947,6 +963,7 @@ impl TopLevelComposer {
// NOTE: since only class need this, for function // NOTE: since only class need this, for function
// it should be fine to be empty map // it should be fine to be empty map
HashMap::new(), HashMap::new(),
None,
)? )?
}; };
@ -1144,6 +1161,7 @@ impl TopLevelComposer {
vec![(class_id, class_type_vars_def.clone())] vec![(class_id, class_type_vars_def.clone())]
.into_iter() .into_iter()
.collect(), .collect(),
None,
)? )?
}; };
// find type vars within this method parameter type annotation // find type vars within this method parameter type annotation
@ -1207,6 +1225,7 @@ impl TopLevelComposer {
primitives, primitives,
result, result,
vec![(class_id, class_type_vars_def.clone())].into_iter().collect(), vec![(class_id, class_type_vars_def.clone())].into_iter().collect(),
None,
)?; )?;
// find type vars within this return type annotation // find type vars within this return type annotation
let type_vars_within = let type_vars_within =
@ -1303,6 +1322,7 @@ impl TopLevelComposer {
primitives, primitives,
annotation.as_ref(), annotation.as_ref(),
vec![(class_id, class_type_vars_def.clone())].into_iter().collect(), vec![(class_id, class_type_vars_def.clone())].into_iter().collect(),
None,
)?; )?;
// find type vars within this return type annotation // find type vars within this return type annotation
let type_vars_within = let type_vars_within =
@ -1721,7 +1741,7 @@ impl TopLevelComposer {
.iter() .iter()
.map(|(_, ty)| { .map(|(_, ty)| {
unifier.get_instantiations(*ty).unwrap_or_else(|| { unifier.get_instantiations(*ty).unwrap_or_else(|| {
if let TypeEnum::TVar { name, loc, .. } = &*unifier.get_ty(*ty) if let TypeEnum::TVar { name, loc, is_const_generic: false, .. } = &*unifier.get_ty(*ty)
{ {
let rigid = unifier.get_fresh_rigid_var(*name, *loc).0; let rigid = unifier.get_fresh_rigid_var(*name, *loc).0;
no_ranges.push(rigid); no_ranges.push(rigid);

View File

@ -416,40 +416,6 @@ impl TopLevelComposer {
primitive: &PrimitiveStore, primitive: &PrimitiveStore,
unifier: &mut Unifier, unifier: &mut Unifier,
) -> Result<(), String> { ) -> Result<(), String> {
fn type_default_param(
val: &SymbolValue,
primitive: &PrimitiveStore,
unifier: &mut Unifier,
) -> TypeAnnotation {
match val {
SymbolValue::Bool(..) => TypeAnnotation::Primitive(primitive.bool),
SymbolValue::Double(..) => TypeAnnotation::Primitive(primitive.float),
SymbolValue::I32(..) => TypeAnnotation::Primitive(primitive.int32),
SymbolValue::I64(..) => TypeAnnotation::Primitive(primitive.int64),
SymbolValue::U32(..) => TypeAnnotation::Primitive(primitive.uint32),
SymbolValue::U64(..) => TypeAnnotation::Primitive(primitive.uint64),
SymbolValue::Str(..) => TypeAnnotation::Primitive(primitive.str),
SymbolValue::Tuple(vs) => {
let vs_tys = vs
.iter()
.map(|v| type_default_param(v, primitive, unifier))
.collect::<Vec<_>>();
TypeAnnotation::Tuple(vs_tys)
}
SymbolValue::OptionNone => TypeAnnotation::CustomClass {
id: primitive.option.get_obj_id(unifier),
params: Default::default(),
},
SymbolValue::OptionSome(v) => {
let ty = type_default_param(v, primitive, unifier);
TypeAnnotation::CustomClass {
id: primitive.option.get_obj_id(unifier),
params: vec![ty],
}
}
}
}
fn is_compatible( fn is_compatible(
found: &TypeAnnotation, found: &TypeAnnotation,
expect: &TypeAnnotation, expect: &TypeAnnotation,
@ -481,7 +447,7 @@ impl TopLevelComposer {
} }
} }
let found = type_default_param(val, primitive, unifier); let found = val.get_type_annotation(primitive, unifier);
if !is_compatible(&found, ty, unifier, primitive) { if !is_compatible(&found, ty, unifier, primitive) {
Err(format!( Err(format!(
"incompatible default parameter type, expect {}, found {}", "incompatible default parameter type, expect {}, found {}",

View File

@ -361,7 +361,7 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
pass pass
"} "}
], ],
vec!["application of type vars to generic class is not currently supported (at unknown: line 4 column 24)"]; vec!["application of type vars to generic class is not currently supported (at unknown:4:24)"];
"err no type var in generic app" "err no type var in generic app"
)] )]
#[test_case( #[test_case(
@ -417,7 +417,7 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
def __init__(): def __init__():
pass pass
"}], "}],
vec!["__init__ method must have a `self` parameter (at unknown: line 2 column 5)"]; vec!["__init__ method must have a `self` parameter (at unknown:2:5)"];
"err no self_1" "err no self_1"
)] )]
#[test_case( #[test_case(
@ -439,7 +439,7 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
"} "}
], ],
vec!["a class definition can only have at most one base class declaration and one generic declaration (at unknown: line 1 column 24)"]; vec!["a class definition can only have at most one base class declaration and one generic declaration (at unknown:1:24)"];
"err multiple inheritance" "err multiple inheritance"
)] )]
#[test_case( #[test_case(
@ -507,7 +507,7 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
pass pass
"} "}
], ],
vec!["duplicate definition of class `A` (at unknown: line 1 column 1)"]; vec!["duplicate definition of class `A` (at unknown:1:1)"];
"class same name" "class same name"
)] )]
fn test_analyze(source: Vec<&str>, res: Vec<&str>) { fn test_analyze(source: Vec<&str>, res: Vec<&str>) {

View File

@ -1,3 +1,4 @@
use crate::symbol_resolver::SymbolValue;
use super::*; use super::*;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -12,6 +13,16 @@ pub enum TypeAnnotation {
// can only be CustomClassKind // can only be CustomClassKind
Virtual(Box<TypeAnnotation>), Virtual(Box<TypeAnnotation>),
TypeVar(Type), TypeVar(Type),
/// A constant used in the context of a const-generic variable.
Constant {
/// The non-type variable associated with this constant.
///
/// Invoking [Unifier::get_ty] on this type will return a [TypeEnum::TVar] representing the
/// const generic variable of which this constant is associated with.
ty: Type,
/// The constant value of this constant.
value: SymbolValue
},
List(Box<TypeAnnotation>), List(Box<TypeAnnotation>),
Tuple(Vec<TypeAnnotation>), Tuple(Vec<TypeAnnotation>),
} }
@ -47,6 +58,7 @@ impl TypeAnnotation {
} }
) )
} }
Constant { value, .. } => format!("Const({value})"),
Virtual(ty) => format!("virtual[{}]", ty.stringify(unifier)), Virtual(ty) => format!("virtual[{}]", ty.stringify(unifier)),
List(ty) => format!("list[{}]", ty.stringify(unifier)), List(ty) => format!("list[{}]", ty.stringify(unifier)),
Tuple(types) => { Tuple(types) => {
@ -56,6 +68,12 @@ impl TypeAnnotation {
} }
} }
/// Parses an AST expression `expr` into a [TypeAnnotation].
///
/// * `locked` - A [HashMap] containing the IDs of known definitions, mapped to a [Vec] of all
/// generic variables associated with the definition.
/// * `type_var` - The type variable associated with the type argument currently being parsed. Pass
/// [None] when this function is invoked externally.
pub fn parse_ast_to_type_annotation_kinds<T>( pub fn parse_ast_to_type_annotation_kinds<T>(
resolver: &(dyn SymbolResolver + Send + Sync), resolver: &(dyn SymbolResolver + Send + Sync),
top_level_defs: &[Arc<RwLock<TopLevelDef>>], top_level_defs: &[Arc<RwLock<TopLevelDef>>],
@ -64,6 +82,7 @@ pub fn parse_ast_to_type_annotation_kinds<T>(
expr: &ast::Expr<T>, expr: &ast::Expr<T>,
// the key stores the type_var of this topleveldef::class, we only need this field here // the key stores the type_var of this topleveldef::class, we only need this field here
locked: HashMap<DefinitionId, Vec<Type>>, locked: HashMap<DefinitionId, Vec<Type>>,
type_var: Option<Type>,
) -> Result<TypeAnnotation, String> { ) -> Result<TypeAnnotation, String> {
let name_handle = |id: &StrRef, let name_handle = |id: &StrRef,
unifier: &mut Unifier, unifier: &mut Unifier,
@ -127,7 +146,7 @@ pub fn parse_ast_to_type_annotation_kinds<T>(
slice: &ast::Expr<T>, slice: &ast::Expr<T>,
unifier: &mut Unifier, unifier: &mut Unifier,
mut locked: HashMap<DefinitionId, Vec<Type>>| { mut locked: HashMap<DefinitionId, Vec<Type>>| {
if vec!["virtual".into(), "Generic".into(), "list".into(), "tuple".into()].contains(id) if vec!["virtual".into(), "Generic".into(), "list".into(), "tuple".into(), "Option".into()].contains(id)
{ {
return Err(format!("keywords cannot be class name (at {})", expr.location)); return Err(format!("keywords cannot be class name (at {})", expr.location));
} }
@ -161,7 +180,8 @@ pub fn parse_ast_to_type_annotation_kinds<T>(
} }
let result = params_ast let result = params_ast
.iter() .iter()
.map(|x| { .enumerate()
.map(|(idx, x)| {
parse_ast_to_type_annotation_kinds( parse_ast_to_type_annotation_kinds(
resolver, resolver,
top_level_defs, top_level_defs,
@ -172,6 +192,7 @@ pub fn parse_ast_to_type_annotation_kinds<T>(
locked.insert(obj_id, type_vars.clone()); locked.insert(obj_id, type_vars.clone());
locked.clone() locked.clone()
}, },
Some(type_vars[idx]),
) )
}) })
.collect::<Result<Vec<_>, _>>()?; .collect::<Result<Vec<_>, _>>()?;
@ -190,6 +211,7 @@ pub fn parse_ast_to_type_annotation_kinds<T>(
}; };
Ok(TypeAnnotation::CustomClass { id: obj_id, params: param_type_infos }) Ok(TypeAnnotation::CustomClass { id: obj_id, params: param_type_infos })
}; };
match &expr.node { match &expr.node {
ast::ExprKind::Name { id, .. } => name_handle(id, unifier, locked), ast::ExprKind::Name { id, .. } => name_handle(id, unifier, locked),
// virtual // virtual
@ -205,6 +227,7 @@ pub fn parse_ast_to_type_annotation_kinds<T>(
primitives, primitives,
slice.as_ref(), slice.as_ref(),
locked, locked,
None,
)?; )?;
if !matches!(def, TypeAnnotation::CustomClass { .. }) { if !matches!(def, TypeAnnotation::CustomClass { .. }) {
unreachable!("must be concretized custom class kind in the virtual") unreachable!("must be concretized custom class kind in the virtual")
@ -225,6 +248,7 @@ pub fn parse_ast_to_type_annotation_kinds<T>(
primitives, primitives,
slice.as_ref(), slice.as_ref(),
locked, locked,
None,
)?; )?;
Ok(TypeAnnotation::List(def_ann.into())) Ok(TypeAnnotation::List(def_ann.into()))
} }
@ -242,6 +266,7 @@ pub fn parse_ast_to_type_annotation_kinds<T>(
primitives, primitives,
slice.as_ref(), slice.as_ref(),
locked, locked,
None,
)?; )?;
let id = let id =
if let TypeEnum::TObj { obj_id, .. } = unifier.get_ty(primitives.option).as_ref() { if let TypeEnum::TObj { obj_id, .. } = unifier.get_ty(primitives.option).as_ref() {
@ -275,6 +300,7 @@ pub fn parse_ast_to_type_annotation_kinds<T>(
primitives, primitives,
e, e,
locked.clone(), locked.clone(),
None,
) )
}) })
.collect::<Result<Vec<_>, _>>()?; .collect::<Result<Vec<_>, _>>()?;
@ -290,6 +316,31 @@ pub fn parse_ast_to_type_annotation_kinds<T>(
} }
} }
ast::ExprKind::Constant { value, .. } => {
let type_var = type_var.expect("Expect type variable to be present");
let ntv_ty_enum = unifier.get_ty_immutable(type_var);
let TypeEnum::TVar { range: underlying_ty, .. } = ntv_ty_enum.as_ref() else {
unreachable!()
};
let underlying_ty = underlying_ty[0];
let value = SymbolValue::from_constant(value, underlying_ty, primitives, unifier)?;
if matches!(value, SymbolValue::Str(_) | SymbolValue::Tuple(_) | SymbolValue::OptionSome(_)) {
return Err(format!(
"expression {} is not allowed for constant type annotation (at {})",
value.to_string(),
expr.location
))
}
Ok(TypeAnnotation::Constant {
ty: type_var,
value,
})
}
_ => Err(format!("unsupported expression for type annotation (at {})", expr.location)), _ => Err(format!("unsupported expression for type annotation (at {})", expr.location)),
} }
} }
@ -308,94 +359,130 @@ pub fn get_type_from_type_annotation_kinds(
TypeAnnotation::CustomClass { id: obj_id, params } => { TypeAnnotation::CustomClass { id: obj_id, params } => {
let def_read = top_level_defs[obj_id.0].read(); let def_read = top_level_defs[obj_id.0].read();
let class_def: &TopLevelDef = def_read.deref(); let class_def: &TopLevelDef = def_read.deref();
if let TopLevelDef::Class { fields, methods, type_vars, .. } = class_def { let TopLevelDef::Class { fields, methods, type_vars, .. } = class_def else {
if type_vars.len() != params.len() { unreachable!("should be class def here")
Err(format!( };
"unexpected number of type parameters: expected {} but got {}",
type_vars.len(),
params.len()
))
} else {
let param_ty = params
.iter()
.map(|x| {
get_type_from_type_annotation_kinds(
top_level_defs,
unifier,
primitives,
x,
subst_list
)
})
.collect::<Result<Vec<_>, _>>()?;
let subst = { if type_vars.len() != params.len() {
// check for compatible range return Err(format!(
// TODO: if allow type var to be applied(now this disallowed in the parse_to_type_annotation), need more check "unexpected number of type parameters: expected {} but got {}",
let mut result: HashMap<u32, Type> = HashMap::new(); type_vars.len(),
for (tvar, p) in type_vars.iter().zip(param_ty) { params.len()
if let TypeEnum::TVar { id, range, fields: None, name, loc } = ))
unifier.get_ty(*tvar).as_ref() }
{
let ok: bool = { let param_ty = params
// create a temp type var and unify to check compatibility .iter()
p == *tvar || { .map(|x| {
let temp = unifier.get_fresh_var_with_range( get_type_from_type_annotation_kinds(
range.as_slice(), top_level_defs,
*name, unifier,
*loc, primitives,
); x,
unifier.unify(temp.0, p).is_ok() subst_list
} )
}; })
if ok { .collect::<Result<Vec<_>, _>>()?;
result.insert(*id, p);
} else { let subst = {
return Err(format!( // check for compatible range
"cannot apply type {} to type variable with id {:?}", // TODO: if allow type var to be applied(now this disallowed in the parse_to_type_annotation), need more check
unifier.internal_stringify( let mut result: HashMap<u32, Type> = HashMap::new();
p, for (tvar, p) in type_vars.iter().zip(param_ty) {
&mut |id| format!("class{}", id), match unifier.get_ty(*tvar).as_ref() {
&mut |id| format!("typevar{}", id), TypeEnum::TVar { id, range, fields: None, name, loc, is_const_generic: false } => {
&mut None let ok: bool = {
), // create a temp type var and unify to check compatibility
*id p == *tvar || {
)); let temp = unifier.get_fresh_var_with_range(
range.as_slice(),
*name,
*loc,
);
unifier.unify(temp.0, p).is_ok()
} }
};
if ok {
result.insert(*id, p);
} else { } else {
unreachable!("must be generic type var") return Err(format!(
"cannot apply type {} to type variable with id {:?}",
unifier.internal_stringify(
p,
&mut |id| format!("class{}", id),
&mut |id| format!("typevar{}", id),
&mut None
),
*id
));
} }
} }
result
}; TypeEnum::TVar { id, range, name, loc, is_const_generic: true, .. } => {
let mut tobj_fields = methods let ty = range[0];
.iter() let ok: bool = {
.map(|(name, ty, _)| { // create a temp type var and unify to check compatibility
let subst_ty = unifier.subst(*ty, &subst).unwrap_or(*ty); p == *tvar || {
// methods are immutable let temp = unifier.get_fresh_const_generic_var(
(*name, (subst_ty, false)) ty,
}) *name,
.collect::<HashMap<_, _>>(); *loc,
tobj_fields.extend(fields.iter().map(|(name, ty, mutability)| { );
let subst_ty = unifier.subst(*ty, &subst).unwrap_or(*ty); unifier.unify(temp.0, p).is_ok()
(*name, (subst_ty, *mutability)) }
})); };
let need_subst = !subst.is_empty(); if ok {
let ty = unifier.add_ty(TypeEnum::TObj { result.insert(*id, p);
obj_id: *obj_id, } else {
fields: tobj_fields, return Err(format!(
params: subst, "cannot apply type {} to type variable {}",
}); unifier.stringify(p),
if need_subst { name.unwrap_or_else(|| format!("typevar{id}").into()),
subst_list.as_mut().map(|wl| wl.push(ty)); ))
}
}
_ => unreachable!("must be generic type var"),
} }
Ok(ty)
} }
} else { result
unreachable!("should be class def here") };
let mut tobj_fields = methods
.iter()
.map(|(name, ty, _)| {
let subst_ty = unifier.subst(*ty, &subst).unwrap_or(*ty);
// methods are immutable
(*name, (subst_ty, false))
})
.collect::<HashMap<_, _>>();
tobj_fields.extend(fields.iter().map(|(name, ty, mutability)| {
let subst_ty = unifier.subst(*ty, &subst).unwrap_or(*ty);
(*name, (subst_ty, *mutability))
}));
let need_subst = !subst.is_empty();
let ty = unifier.add_ty(TypeEnum::TObj {
obj_id: *obj_id,
fields: tobj_fields,
params: subst,
});
if need_subst {
subst_list.as_mut().map(|wl| wl.push(ty));
} }
Ok(ty)
} }
TypeAnnotation::Primitive(ty) | TypeAnnotation::TypeVar(ty) => Ok(*ty), TypeAnnotation::Primitive(ty) | TypeAnnotation::TypeVar(ty) => Ok(*ty),
TypeAnnotation::Constant { ty, value, .. } => {
let ty_enum = unifier.get_ty(*ty);
let (ty, loc) = match &*ty_enum {
TypeEnum::TVar { range: ntv_underlying_ty, loc, is_const_generic: true, .. } => {
(ntv_underlying_ty[0], loc)
}
_ => unreachable!("{} ({})", unifier.stringify(*ty), ty_enum.get_type_name()),
};
let var = unifier.get_fresh_constant(value.clone(), ty, *loc);
Ok(var)
}
TypeAnnotation::Virtual(ty) => { TypeAnnotation::Virtual(ty) => {
let ty = get_type_from_type_annotation_kinds( let ty = get_type_from_type_annotation_kinds(
top_level_defs, top_level_defs,
@ -470,7 +557,7 @@ pub fn get_type_var_contained_in_type_annotation(ann: &TypeAnnotation) -> Vec<Ty
result.extend(get_type_var_contained_in_type_annotation(a)); result.extend(get_type_var_contained_in_type_annotation(a));
} }
} }
TypeAnnotation::Primitive(..) => {} TypeAnnotation::Primitive(..) | TypeAnnotation::Constant { .. } => {}
} }
result result
} }

View File

@ -62,7 +62,7 @@ impl<'a> Inferencer<'a> {
) -> Result<(), String> { ) -> Result<(), String> {
// there are some cases where the custom field is None // there are some cases where the custom field is None
if let Some(ty) = &expr.custom { if let Some(ty) = &expr.custom {
if !self.unifier.is_concrete(*ty, &self.function_data.bound_variables) { if !matches!(&expr.node, ExprKind::Constant { value: Constant::Ellipsis, .. }) && !self.unifier.is_concrete(*ty, &self.function_data.bound_variables) {
return Err(format!( return Err(format!(
"expected concrete type at {} but got {}", "expected concrete type at {} but got {}",
expr.location, expr.location,

View File

@ -964,6 +964,7 @@ impl<'a> Inferencer<'a> {
ast::Constant::Str(_) => Ok(self.primitives.str), ast::Constant::Str(_) => Ok(self.primitives.str),
ast::Constant::None ast::Constant::None
=> report_error("CPython `None` not supported (nac3 uses `none` instead)", *loc), => report_error("CPython `None` not supported (nac3 uses `none` instead)", *loc),
ast::Constant::Ellipsis => Ok(self.unifier.get_fresh_var(None, None).0),
_ => report_error("not supported", *loc), _ => report_error("not supported", *loc),
} }
} }

View File

@ -134,6 +134,17 @@ pub enum TypeEnum {
range: Vec<Type>, range: Vec<Type>,
name: Option<StrRef>, name: Option<StrRef>,
loc: Option<Location>, loc: Option<Location>,
/// Whether this type variable refers to a const-generic variable.
is_const_generic: bool,
},
/// A constant for substitution into a const generic variable.
TConstant {
/// The value of the constant.
value: SymbolValue,
/// The underlying type of the value.
ty: Type,
loc: Option<Location>,
}, },
/// A tuple type. /// A tuple type.
@ -178,6 +189,7 @@ impl TypeEnum {
match self { match self {
TypeEnum::TRigidVar { .. } => "TRigidVar", TypeEnum::TRigidVar { .. } => "TRigidVar",
TypeEnum::TVar { .. } => "TVar", TypeEnum::TVar { .. } => "TVar",
TypeEnum::TConstant { .. } => "TConstant",
TypeEnum::TTuple { .. } => "TTuple", TypeEnum::TTuple { .. } => "TTuple",
TypeEnum::TList { .. } => "TList", TypeEnum::TList { .. } => "TList",
TypeEnum::TObj { .. } => "TObj", TypeEnum::TObj { .. } => "TObj",
@ -263,6 +275,7 @@ impl Unifier {
fields: Some(fields), fields: Some(fields),
name: None, name: None,
loc: None, loc: None,
is_const_generic: false,
}) })
} }
@ -336,7 +349,33 @@ impl Unifier {
let id = self.var_id + 1; let id = self.var_id + 1;
self.var_id += 1; self.var_id += 1;
let range = range.to_vec(); let range = range.to_vec();
(self.add_ty(TypeEnum::TVar { id, range, fields: None, name, loc }), id) (self.add_ty(TypeEnum::TVar { id, range, fields: None, name, loc, is_const_generic: false }), id)
}
/// Returns a fresh type representing a constant generic variable with the given underlying type
/// `ty`.
pub fn get_fresh_const_generic_var(
&mut self,
ty: Type,
name: Option<StrRef>,
loc: Option<Location>,
) -> (Type, u32) {
let id = self.var_id + 1;
self.var_id += 1;
(self.add_ty(TypeEnum::TVar { id, range: vec![ty], fields: None, name, loc, is_const_generic: true }), id)
}
/// Returns a fresh type representing a [fresh constant][TypeEnum::TConstant] with the given
/// `value` and type `ty`.
pub fn get_fresh_constant(
&mut self,
value: SymbolValue,
ty: Type,
loc: Option<Location>,
) -> Type {
assert!(matches!(self.get_ty(ty).as_ref(), TypeEnum::TObj { .. }));
self.add_ty(TypeEnum::TConstant { ty, value, loc })
} }
/// Unification would not unify rigid variables with other types, but we want to do this for /// Unification would not unify rigid variables with other types, but we want to do this for
@ -412,7 +451,7 @@ impl Unifier {
pub fn is_concrete(&mut self, a: Type, allowed_typevars: &[Type]) -> bool { pub fn is_concrete(&mut self, a: Type, allowed_typevars: &[Type]) -> bool {
use TypeEnum::*; use TypeEnum::*;
match &*self.get_ty(a) { match &*self.get_ty(a) {
TRigidVar { .. } => true, TRigidVar { .. } | TConstant { .. } => true,
TVar { .. } => allowed_typevars.iter().any(|b| self.unification_table.unioned(a, *b)), TVar { .. } => allowed_typevars.iter().any(|b| self.unification_table.unioned(a, *b)),
TCall { .. } => false, TCall { .. } => false,
TList { ty } => self.is_concrete(*ty, allowed_typevars), TList { ty } => self.is_concrete(*ty, allowed_typevars),
@ -560,8 +599,8 @@ impl Unifier {
}; };
match (&*ty_a, &*ty_b) { match (&*ty_a, &*ty_b) {
( (
TVar { fields: fields1, id, name: name1, loc: loc1, .. }, TVar { fields: fields1, id, name: name1, loc: loc1, is_const_generic: false, .. },
TVar { fields: fields2, id: id2, name: name2, loc: loc2, .. }, TVar { fields: fields2, id: id2, name: name2, loc: loc2, is_const_generic: false, .. },
) => { ) => {
let new_fields = match (fields1, fields2) { let new_fields = match (fields1, fields2) {
(None, None) => None, (None, None) => None,
@ -616,10 +655,11 @@ impl Unifier {
range, range,
name: name1.or(*name2), name: name1.or(*name2),
loc: loc1.or(*loc2), loc: loc1.or(*loc2),
is_const_generic: false,
}), }),
); );
} }
(TVar { fields: None, range, .. }, _) => { (TVar { fields: None, range, is_const_generic: false, .. }, _) => {
// We check for the range of the type variable to see if unification is allowed. // We check for the range of the type variable to see if unification is allowed.
// Note that although b may be compatible with a, we may have to constrain type // Note that although b may be compatible with a, we may have to constrain type
// variables in b to make sure that instantiations of b would always be compatible // variables in b to make sure that instantiations of b would always be compatible
@ -636,7 +676,7 @@ impl Unifier {
self.unify_impl(x, b, false)?; self.unify_impl(x, b, false)?;
self.set_a_to_b(a, x); self.set_a_to_b(a, x);
} }
(TVar { fields: Some(fields), range, .. }, TTuple { ty }) => { (TVar { fields: Some(fields), range, is_const_generic: false, .. }, TTuple { ty }) => {
let len = ty.len() as i32; let len = ty.len() as i32;
for (k, v) in fields.iter() { for (k, v) in fields.iter() {
match *k { match *k {
@ -666,7 +706,7 @@ impl Unifier {
self.unify_impl(x, b, false)?; self.unify_impl(x, b, false)?;
self.set_a_to_b(a, x); self.set_a_to_b(a, x);
} }
(TVar { fields: Some(fields), range, .. }, TList { ty }) => { (TVar { fields: Some(fields), range, is_const_generic: false, .. }, TList { ty }) => {
for (k, v) in fields.iter() { for (k, v) in fields.iter() {
match *k { match *k {
RecordKey::Int(_) => { RecordKey::Int(_) => {
@ -681,6 +721,35 @@ impl Unifier {
self.unify_impl(x, b, false)?; self.unify_impl(x, b, false)?;
self.set_a_to_b(a, x); self.set_a_to_b(a, x);
} }
(TVar { id: id1, range: ty1, is_const_generic: true, .. }, TVar { id: id2, range: ty2, .. }) => {
let ty1 = ty1[0];
let ty2 = ty2[0];
if id1 != id2 {
self.unify_impl(ty1, ty2, false)?;
}
self.set_a_to_b(a, b);
}
(TVar { range: ty1, is_const_generic: true, .. }, TConstant { ty: ty2, .. }) => {
let ty1 = ty1[0];
self.unify_impl(ty1, *ty2, false)?;
self.set_a_to_b(a, b);
}
(TConstant { value: val1, ty: ty1, .. }, TConstant { value: val2, ty: ty2, .. }) => {
if val1 != val2 {
eprintln!("VALUE MISMATCH: lhs={val1:?} rhs={val2:?} eq={}", val1 == val2);
return self.incompatible_types(a, b)
}
self.unify_impl(*ty1, *ty2, false)?;
self.set_a_to_b(a, b);
}
(TTuple { ty: ty1 }, TTuple { ty: ty2 }) => { (TTuple { ty: ty1 }, TTuple { ty: ty2 }) => {
if ty1.len() != ty2.len() { if ty1.len() != ty2.len() {
return Err(TypeError::new(TypeErrorKind::IncompatibleTypes(a, b), None)); return Err(TypeError::new(TypeErrorKind::IncompatibleTypes(a, b), None));
@ -775,7 +844,14 @@ impl Unifier {
if id1 != id2 { if id1 != id2 {
self.incompatible_types(a, b)?; self.incompatible_types(a, b)?;
} }
for (x, y) in zip(params1.values(), params2.values()) {
// Sort the type arguments by its UnificationKey first, since `HashMap::iter` visits
// all K-V pairs "in arbitrary order"
let (tv1, tv2) = (
params1.iter().sorted_by_key(|(k, _)| *k).map(|(_, v)| v).collect_vec(),
params2.iter().sorted_by_key(|(k, _)| *k).map(|(_, v)| v).collect_vec(),
);
for (x, y) in zip(tv1, tv2) {
if self.unify_impl(*x, *y, false).is_err() { if self.unify_impl(*x, *y, false).is_err() {
return Err(TypeError::new(TypeErrorKind::IncompatibleTypes(a, b), None)); return Err(TypeError::new(TypeErrorKind::IncompatibleTypes(a, b), None));
}; };
@ -928,6 +1004,9 @@ impl Unifier {
}; };
n n
} }
TypeEnum::TConstant { value, .. } => {
format!("const({value})")
}
TypeEnum::TTuple { ty } => { TypeEnum::TTuple { ty } => {
let mut fields = let mut fields =
ty.iter().map(|v| self.internal_stringify(*v, obj_to_name, var_to_name, notes)); ty.iter().map(|v| self.internal_stringify(*v, obj_to_name, var_to_name, notes));
@ -983,8 +1062,8 @@ impl Unifier {
} }
} }
/// Unifies `a` and `b` together, and set the value to the value of `b`.
fn set_a_to_b(&mut self, a: Type, b: Type) { fn set_a_to_b(&mut self, a: Type, b: Type) {
// unify a and b together, and set the value to b's value.
let table = &mut self.unification_table; let table = &mut self.unification_table;
let ty_b = table.probe_value(b).clone(); let ty_b = table.probe_value(b).clone();
table.unify(a, b); table.unify(a, b);
@ -1207,6 +1286,7 @@ impl Unifier {
range, range,
name: name2.or(*name), name: name2.or(*name),
loc: loc2.or(*loc), loc: loc2.or(*loc),
is_const_generic: false,
}; };
Ok(Some(self.unification_table.new_key(ty.into()))) Ok(Some(self.unification_table.new_key(ty.into())))
} }

View File

@ -30,7 +30,7 @@ void output_int32(int32_t x) {
} }
void output_int64(int64_t x) { void output_int64(int64_t x) {
printf("%ld\n", x); printf("%lld\n", x);
} }
void output_uint32(uint32_t x) { void output_uint32(uint32_t x) {
@ -38,7 +38,7 @@ void output_uint32(uint32_t x) {
} }
void output_uint64(uint64_t x) { void output_uint64(uint64_t x) {
printf("%lu\n", x); printf("%llu\n", x);
} }
void output_float64(double x) { void output_float64(double x) {

View File

@ -6,9 +6,9 @@ import importlib.machinery
import math import math
import numpy as np import numpy as np
import pathlib import pathlib
import scipy
from numpy import int32, int64, uint32, uint64 from numpy import int32, int64, uint32, uint64
from scipy import special
from typing import TypeVar, Generic from typing import TypeVar, Generic
T = TypeVar('T') T = TypeVar('T')
@ -44,6 +44,12 @@ def Some(v: T) -> Option[T]:
none = Option(None) none = Option(None)
class _ConstGenericMarker:
pass
def ConstGeneric(name, constraint):
return TypeVar(name, _ConstGenericMarker, constraint)
def round_away_zero(x): def round_away_zero(x):
if x >= 0.0: if x >= 0.0:
return math.floor(x + 0.5) return math.floor(x + 0.5)
@ -99,6 +105,7 @@ def patch(module):
module.uint32 = uint32 module.uint32 = uint32
module.uint64 = uint64 module.uint64 = uint64
module.TypeVar = TypeVar module.TypeVar = TypeVar
module.ConstGeneric = ConstGeneric
module.Generic = Generic module.Generic = Generic
module.extern = extern module.extern = extern
module.Option = Option module.Option = Option
@ -108,52 +115,55 @@ def patch(module):
# Builtin Math functions # Builtin Math functions
module.round = round_away_zero module.round = round_away_zero
module.round64 = round_away_zero module.round64 = round_away_zero
module.np_round = np.round
module.floor = math.floor module.floor = math.floor
module.floor64 = math.floor module.floor64 = math.floor
module.np_floor = np.floor
module.ceil = math.ceil module.ceil = math.ceil
module.ceil64 = math.ceil module.ceil64 = math.ceil
module.np_ceil = np.ceil
# NumPy Math functions # NumPy Math functions
module.isnan = np.isnan module.np_isnan = np.isnan
module.isinf = np.isinf module.np_isinf = np.isinf
module.sin = np.sin module.np_sin = np.sin
module.cos = np.cos module.np_cos = np.cos
module.exp = np.exp module.np_exp = np.exp
module.exp2 = np.exp2 module.np_exp2 = np.exp2
module.log = np.log module.np_log = np.log
module.log10 = np.log10 module.np_log10 = np.log10
module.log2 = np.log2 module.np_log2 = np.log2
module.fabs = np.fabs module.np_fabs = np.fabs
module.trunc = np.trunc module.np_trunc = np.trunc
module.sqrt = np.sqrt module.np_sqrt = np.sqrt
module.rint = np.rint module.np_rint = np.rint
module.tan = np.tan module.np_tan = np.tan
module.arcsin = np.arcsin module.np_arcsin = np.arcsin
module.arccos = np.arccos module.np_arccos = np.arccos
module.arctan = np.arctan module.np_arctan = np.arctan
module.sinh = np.sinh module.np_sinh = np.sinh
module.cosh = np.cosh module.np_cosh = np.cosh
module.tanh = np.tanh module.np_tanh = np.tanh
module.arcsinh = np.arcsinh module.np_arcsinh = np.arcsinh
module.arccosh = np.arccosh module.np_arccosh = np.arccosh
module.arctanh = np.arctanh module.np_arctanh = np.arctanh
module.expm1 = np.expm1 module.np_expm1 = np.expm1
module.cbrt = np.cbrt module.np_cbrt = np.cbrt
module.arctan2 = np.arctan2 module.np_arctan2 = np.arctan2
module.copysign = np.copysign module.np_copysign = np.copysign
module.fmax = np.fmax module.np_fmax = np.fmax
module.fmin = np.fmin module.np_fmin = np.fmin
module.ldexp = np.ldexp module.np_ldexp = np.ldexp
module.hypot = np.hypot module.np_hypot = np.hypot
module.nextafter = np.nextafter module.np_nextafter = np.nextafter
# SciPy Math Functions # SciPy Math Functions
module.erf = scipy.special.erf module.sp_spec_erf = special.erf
module.erfc = scipy.special.erfc module.sp_spec_erfc = special.erfc
module.gamma = scipy.special.gamma module.sp_spec_gamma = special.gamma
module.gammaln = scipy.special.gammaln module.sp_spec_gammaln = special.gammaln
module.j0 = scipy.special.j0 module.sp_spec_j0 = special.j0
module.j1 = scipy.special.j1 module.sp_spec_j1 = special.j1
def file_import(filename, prefix="file_import_"): def file_import(filename, prefix="file_import_"):

View File

@ -0,0 +1,50 @@
A = ConstGeneric("A", int32)
B = ConstGeneric("B", uint32)
T = TypeVar("T")
class ConstGenericClass(Generic[A]):
def __init__(self):
pass
class ConstGeneric2Class(Generic[A, B]):
def __init__(self):
pass
class HybridGenericClass2(Generic[A, T]):
pass
class HybridGenericClass3(Generic[T, A, B]):
pass
def make_generic_2() -> ConstGenericClass[2]:
return ...
def make_generic2_1_2() -> ConstGeneric2Class[1, 2]:
return ...
def make_hybrid_class_2_int32() -> HybridGenericClass2[2, int32]:
return ...
def make_hybrid_class_i32_0_1() -> HybridGenericClass3[int32, 0, 1]:
return ...
def consume_generic_2(instance: ConstGenericClass[2]):
pass
def consume_generic2_1_2(instance: ConstGeneric2Class[1, 2]):
pass
def consume_hybrid_class_2_i32(instance: HybridGenericClass2[2, int32]):
pass
def consume_hybrid_class_i32_0_1(instance: HybridGenericClass3[int32, 0, 1]):
pass
def f():
consume_generic_2(make_generic_2())
consume_generic2_1_2(make_generic2_1_2())
consume_hybrid_class_2_i32(make_hybrid_class_2_int32())
consume_hybrid_class_i32_0_1(make_hybrid_class_i32_0_1())
def run() -> int32:
return 0

View File

@ -36,48 +36,52 @@ def test_round64():
for x in [-1.5, -0.5, 0.5, 1.5]: for x in [-1.5, -0.5, 0.5, 1.5]:
output_int64(round64(x)) output_int64(round64(x))
def test_isnan(): def test_np_round():
for x in [-1.5, -0.5, 0.5, 1.5, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(np_round(x))
def test_np_isnan():
for x in [dbl_nan(), 0.0, dbl_inf()]: for x in [dbl_nan(), 0.0, dbl_inf()]:
output_bool(isnan(x)) output_bool(np_isnan(x))
def test_isinf(): def test_np_isinf():
for x in [dbl_inf(), -dbl_inf(), 0.0, dbl_nan()]: for x in [dbl_inf(), -dbl_inf(), 0.0, dbl_nan()]:
output_bool(isinf(x)) output_bool(np_isinf(x))
def test_sin(): def test_np_sin():
pi = dbl_pi() pi = dbl_pi()
for x in [-pi, -pi / 2.0, -pi / 4.0, 0.0, pi / 4.0, pi / 2.0, pi, dbl_inf(), -dbl_inf(), dbl_nan()]: for x in [-pi, -pi / 2.0, -pi / 4.0, 0.0, pi / 4.0, pi / 2.0, pi, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(sin(x)) output_float64(np_sin(x))
def test_cos(): def test_np_cos():
pi = dbl_pi() pi = dbl_pi()
for x in [-pi, -pi / 2.0, -pi / 4.0, 0.0, pi / 4.0, pi / 2.0, pi, dbl_inf(), -dbl_inf(), dbl_nan()]: for x in [-pi, -pi / 2.0, -pi / 4.0, 0.0, pi / 4.0, pi / 2.0, pi, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(cos(x)) output_float64(np_cos(x))
def test_exp(): def test_np_exp():
for x in [0.0, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x in [0.0, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(exp(x)) output_float64(np_exp(x))
def test_exp2(): def test_np_exp2():
for x in [0.0, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x in [0.0, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(exp2(x)) output_float64(np_exp2(x))
def test_log(): def test_np_log():
e = dbl_e() e = dbl_e()
for x in [1.0, e, dbl_inf(), -dbl_inf(), dbl_nan()]: for x in [1.0, e, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(log(x)) output_float64(np_log(x))
def test_log10(): def test_np_log10():
for x in [1.0, 10.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x in [1.0, 10.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(log10(x)) output_float64(np_log10(x))
def test_log2(): def test_np_log2():
for x in [1.0, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x in [1.0, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(log2(x)) output_float64(np_log2(x))
def test_fabs(): def test_np_fabs():
for x in [-1.0, 0.0, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x in [-1.0, 0.0, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(fabs(x)) output_float64(np_fabs(x))
def test_floor(): def test_floor():
for x in [-1.5, -0.5, 0.5, 1.5]: for x in [-1.5, -0.5, 0.5, 1.5]:
@ -87,6 +91,10 @@ def test_floor64():
for x in [-1.5, -0.5, 0.5, 1.5]: for x in [-1.5, -0.5, 0.5, 1.5]:
output_int64(floor64(x)) output_int64(floor64(x))
def test_np_floor():
for x in [-1.5, -0.5, 0.5, 1.5, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(np_floor(x))
def test_ceil(): def test_ceil():
for x in [-1.5, -0.5, 0.5, 1.5]: for x in [-1.5, -0.5, 0.5, 1.5]:
output_int32(ceil(x)) output_int32(ceil(x))
@ -95,165 +103,172 @@ def test_ceil64():
for x in [-1.5, -0.5, 0.5, 1.5]: for x in [-1.5, -0.5, 0.5, 1.5]:
output_int64(ceil64(x)) output_int64(ceil64(x))
def test_sqrt(): def test_np_ceil():
for x in [1.0, 2.0, 4.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(sqrt(x))
def test_rint():
for x in [-1.5, -0.5, 0.5, 1.5, dbl_inf(), -dbl_inf(), dbl_nan()]: for x in [-1.5, -0.5, 0.5, 1.5, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(rint(x)) output_float64(np_ceil(x))
def test_tan(): def test_np_sqrt():
for x in [1.0, 2.0, 4.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(np_sqrt(x))
def test_np_rint():
for x in [-1.5, -0.5, 0.5, 1.5, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(np_rint(x))
def test_np_tan():
pi = dbl_pi() pi = dbl_pi()
for x in [-pi, -pi / 2.0, -pi / 4.0, 0.0, pi / 4.0, pi / 2.0, pi, dbl_inf(), -dbl_inf(), dbl_nan()]: for x in [-pi, -pi / 2.0, -pi / 4.0, 0.0, pi / 4.0, pi / 2.0, pi, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(tan(x)) output_float64(np_tan(x))
def test_arcsin(): def test_np_arcsin():
for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(arcsin(x)) output_float64(np_arcsin(x))
def test_arccos(): def test_np_arccos():
for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(arccos(x)) output_float64(np_arccos(x))
def test_arctan(): def test_np_arctan():
for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(arctan(x)) output_float64(np_arctan(x))
def test_sinh(): def test_np_sinh():
for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(sinh(x)) output_float64(np_sinh(x))
def test_cosh(): def test_np_cosh():
for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(cosh(x)) output_float64(np_cosh(x))
def test_tanh(): def test_np_tanh():
for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(tanh(x)) output_float64(np_tanh(x))
def test_arcsinh(): def test_np_arcsinh():
for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(arcsinh(x)) output_float64(np_arcsinh(x))
def test_arccosh(): def test_np_arccosh():
for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(arccosh(x)) output_float64(np_arccosh(x))
def test_arctanh(): def test_np_arctanh():
for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(arctanh(x)) output_float64(np_arctanh(x))
def test_expm1(): def test_np_expm1():
for x in [0.0, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x in [0.0, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(expm1(x)) output_float64(np_expm1(x))
def test_cbrt(): def test_np_cbrt():
for x in [1.0, 8.0, 27.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x in [1.0, 8.0, 27.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(expm1(x)) output_float64(np_expm1(x))
def test_erf(): def test_sp_spec_erf():
for x in [-3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x in [-3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(erf(x)) output_float64(sp_spec_erf(x))
def test_erfc(): def test_sp_spec_erfc():
for x in [-3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x in [-3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(erfc(x)) output_float64(sp_spec_erfc(x))
def test_gamma(): def test_sp_spec_gamma():
for x in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(gamma(x)) output_float64(sp_spec_gamma(x))
def test_gammaln(): def test_sp_spec_gammaln():
for x in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(gammaln(x)) output_float64(sp_spec_gammaln(x))
def test_j0(): def test_sp_spec_j0():
for x in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(j0(x)) output_float64(sp_spec_j0(x))
def test_j1(): def test_sp_spec_j1():
for x in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0]: for x in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0]:
output_float64(j1(x)) output_float64(sp_spec_j1(x))
def test_arctan2(): def test_np_arctan2():
for x1 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x1 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
for x2 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x2 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(arctan2(x1, x2)) output_float64(np_arctan2(x1, x2))
def test_copysign(): def test_np_copysign():
for x1 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x1 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
for x2 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x2 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(copysign(x1, x2)) output_float64(np_copysign(x1, x2))
def test_fmax(): def test_np_fmax():
for x1 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x1 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
for x2 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x2 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(fmax(x1, x2)) output_float64(np_fmax(x1, x2))
def test_fmin(): def test_np_fmin():
for x1 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x1 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
for x2 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x2 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(fmin(x1, x2)) output_float64(np_fmin(x1, x2))
def test_ldexp(): def test_np_ldexp():
for x1 in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x1 in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
for x2 in [-2, -1, 0, 1, 2]: for x2 in [-2, -1, 0, 1, 2]:
output_float64(ldexp(x1, x2)) output_float64(np_ldexp(x1, x2))
def test_hypot(): def test_np_hypot():
for x1 in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x1 in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
for x2 in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x2 in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(hypot(x1, x2)) output_float64(np_hypot(x1, x2))
def test_nextafter(): def test_np_nextafter():
for x1 in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x1 in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
for x2 in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]: for x2 in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(nextafter(x1, x2)) output_float64(np_nextafter(x1, x2))
def run() -> int32: def run() -> int32:
test_round() test_round()
test_round64() test_round64()
test_isnan() test_np_round()
test_isinf() test_np_isnan()
test_sin() test_np_isinf()
test_cos() test_np_sin()
test_exp() test_np_cos()
test_exp2() test_np_exp()
test_log() test_np_exp2()
test_log10() test_np_log()
test_log2() test_np_log10()
test_fabs() test_np_log2()
test_np_fabs()
test_floor() test_floor()
test_floor64() test_floor64()
test_np_floor()
test_ceil() test_ceil()
test_ceil64() test_ceil64()
test_sqrt() test_np_ceil()
test_rint() test_np_sqrt()
test_tan() test_np_rint()
test_arcsin() test_np_tan()
test_arccos() test_np_arcsin()
test_arctan() test_np_arccos()
test_sinh() test_np_arctan()
test_cosh() test_np_sinh()
test_tanh() test_np_cosh()
test_arcsinh() test_np_tanh()
test_arccosh() test_np_arcsinh()
test_arctanh() test_np_arccosh()
test_expm1() test_np_arctanh()
test_cbrt() test_np_expm1()
test_erf() test_np_cbrt()
test_erfc() test_sp_spec_erf()
test_gamma() test_sp_spec_erfc()
test_gammaln() test_sp_spec_gamma()
test_j0() test_sp_spec_gammaln()
test_j1() test_sp_spec_j0()
test_arctan2() test_sp_spec_j1()
test_copysign() test_np_arctan2()
test_fmax() test_np_copysign()
test_fmin() test_np_fmax()
test_ldexp() test_np_fmin()
test_hypot() test_np_ldexp()
test_nextafter() test_np_hypot()
test_np_nextafter()
return 0 return 0

View File

@ -0,0 +1,26 @@
def run() -> int32:
# Numeric Primitives
b: bool = False
i32: int32 = 0
i64: int64 = int64(0)
u32: uint32 = uint32(0)
u64: uint64 = uint64(0)
f64: float = 0.0
# String
s: str = ""
# List
l_i32: list[int32] = []
l_f64: list[float] = []
l_str: list[str] = []
# Option
o_some: Option[int32] = Some(0)
o_none: Option[int32] = none
# Tuple
t_i32_i32: tuple[int32, int32] = (0, 0)
t_i32_f64: tuple[int32, float] = (0, 0.0)
return 0

View File

@ -7,7 +7,7 @@ use inkwell::{
OptimizationLevel, OptimizationLevel,
}; };
use parking_lot::{Mutex, RwLock}; use parking_lot::{Mutex, RwLock};
use std::{borrow::Borrow, collections::HashMap, fs, path::Path, sync::Arc}; use std::{collections::HashMap, fs, path::Path, sync::Arc};
use nac3core::{ use nac3core::{
codegen::{ codegen::{
@ -25,7 +25,7 @@ use nac3core::{
}, },
}; };
use nac3parser::{ use nac3parser::{
ast::{Expr, ExprKind, StmtKind}, ast::{Constant, Expr, ExprKind, StmtKind, StrRef},
parser, parser,
}; };
@ -77,8 +77,20 @@ fn handle_typevar_definition(
unifier: &mut Unifier, unifier: &mut Unifier,
primitives: &PrimitiveStore, primitives: &PrimitiveStore,
) -> Result<Type, String> { ) -> Result<Type, String> {
if let ExprKind::Call { func, args, .. } = &var.node { let ExprKind::Call { func, args, .. } = &var.node else {
if matches!(&func.node, ExprKind::Name { id, .. } if id == &"TypeVar".into()) { return Err(format!(
"expression {:?} cannot be handled as a generic parameter in global scope",
var
))
};
match &func.node {
ExprKind::Name { id, .. } if id == &"TypeVar".into() => {
let ExprKind::Constant { value: Constant::Str(ty_name), .. } = &args[0].node else {
return Err(format!("Expected string constant for first parameter of `TypeVar`, got {:?}", &args[0].node))
};
let generic_name: StrRef = ty_name.to_string().into();
let constraints = args let constraints = args
.iter() .iter()
.skip(1) .skip(1)
@ -90,22 +102,54 @@ fn handle_typevar_definition(
primitives, primitives,
x, x,
Default::default(), Default::default(),
None,
)?; )?;
get_type_from_type_annotation_kinds( get_type_from_type_annotation_kinds(
def_list, unifier, primitives, &ty, &mut None def_list, unifier, primitives, &ty, &mut None
) )
}) })
.collect::<Result<Vec<_>, _>>()?; .collect::<Result<Vec<_>, _>>()?;
Ok(unifier.get_fresh_var_with_range(&constraints, None, None).0) let loc = func.location;
} else {
Err(format!( if constraints.len() == 1 {
"expression {:?} cannot be handled as a TypeVar in global scope", return Err(format!("A single constraint is not allowed (at {})", loc))
var }
))
Ok(unifier.get_fresh_var_with_range(&constraints, Some(generic_name), Some(loc)).0)
} }
} else {
Err(format!( ExprKind::Name { id, .. } if id == &"ConstGeneric".into() => {
"expression {:?} cannot be handled as a TypeVar in global scope", if args.len() != 2 {
return Err(format!("Expected 2 arguments for `ConstGeneric`, got {}", args.len()))
}
let ExprKind::Constant { value: Constant::Str(ty_name), .. } = &args[0].node else {
return Err(format!(
"Expected string constant for first parameter of `ConstGeneric`, got {:?}",
&args[0].node
))
};
let generic_name: StrRef = ty_name.to_string().into();
let ty = parse_ast_to_type_annotation_kinds(
resolver,
def_list,
unifier,
primitives,
&args[1],
Default::default(),
None,
)?;
let constraint = get_type_from_type_annotation_kinds(
def_list, unifier, primitives, &ty, &mut None
)?;
let loc = func.location;
Ok(unifier.get_fresh_const_generic_var(constraint, Some(generic_name), Some(loc)).0)
}
_ => Err(format!(
"expression {:?} cannot be handled as a generic parameter in global scope",
var var
)) ))
} }
@ -124,7 +168,7 @@ fn handle_assignment_pattern(
match &targets[0].node { match &targets[0].node {
ExprKind::Name { id, .. } => { ExprKind::Name { id, .. } => {
if let Ok(var) = handle_typevar_definition( if let Ok(var) = handle_typevar_definition(
value.borrow(), value,
resolver, resolver,
def_list, def_list,
unifier, unifier,
@ -133,12 +177,12 @@ fn handle_assignment_pattern(
internal_resolver.add_id_type(*id, var); internal_resolver.add_id_type(*id, var);
Ok(()) Ok(())
} else if let Ok(val) = } else if let Ok(val) =
parse_parameter_default_value(value.borrow(), resolver) parse_parameter_default_value(value, resolver)
{ {
internal_resolver.add_module_global(*id, val); internal_resolver.add_module_global(*id, val);
Ok(()) Ok(())
} else { } else {
Err(format!("fails to evaluate this expression `{:?}` as a constant or TypeVar at {}", Err(format!("fails to evaluate this expression `{:?}` as a constant or generic parameter at {}",
targets[0].node, targets[0].node,
targets[0].location, targets[0].location,
)) ))
@ -324,6 +368,7 @@ fn main() {
triple, triple,
cpu: mcpu, cpu: mcpu,
features: target_features, features: target_features,
reloc_mode: RelocMode::PIC,
..host_target_machine ..host_target_machine
}, },
}; };

View File

@ -1,16 +1,16 @@
pkgbase="mingw-w64-nac3artiq" pkgbase="mingw-w64-nac3artiq"
pkgname="mingw-w64-x86_64-nac3artiq" pkgname="mingw-w64-clang-x86_64-nac3artiq"
pkgver=1.0 pkgver=1.0
pkgrel=1 pkgrel=1
pkgdesc="New ARTIQ compiler 3" pkgdesc="New ARTIQ compiler 3"
arch=("any") arch=("any")
mingw_arch=("mingw64") mingw_arch=("clang64")
url="https://m-labs.hk" url="https://m-labs.hk"
license=("LGPL") license=("LGPL")
source=("nac3artiq.pyd") source=("nac3artiq.pyd")
noextract=("nac3artiq.pyd") noextract=("nac3artiq.pyd")
sha256sums=("SKIP") sha256sums=("SKIP")
depends=("mingw-w64-x86_64-python") depends=("mingw-w64-clang-x86_64-python")
prepare() { prepare() {
true true
@ -21,6 +21,6 @@ build() {
} }
package() { package() {
mkdir -p $pkgdir/mingw64/lib/python3.11/site-packages mkdir -p $pkgdir/clang64/lib/python3.11/site-packages
cp ${srcdir}/nac3artiq.pyd $pkgdir/mingw64/lib/python3.11/site-packages cp ${srcdir}/nac3artiq.pyd $pkgdir/clang64/lib/python3.11/site-packages
} }

View File

@ -25,7 +25,7 @@ let
shared=true shared=true
abi3=false abi3=false
lib_name=python3.11 lib_name=python3.11
lib_dir=${msys2-env}/mingw64/lib lib_dir=${msys2-env}/clang64/lib
pointer_width=64 pointer_width=64
build_flags=WITH_THREAD build_flags=WITH_THREAD
suppress_build_script_link_lines=false suppress_build_script_link_lines=false
@ -61,7 +61,7 @@ in rec {
'' ''
export HOME=`mktemp -d` export HOME=`mktemp -d`
export WINEDEBUG=-all export WINEDEBUG=-all
export WINEPATH=Z:${msys2-env}/mingw64/bin export WINEPATH=Z:${msys2-env}/clang64/bin
${silenceFontconfig} ${silenceFontconfig}
mkdir build mkdir build
cd build cd build
@ -77,7 +77,12 @@ in rec {
''; '';
dontFixup = true; dontFixup = true;
}; };
clang-unwrapped = pkgs.runCommandNoCC "clang-unwrapped" {} "mkdir -p $out/bin; ln -s ${llvm-nac3}/bin/clang.exe $out/bin/clang-unwrapped.exe"; llvm-tools-irrt = pkgs.runCommandNoCC "llvm-tools-irrt" {}
''
mkdir -p $out/bin
ln -s ${llvm-nac3}/bin/clang.exe $out/bin/clang-irrt.exe
ln -s ${llvm-nac3}/bin/llvm-as.exe $out/bin/llvm-as-irrt.exe
'';
nac3artiq = pkgs.rustPlatform.buildRustPackage { nac3artiq = pkgs.rustPlatform.buildRustPackage {
name = "nac3artiq-msys2"; name = "nac3artiq-msys2";
src = ../../.; src = ../../.;
@ -89,9 +94,11 @@ in rec {
'' ''
export HOME=`mktemp -d` export HOME=`mktemp -d`
export WINEDEBUG=-all export WINEDEBUG=-all
export WINEPATH=Z:${msys2-env}/mingw64/bin\;Z:${llvm-nac3}/bin\;Z:${clang-unwrapped}/bin export WINEPATH=Z:${msys2-env}/clang64/bin\;Z:${llvm-nac3}/bin\;Z:${llvm-tools-irrt}/bin
${silenceFontconfig} ${silenceFontconfig}
export PYO3_CONFIG_FILE=Z:${pyo3-mingw-config} export PYO3_CONFIG_FILE=Z:${pyo3-mingw-config}
export CC=clang
export LLVM_SYS_140_PREFIX=Z:${llvm-nac3}
wine64 cargo build --release -p nac3artiq wine64 cargo build --release -p nac3artiq
''; '';
installPhase = installPhase =
@ -100,6 +107,7 @@ in rec {
cp target/release/nac3artiq.dll $out/nac3artiq.pyd cp target/release/nac3artiq.dll $out/nac3artiq.pyd
echo file binary-dist $out/nac3artiq.pyd >> $out/nix-support/hydra-build-products echo file binary-dist $out/nac3artiq.pyd >> $out/nix-support/hydra-build-products
''; '';
doCheck = false; # https://git.m-labs.hk/M-Labs/nac3/issues/358
checkPhase = checkPhase =
'' ''
wine64 cargo test --release wine64 cargo test --release
@ -127,7 +135,7 @@ in rec {
wine-msys2 = pkgs.writeShellScriptBin "wine-msys2" wine-msys2 = pkgs.writeShellScriptBin "wine-msys2"
'' ''
export WINEDEBUG=-all export WINEDEBUG=-all
export WINEPATH=Z:${msys2-env}/mingw64/bin\;Z:${llvm-nac3}/bin\;Z:${clang-unwrapped}/bin export WINEPATH=Z:${msys2-env}/clang64/bin\;Z:${llvm-nac3}/bin\;Z:${llvm-tools-irrt}/bin
export PYO3_CONFIG_FILE=Z:${pyo3-mingw-config} export PYO3_CONFIG_FILE=Z:${pyo3-mingw-config}
exec ${pkgs.wineWowPackages.stable}/bin/wine64 cmd exec ${pkgs.wineWowPackages.stable}/bin/wine64 cmd
''; '';
@ -135,7 +143,7 @@ in rec {
'' ''
export HOME=`mktemp -d` export HOME=`mktemp -d`
export WINEDEBUG=-all export WINEDEBUG=-all
export WINEPATH=Z:${msys2-env}/mingw64/bin export WINEPATH=Z:${msys2-env}/clang64/bin
${silenceFontconfig} ${silenceFontconfig}
exec ${pkgs.wineWowPackages.stable}/bin/wine64 $@ exec ${pkgs.wineWowPackages.stable}/bin/wine64 $@
''; '';

View File

@ -10,7 +10,7 @@ curl -L https://mirror.msys2.org/msys/x86_64/pacman-mirrors-20220205-1-any.pkg.t
curl -L https://raw.githubusercontent.com/msys2/MSYS2-packages/master/pacman/pacman.conf | sed "s|SigLevel = Required|SigLevel = Never|g" | sed "s|/etc/pacman.d|$MSYS2DIR/etc/pacman.d|g" > $MSYS2DIR/etc/pacman.conf curl -L https://raw.githubusercontent.com/msys2/MSYS2-packages/master/pacman/pacman.conf | sed "s|SigLevel = Required|SigLevel = Never|g" | sed "s|/etc/pacman.d|$MSYS2DIR/etc/pacman.d|g" > $MSYS2DIR/etc/pacman.conf
fakeroot pacman --root $MSYS2DIR --config $MSYS2DIR/etc/pacman.conf -Syy fakeroot pacman --root $MSYS2DIR --config $MSYS2DIR/etc/pacman.conf -Syy
pacman --root $MSYS2DIR --config $MSYS2DIR/etc/pacman.conf --cachedir $MSYS2DIR/msys/cache -Sp mingw-w64-x86_64-rust mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-python3.11 mingw-w64-x86_64-python-numpy mingw-w64-x86_64-python-setuptools > $MSYS2DIR/packages.txt pacman --root $MSYS2DIR --config $MSYS2DIR/etc/pacman.conf --cachedir $MSYS2DIR/msys/cache -Sp mingw-w64-clang-x86_64-rust mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-ninja mingw-w64-clang-x86_64-python3.11 mingw-w64-clang-x86_64-python-numpy mingw-w64-clang-x86_64-python-setuptools > $MSYS2DIR/packages.txt
echo "{ pkgs } : [" > msys2_packages.nix echo "{ pkgs } : [" > msys2_packages.nix
while read package; do while read package; do

View File

@ -1,350 +1,344 @@
{ pkgs } : [ { pkgs } : [
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-libwinpthread-git-11.0.0.r198.g93ca95b32-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-libffi-3.4.4-1-any.pkg.tar.zst";
sha256 = "1zv1s7jamj6m4b7l05s185cslyiclp1r5vhxv7lj16gz21n800vg"; sha256 = "0mws1g7w11riczc168x7kzb8nl74iry4bzkb72nspw1vmlblxfy6";
name = "mingw-w64-x86_64-libwinpthread-git-11.0.0.r198.g93ca95b32-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-libffi-3.4.4-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-gcc-libs-13.2.0-2-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-libunwind-17.0.4-1-any.pkg.tar.zst";
sha256 = "0bxdyy0w0ld437skyl6wmp9d1j2jj71s8sw7wcysgv40y72b9jxc"; sha256 = "1748ncih1zj4vnj9c0gcp5rf21gm2pn9xdy2hrigp2pvfchrnmwn";
name = "mingw-w64-x86_64-gcc-libs-13.2.0-2-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-libunwind-17.0.4-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-zstd-1.5.5-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-libc++-17.0.4-1-any.pkg.tar.zst";
sha256 = "19jr14l5anl1qr1lvcmdpnpgyxghf2mds2j7iiq4j99kfg7ig2s0"; sha256 = "00waw5qmpycib7xhk6aywqgqg8y26q2xbm8m4za7mpy04g2alav4";
name = "mingw-w64-x86_64-zstd-1.5.5-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-libc++-17.0.4-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-binutils-2.41-2-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-zlib-1.3-1-any.pkg.tar.zst";
sha256 = "1r2pf8sdhhs8mlyzagfl209d6xa92yqf0nzqvbd0ggapijni02ga"; sha256 = "0rfwz7czvwa8clickjw1kd114miyifxf1s2v9mxffkaivm45f62v";
name = "mingw-w64-x86_64-binutils-2.41-2-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-zlib-1.3-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-headers-git-11.0.0.r198.g93ca95b32-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-libiconv-1.17-3-any.pkg.tar.zst";
sha256 = "19sgcf61vrs5cpzxskb6g279srsc49mhq4840snf45lrsxfrk6ja"; sha256 = "1hxmdgivb86h7wz9hcp0had99ngv157w1fbjg7cgy068zv787m8w";
name = "mingw-w64-x86_64-headers-git-11.0.0.r198.g93ca95b32-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-libiconv-1.17-3-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-crt-git-11.0.0.r198.g93ca95b32-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-expat-2.5.0-1-any.pkg.tar.zst";
sha256 = "04717li07m2f3q608ir83vqayixw38mkr9sjk2xjhaam5hhl96lq"; sha256 = "1gi9ckh48k64gras307f6pf5y558hj80izlxri8cnwvzzmmra8dg";
name = "mingw-w64-x86_64-crt-git-11.0.0.r198.g93ca95b32-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-expat-2.5.0-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-gmp-6.3.0-2-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-gettext-0.22.4-3-any.pkg.tar.zst";
sha256 = "1k0ma22hyn5m2m8kflpmscwm2p1v53pzd93fnind9bf4fhwl6949"; sha256 = "0i2gbhzvcy8cq7gnd9zsjw47jmn8gsq5pam5j3yn84jn578f3mfi";
name = "mingw-w64-x86_64-gmp-6.3.0-2-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-gettext-0.22.4-3-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-isl-0.26-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-xz-5.4.5-1-any.pkg.tar.zst";
sha256 = "0hfycibi23xkah9sw60n4ka786l8vmlc67d2waw9mwqqljdmx7pr"; sha256 = "1niky9s7qq0434ljma3f9m8yybcifkvkxwhk580crzb2ifpmqxc3";
name = "mingw-w64-x86_64-isl-0.26-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-xz-5.4.5-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-libiconv-1.17-3-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-libxml2-2.12.1-1-any.pkg.tar.zst";
sha256 = "061dlpg69ph2205xabshya827m6dqchxxn3jvhnnicja6bsb8ivh"; sha256 = "0lajdhkqv3hrfmnf9wa0ddqpr9z8rvb037rv0ss60g2n0b92s5gk";
name = "mingw-w64-x86_64-libiconv-1.17-3-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-libxml2-2.12.1-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-mpfr-4.2.1-2-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-zstd-1.5.5-1-any.pkg.tar.zst";
sha256 = "1j96kipr7mzawngjhi9m0rh2lhylmggg1mkgkipw9ssrsxxf7g97"; sha256 = "07739wmwgxf0d6db4p8w302a6jwcm01aafr1s8jvcl5k1h5a1m2m";
name = "mingw-w64-x86_64-mpfr-4.2.1-2-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-zstd-1.5.5-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-mpc-1.3.1-2-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-llvm-libs-17.0.4-1-any.pkg.tar.zst";
sha256 = "04md7pzz6rwvlsxzgxn8zc6l5lmqn1w2dg9f5xdf13qbl9zfm615"; sha256 = "13gpp9ah8g4ggzmgsskwcrck16rvjwp464i5vyw9zwm88bdhmz93";
name = "mingw-w64-x86_64-mpc-1.3.1-2-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-llvm-libs-17.0.4-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-windows-default-manifest-6.4-4-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-llvm-17.0.4-1-any.pkg.tar.zst";
sha256 = "1ylipf8k9j7bgmwndkib2l29mds394i7jcij7a6ciag4kynlhsvi"; sha256 = "103zfg4ypmzhy0gd02arjydca2l4ak2mai3g1xrck83l15v85f9h";
name = "mingw-w64-x86_64-windows-default-manifest-6.4-4-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-llvm-17.0.4-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-winpthreads-git-11.0.0.r198.g93ca95b32-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-compiler-rt-17.0.4-1-any.pkg.tar.zst";
sha256 = "171blcxd721pp0881blbid8vdbc18fx2lwyzk2prsnjhlf9yampj"; sha256 = "0n38jb9gl3zmy7f07bqzpk70k00hdrnasrclhcxgbn4ylzlca07w";
name = "mingw-w64-x86_64-winpthreads-git-11.0.0.r198.g93ca95b32-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-compiler-rt-17.0.4-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-zlib-1.3-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-headers-git-11.0.0.r404.g3a137bd87-1-any.pkg.tar.zst";
sha256 = "167g32vk257sbfmz85azgjs01cnfkjip0gks6y3vgl97i9d6qji5"; sha256 = "1wisa5j86xn8fanx4ks5pkj2hx0k89cippcap6c6yf6d3qmj4mvr";
name = "mingw-w64-x86_64-zlib-1.3-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-headers-git-11.0.0.r404.g3a137bd87-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-gcc-13.2.0-2-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-crt-git-11.0.0.r404.g3a137bd87-1-any.pkg.tar.zst";
sha256 = "09v6iz3iyp8w3ynw7wrs2qh54vr2kjpwfbv5rya8dskdx4sp2bvd"; sha256 = "0x1x3rnxivm58sqjx5v5smnzl5hdinx4qrjgkn59nylcd24fvnk4";
name = "mingw-w64-x86_64-gcc-13.2.0-2-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-crt-git-11.0.0.r404.g3a137bd87-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-c-ares-1.19.1-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-lld-17.0.4-1-any.pkg.tar.zst";
sha256 = "0mnkybl3ymxljvg4z5lnww14k29axyxg6ww30mxz6p5i2kqb0vik"; sha256 = "1028iymsay6smk856xfyccl7pkcxzigqlrhj4sgz4xxqij7xqnp0";
name = "mingw-w64-x86_64-c-ares-1.19.1-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-lld-17.0.4-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-brotli-1.1.0-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-libwinpthread-git-11.0.0.r404.g3a137bd87-1-any.pkg.tar.zst";
sha256 = "1ix63yg59k6wq32xgs64i3i2hqsi9f5qj5qw5apsfr1sgy9zlppm"; sha256 = "01q7r8mvn60yc0bxlhfbb1rx8w6lbvf1bd0xfaycqmc25b8vnfnp";
name = "mingw-w64-x86_64-brotli-1.1.0-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-libwinpthread-git-11.0.0.r404.g3a137bd87-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-expat-2.5.0-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-winpthreads-git-11.0.0.r404.g3a137bd87-1-any.pkg.tar.zst";
sha256 = "09hrzvdfkr2zaq239z87m1j3zyq0pvjhsyikg65wrbljrir6wc6r"; sha256 = "0f5828injyxhy8vxkv02wmk4fh6x5gsqnkr97p50vz692fxkwk48";
name = "mingw-w64-x86_64-expat-2.5.0-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-winpthreads-git-11.0.0.r404.g3a137bd87-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-gettext-0.21.1-2-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-clang-17.0.4-1-any.pkg.tar.zst";
sha256 = "0gj9qgxph9qw1x3y9ijacxi4ia90vzgkmg5jvl99pdq55h3xxl9x"; sha256 = "1adfijlky02waz6gm2rx32rd413ws5rphkpybihpc8hi11yag761";
name = "mingw-w64-x86_64-gettext-0.21.1-2-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-clang-17.0.4-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-libunistring-1.1-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-c-ares-1.22.1-1-any.pkg.tar.zst";
sha256 = "1zpmarlb2j0q2hcv30xl6c0mm3pwdjp7fh9mqpb6y0yygj1ivcza"; sha256 = "0bv8n3862krxhlmz0lxqq71y40dy4flpjvb7adl5a96jixgsbxav";
name = "mingw-w64-x86_64-libunistring-1.1-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-c-ares-1.22.1-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-libidn2-2.3.4-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-brotli-1.1.0-1-any.pkg.tar.zst";
sha256 = "0z926vsxz61m5zxdarah3zc4n253ksykxvb72qg86kcxcl3z0ppc"; sha256 = "113mha41q53cx0hw13cq1xdf7zbsd58sh8cl1cd7xzg1q69n60w2";
name = "mingw-w64-x86_64-libidn2-2.3.4-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-brotli-1.1.0-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-libpsl-0.21.2-4-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-libunistring-1.1-1-any.pkg.tar.zst";
sha256 = "0scpar3qp91y920c065y7jcvzfpmxx5vva9ybgxkk4df8a8mrbs9"; sha256 = "16myvbg33q5s7jl30w5qd8n8f1r05335ms8r61234vn52n32l2c4";
name = "mingw-w64-x86_64-libpsl-0.21.2-4-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-libunistring-1.1-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-libtasn1-4.19.0-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-libidn2-2.3.4-1-any.pkg.tar.zst";
sha256 = "09bgm2y25jyjm0pwn2imnr30nxzdd7j71ifmxkpabaqkpsfa5av5"; sha256 = "105valrldri39sx7d5zdscxgsz9px382f8vbbl2zpr2xzb3jq8p8";
name = "mingw-w64-x86_64-libtasn1-4.19.0-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-libidn2-2.3.4-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-libffi-3.4.4-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-libpsl-0.21.2-4-any.pkg.tar.zst";
sha256 = "1na3giynh9f3i0xg2mr0dm4bm6zhv8h908rrrv4kcxfawr8nyjdy"; sha256 = "0h4inq6prhiipl3h5k9br9rz5mih123b8n12wiwp2qck0h2q3x98";
name = "mingw-w64-x86_64-libffi-3.4.4-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-libpsl-0.21.2-4-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-p11-kit-0.25.0-2-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-libtasn1-4.19.0-1-any.pkg.tar.zst";
sha256 = "0j6w4hijyclv2av8wxldqdznyyycsmx00kshbs8kpk2wd5gz1scs"; sha256 = "19m59mjxww26ah2gk9c0i512fmqpyaj6r5na564kmg6wpwvkihcj";
name = "mingw-w64-x86_64-p11-kit-0.25.0-2-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-libtasn1-4.19.0-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-ca-certificates-20230311-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-p11-kit-0.25.3-1-any.pkg.tar.zst";
sha256 = "1rcxxlpmvian8c2d9bmnx5hldzvzz4wybz5wp9pjryps1rmzylyx"; sha256 = "19330k2jxpzm552m7j116hz8qrn2d14h9ybi0lcmkj4c1l25m6mf";
name = "mingw-w64-x86_64-ca-certificates-20230311-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-p11-kit-0.25.3-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-openssl-3.1.3-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-ca-certificates-20230311-1-any.pkg.tar.zst";
sha256 = "1vi1zxb5lvgxpmk80giqahqrjh2lv06r2ah4hf55jzjsi1mmcard"; sha256 = "00hdl239695xi5bgld7a1ssp6kapkb9az02dpx80vmz7mqg6wwxx";
name = "mingw-w64-x86_64-openssl-3.1.3-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-ca-certificates-20230311-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-libssh2-1.11.0-2-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-openssl-3.2.0-1-any.pkg.tar.zst";
sha256 = "0h4hfsig3n7grp7hn7vn16af6x122hc220llpmd8aii3d3jwc8d1"; sha256 = "1623bkf4bjwf4cs1j5f6c37gwj4z775kjk4jswwy58r61yimwnd5";
name = "mingw-w64-x86_64-libssh2-1.11.0-2-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-openssl-3.2.0-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-nghttp2-1.56.0-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-libssh2-1.11.0-2-any.pkg.tar.zst";
sha256 = "1jxn8g0w5qlkfb30bllwsm8vjfnk5952x8z8rq3wbawdncwsgvmk"; sha256 = "0l2m823gm1rvnjmqm5ads17mxz1bhpzai5ixyhnkpzrsjxd1ygy5";
name = "mingw-w64-x86_64-nghttp2-1.56.0-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-libssh2-1.11.0-2-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-curl-8.3.0-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-nghttp2-1.58.0-1-any.pkg.tar.zst";
sha256 = "03gkb36fp079gd2hi980qk1k2baly17ca457ah1gjcmc6p56jx6d"; sha256 = "00f7raqmky43v9h2356yzfbvbhkbsjpc17n6ksgpv66h31svna6q";
name = "mingw-w64-x86_64-curl-8.3.0-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-nghttp2-1.58.0-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-xz-5.4.4-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-curl-8.4.0-2-any.pkg.tar.zst";
sha256 = "0drcmy0x3dydl19slxv64aw8f29a1kxyzx7zj25nnr47qg1w5ycp"; sha256 = "1qi446lq1qqq45xn7fmasfb914jhahqc0cvpnqi8vrp9vlk9dsw3";
name = "mingw-w64-x86_64-xz-5.4.4-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-curl-8.4.0-2-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-libxml2-2.11.5-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-rust-1.74.0-1-any.pkg.tar.zst";
sha256 = "0z1nynr2ip1js3p8rlj5da1sfrm1071s6cn22qwpzk3j6zfjzanv"; sha256 = "071xpmfsnr7j7ycf6w8kyg41fxs3dclnjrcp7grinck5bb5zxn6s";
name = "mingw-w64-x86_64-libxml2-2.11.5-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-rust-1.74.0-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-rust-1.72.1-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-pkgconf-1~2.1.0-1-any.pkg.tar.zst";
sha256 = "0dq01ah76ra5y64kp1xwjhy5rsv7fxh1hnfjzr6l3x26d1hjwgsi"; sha256 = "04y364mzx2sj984cdxq187fg73hzkrzvbpsr5d86xfzrag789nh3";
name = "mingw-w64-x86_64-rust-1.72.1-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-pkgconf-12.1.0-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-pkgconf-1~2.0.3-2-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-jsoncpp-1.9.5-2-any.pkg.tar.zst";
sha256 = "0wkgwk57d6kyljjs0zvlrjp7k87s9b061cvzy0b8iy7r8wql31py"; sha256 = "0cpy76crngj5dfg9f4l216ry0wcavp0nabyc0b9g676rg6400qas";
name = "mingw-w64-x86_64-pkgconf-12.0.3-2-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-jsoncpp-1.9.5-2-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-jsoncpp-1.9.5-2-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-bzip2-1.0.8-3-any.pkg.tar.zst";
sha256 = "0wjf5cycjxwbaxvk4xmzhj4hnpl1mq6ddqj5lcbdcrvsc13nj8ll"; sha256 = "1n8zf2kk1xj7wiszp6mjchy1yzpalddbj0cj17qm625ags2vzflm";
name = "mingw-w64-x86_64-jsoncpp-1.9.5-2-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-bzip2-1.0.8-3-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-bzip2-1.0.8-3-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-libb2-0.98.1-2-any.pkg.tar.zst";
sha256 = "1dki26kz4pmr9q3gp3dirrvrwkcv38b9sjrb9slrq4yw31ycjgk5"; sha256 = "0555dvb2xs6695sz5ndrx6y0cz3qa5cg0m5v8q1md13ssg76vlh6";
name = "mingw-w64-x86_64-bzip2-1.0.8-3-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-libb2-0.98.1-2-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-libb2-0.98.1-2-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-lz4-1.9.4-1-any.pkg.tar.zst";
sha256 = "1nj669rn1i6fxrwmsqmr9n49p34wxvhn0xlsn9spr6aq1hz73b41"; sha256 = "0nn7cy25j53q5ckkx4n4f77w00xdwwf5wjswm374shvvs58nlln0";
name = "mingw-w64-x86_64-libb2-0.98.1-2-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-lz4-1.9.4-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-lz4-1.9.4-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-libtre-git-r128.6fb7206-2-any.pkg.tar.zst";
sha256 = "1mwyd94pwp1j3pgaa7j2i37d1xid1ynr0a42fl2pxgfmcj6hmqfi"; sha256 = "0bmdla75k0q88l93ql9ajbfag4vhdhyp0glzymljvcc7ir0r6f9r";
name = "mingw-w64-x86_64-lz4-1.9.4-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-libtre-git-r128.6fb7206-2-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-libtre-git-r128.6fb7206-2-any.pkg.tar.xz"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-libsystre-1.0.1-4-any.pkg.tar.zst";
sha256 = "0dp3ca83j8jlx32gml2qvqpwp5b42q8r98gf6hyiki45d910wb7x"; sha256 = "0x5ns8ld08gd9r5a98sqi3sm0vz588caaqw10ciix16sgyisfpdh";
name = "mingw-w64-x86_64-libtre-git-r128.6fb7206-2-any.pkg.tar.xz"; name = "mingw-w64-clang-x86_64-libsystre-1.0.1-4-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-libsystre-1.0.1-4-any.pkg.tar.xz"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-libarchive-3.7.2-1-any.pkg.tar.zst";
sha256 = "037gkzaaj8kp5nspcbc8ll64s9b3mj8d6m663lk1za94bq2axff1"; sha256 = "1p84yh6yzkdpmr02vyvgz16x5gycckah25jkdc2py09l7iw96bmw";
name = "mingw-w64-x86_64-libsystre-1.0.1-4-any.pkg.tar.xz"; name = "mingw-w64-clang-x86_64-libarchive-3.7.2-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-libarchive-3.7.2-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-libuv-1.47.0-1-any.pkg.tar.zst";
sha256 = "0p302zs5jgbbrv368yyjvbjmj4bmc1qxb0dp7s4wwafwnjqfm3vw"; sha256 = "1ch8g0mp13dmwi7sc6qxjcx18s1w0bsdl5lhkjmx5ccz55sspnyf";
name = "mingw-w64-x86_64-libarchive-3.7.2-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-libuv-1.47.0-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-libuv-1.46.0-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-ninja-1.11.1-3-any.pkg.tar.zst";
sha256 = "1pasn07awq2mrqzsf1162aa5xlq81745mxkzir0z7cx6smrfqiwb"; sha256 = "13wjfmyfr952n3ydpldjlwx1nla5xpyvr96ng8pfbyw4z900v5ms";
name = "mingw-w64-x86_64-libuv-1.46.0-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-ninja-1.11.1-3-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-ninja-1.11.1-3-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-rhash-1.4.3-1-any.pkg.tar.zst";
sha256 = "0494d54qxax9d2gz11vhm7342311k4s6mf6zy5yq2ka07qfzckcg"; sha256 = "16ghg6894gb3lcrcpc8g1jd7524djnsjrqcr3krqlzskfv51hgj6";
name = "mingw-w64-x86_64-ninja-1.11.1-3-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-rhash-1.4.3-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-rhash-1.4.3-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-cmake-3.27.8-1-any.pkg.tar.zst";
sha256 = "1nd0iqlx1vmn079i24i07r4kqfr3yr0apnzsgcx8qd5cyvwnl7w6"; sha256 = "1hm5975q0kfd0z502qpxq1imwvby3qb93jzhbvrg2fz9zf5d31rg";
name = "mingw-w64-x86_64-rhash-1.4.3-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-cmake-3.27.8-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-cmake-3.27.6-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-mpdecimal-2.5.1-1-any.pkg.tar.zst";
sha256 = "0vhnij28yk7i068b65m1gsmswz0r8nl3vzvx3c9n3cncv6h6m5hs"; sha256 = "0zm9pqcgjk9a8ql6hxcxh477wvvyimndcisd6zrr6y8m5vvklsdi";
name = "mingw-w64-x86_64-cmake-3.27.6-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-mpdecimal-2.5.1-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-mpdecimal-2.5.1-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-ncurses-6.4.20230708-1-any.pkg.tar.zst";
sha256 = "0cpyacmciyzbsar1aka5y592g2gpa4i6a58j3bjdmfjdnpm0j08a"; sha256 = "0l960cf4m558kx6dwahl9z2zdb9vlqd7qgk39kg924mzrfjrsvv5";
name = "mingw-w64-x86_64-mpdecimal-2.5.1-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-ncurses-6.4.20230708-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-ncurses-6.4.20230708-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-termcap-1.3.1-7-any.pkg.tar.zst";
sha256 = "1bpjn6rv85q3rdcdgs7fml140aar93hv649hhqx47za26mjnsdiv"; sha256 = "17ha468qavwin800cc3b7c3xdggwk2gakasfxg7jdx7616d99l0n";
name = "mingw-w64-x86_64-ncurses-6.4.20230708-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-termcap-1.3.1-7-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-termcap-1.3.1-7-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-readline-8.2.001-6-any.pkg.tar.zst";
sha256 = "1s51i2fwy1mrzmxsgr1vv87wlmb3bk88yipqalfldvy3xdgjgjh4"; sha256 = "1aw1qxjvifkzxnn52l6hba1kcj2dci8llzzj29zbvbq5hgllf6dv";
name = "mingw-w64-x86_64-termcap-1.3.1-7-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-readline-8.2.001-6-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-readline-8.2.001-6-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-tcl-8.6.12-2-any.pkg.tar.zst";
sha256 = "0a6s6kq2hmz96cg7hxzcgldh16sk7dvpzfdfqchq3c07rwzhqhiq"; sha256 = "06r7ni7m1vf83ms8ha3glalc5rfriiffh7v644jmnvzs5g9x0pzb";
name = "mingw-w64-x86_64-readline-8.2.001-6-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-tcl-8.6.12-2-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-tcl-8.6.12-2-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-sqlite3-3.44.0-1-any.pkg.tar.zst";
sha256 = "17lyrkyh76lh0ghk19d91kwicms6lxshhhb6n3zh748awfvihknm"; sha256 = "022vy54ph6kxmgafbsmgpclvd55ljarvc4k7497ka03g7465zq6j";
name = "mingw-w64-x86_64-tcl-8.6.12-2-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-sqlite3-3.44.0-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-sqlite3-3.43.1-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-tk-8.6.12-2-any.pkg.tar.zst";
sha256 = "05csh3sa6g5nnfmry50w6p2j4v7fqylmlgnny5cimm350ppmmkka"; sha256 = "0pi74q91vl6vw8vvmmwnvrgai3b1aanp0zhca5qsmv8ljh2wdgzx";
name = "mingw-w64-x86_64-sqlite3-3.43.1-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-tk-8.6.12-2-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-tk-8.6.12-2-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-tzdata-2023c-1-any.pkg.tar.zst";
sha256 = "0j6nvwc0a1cc2k4akq3095r1rfhprslf8jpr07ypcjb91q5s3yfi"; sha256 = "018qw8lk5r7gqvavnl1414gmbd4bx22528a7bjk4injfr3cib9c2";
name = "mingw-w64-x86_64-tk-8.6.12-2-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-tzdata-2023c-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-tzdata-2023c-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-python-3.11.6-2-any.pkg.tar.zst";
sha256 = "0ifavpqi1ykn9962ic4sh5l18y2mvz9pj6742fgw85s9wixbj7fl"; sha256 = "0j6wkjjay52f4mgvfagi7xql4v74dizhmwdx07n2fixr7j1lg6n7";
name = "mingw-w64-x86_64-tzdata-2023c-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-python-3.11.6-2-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-python-3.11.6-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-openmp-17.0.4-1-any.pkg.tar.zst";
sha256 = "0s4z65i3p0arwjry877q9q154h58b3wd35svifpj2c1j7frr41vi"; sha256 = "1y2cf43fcyb1qv4kn0h0mzljmibaqklcj167krwxq5ymfbipy1yw";
name = "mingw-w64-x86_64-python-3.11.6-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-openmp-17.0.4-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-gcc-libgfortran-13.2.0-2-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-openblas-0.3.25-1-any.pkg.tar.zst";
sha256 = "150k73v8g71wrp855f747mal009cf34lbpv8xzbibj50m3g6yxvv"; sha256 = "1789hd7sc249vbzppqqg56i080c8kc6bj6qngn9rjvzcdllh0d07";
name = "mingw-w64-x86_64-gcc-libgfortran-13.2.0-2-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-openblas-0.3.25-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-openblas-0.3.24-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-python-numpy-1.26.2-1-any.pkg.tar.zst";
sha256 = "0j2aka8bml2j2aszxsjy5gp8xqvdxw3s292pd7iarzn1kliwv84j"; sha256 = "1njbxlxha05c8fzm7yl3ksjlpanh5jxn1z1s06iv9knx2zmqjk6f";
name = "mingw-w64-x86_64-openblas-0.3.24-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-python-numpy-1.26.2-1-any.pkg.tar.zst";
}) })
(pkgs.fetchurl { (pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-python-numpy-1.25.2-1-any.pkg.tar.zst"; url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-python-setuptools-68.2.2-1-any.pkg.tar.zst";
sha256 = "0vjb2qps0kzzcjhjrh11h661i9q1hmzi08jvirqyslayp3jmbkd9"; sha256 = "16m1ph7yq3mqzaaaka5vij27jzaw59lpxwbmpdxkcp8lb6h5xcn9";
name = "mingw-w64-x86_64-python-numpy-1.25.2-1-any.pkg.tar.zst"; name = "mingw-w64-clang-x86_64-python-setuptools-68.2.2-1-any.pkg.tar.zst";
})
(pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-python-setuptools-68.2.2-1-any.pkg.tar.zst";
sha256 = "0hci3vran7cw4hnr17b04xcpwl322ffvxf9sgv3793rpx7fx5h7a";
name = "mingw-w64-x86_64-python-setuptools-68.2.2-1-any.pkg.tar.zst";
}) })
] ]