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__
/target
windows/msys2
nix/windows/msys2

124
Cargo.lock generated
View File

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

View File

@ -23,7 +23,7 @@ After setting up Nix as above, use ``nix shell git+https://github.com/m-labs/art
### 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]
SigLevel = Optional TrustAll
@ -33,11 +33,9 @@ Server = https://msys2.m-labs.hk/artiq-nac3
Then run the following commands:
```
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
This repository contains:

View File

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

View File

@ -1,7 +1,7 @@
{
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 }:
let
@ -9,7 +9,12 @@
in rec {
packages.x86_64-linux = rec {
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 (
pkgs.rustPlatform.buildRustPackage rec {
name = "nac3artiq";
@ -19,7 +24,7 @@
lockFile = ./Cargo.lock;
};
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 ];
checkInputs = [ (pkgs.python3.withPackages(ps: [ ps.numpy ps.scipy ])) ];
checkPhase =
@ -59,7 +64,7 @@
name = "nac3artiq-instrumented";
src = self;
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 ];
cargoBuildFlags = [ "--package" "nac3artiq" "--features" "init-llvm-profile" ];
doCheck = false;
@ -87,8 +92,8 @@
(pkgs.fetchFromGitHub {
owner = "m-labs";
repo = "artiq";
rev = "5bbac04bef170cddb608b5dc8d9e6778cc7b31e8";
sha256 = "sha256-TnRS2NrQaDiDzUsmfjkZh69xi2XC9v+4hnkedycAo0k=";
rev = "4c189f8c0576111733bb6ff934035c080c8ccc58";
sha256 = "sha256-gYGzmfaIoftKFDwn8AybUenYtIpux+tHGMu51WgwA8A=";
})
];
buildInputs = [
@ -121,7 +126,7 @@
name = "nac3artiq-pgo";
src = self;
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 ];
cargoBuildFlags = [ "--package" "nac3artiq" ];
cargoTestFlags = [ "--package" "nac3ast" "--package" "nac3parser" "--package" "nac3core" "--package" "nac3artiq" ];
@ -143,8 +148,7 @@
# build dependencies
packages.x86_64-linux.llvm-nac3
llvmPackages_14.clang # demo
packages.x86_64-linux.clang-unwrapped # IRRT
pkgs.llvmPackages_14.llvm.out # IRRT
packages.x86_64-linux.llvm-tools-irrt
cargo
rustc
# runtime dependencies

View File

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

View File

@ -145,7 +145,8 @@ impl<'a> ArtiqCodeGenerator<'a> {
let end_store = self.gen_store_target(
ctx,
&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);
}
@ -261,7 +262,9 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> {
node: ExprKind::Name { id: start, ctx: name_ctx.clone() },
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);
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() },
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);
self.end = Some(end_expr);
self.name_counter += 1;

View File

@ -75,6 +75,7 @@ pub struct PrimitivePythonId {
list: u64,
tuple: u64,
typevar: u64,
const_generic_dummy: u64,
none: u64,
exception: u64,
generic_alias: (u64, u64),
@ -877,6 +878,15 @@ impl Nac3 {
.extract()
.unwrap(),
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"),
int32: get_attr_id(numpy_mod, "int32"),
int64: get_attr_id(numpy_mod, "int64"),

View File

@ -266,10 +266,12 @@ impl InnerResolver {
Ok(Ok(ty))
}
// 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
// the `bool` value returned indicates whether they are instantiated or not
/// 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
///
/// the `bool` value returned indicates whether they are instantiated or not
fn get_pyty_obj_type(
&self,
py: Python,
@ -345,13 +347,21 @@ impl InnerResolver {
}
} else if ty_ty_id == self.primitive_ids.typevar {
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 mut result: Vec<Type> = vec![];
let needs_defer = self.deferred_eval_store.needs_defer.load(Relaxed);
let mut is_const_generic = false;
for i in 0usize.. {
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);
} else {
result.push({
@ -375,17 +385,28 @@ impl InnerResolver {
break;
}
}
if needs_defer {
if !is_const_generic && needs_defer {
self.deferred_eval_store.store.write()
.push((result.clone(),
constraints.extract()?,
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)))
} else if ty_ty_id == self.primitive_ids.generic_alias.0
|| ty_ty_id == self.primitive_ids.generic_alias.1

View File

@ -26,7 +26,7 @@ pub struct Location {
impl fmt::Display for Location {
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",
"-",
];
let output = Command::new("clang-unwrapped")
let output = Command::new("clang-irrt")
.args(FLAG)
.output()
.map(|o| {
@ -61,7 +61,7 @@ fn main() {
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())
.arg("-o")
.arg(out_path.join("irrt.bc"))

View File

@ -207,12 +207,12 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
generator: &mut dyn CodeGenerator,
value: &Constant,
ty: Type,
) -> BasicValueEnum<'ctx> {
) -> Option<BasicValueEnum<'ctx>> {
match value {
Constant::Bool(v) => {
assert!(self.unifier.unioned(ty, self.primitives.bool));
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) => {
let ty = if self.unifier.unioned(ty, self.primitives.int32)
@ -226,28 +226,33 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
} else {
unreachable!();
};
ty.const_int(*val as u64, false).into()
Some(ty.const_int(*val as u64, false).into())
}
Constant::Float(v) => {
assert!(self.unifier.unioned(ty, self.primitives.float));
let ty = self.ctx.f64_type();
ty.const_float(*v).into()
Some(ty.const_float(*v).into())
}
Constant::Tuple(v) => {
let ty = self.unifier.get_ty(ty);
let types =
if let TypeEnum::TTuple { ty } = &*ty { ty.clone() } else { unreachable!() };
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();
let types = values.iter().map(BasicValueEnum::get_type).collect_vec();
let ty = self.ctx.struct_type(&types, false);
ty.const_named_struct(&values).into()
if values.len() == v.len() {
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) => {
assert!(self.unifier.unioned(ty, self.primitives.str));
if let Some(v) = self.const_strings.get(v) {
*v
Some(*v)
} else {
let str_ptr =
self.builder.build_global_string_ptr(v, "const").as_pointer_value().into();
@ -256,9 +261,22 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
let val =
ty.into_struct_type().const_named_struct(&[str_ptr, size.into()]).into();
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!(),
}
}
@ -481,7 +499,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
generator: &mut dyn CodeGenerator,
s: S,
) -> 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(
@ -935,7 +953,7 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>(
generator: &mut G,
ctx: &mut CodeGenContext<'ctx, 'a>,
expr: &Expr<Option<Type>>,
) -> Result<BasicValueEnum<'ctx>, String> {
) -> Result<Option<BasicValueEnum<'ctx>>, String> {
if let ExprKind::ListComp { elt, generators } = &expr.node {
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);
let Comprehension { target, iter, ifs, .. } = &generators[0];
let iter_val = generator.gen_expr(ctx, iter)?
.unwrap()
.to_basic_value_enum(ctx, generator, iter.custom.unwrap())?;
let iter_val = if let Some(v) = generator.gen_expr(ctx, iter)? {
v.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 size_t = generator.get_size_type(ctx.ctx);
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"))
.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_conditional_branch(
@ -1049,12 +1074,25 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>(
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() {
let result = generator
.gen_expr(ctx, cond)?
.unwrap()
.to_basic_value_enum(ctx, generator, cond.custom.unwrap())?
.into_int_value();
let result = if let Some(v) = generator.gen_expr(ctx, cond)? {
v.to_basic_value_enum(ctx, generator, cond.custom.unwrap())?.into_int_value()
} else {
// Bail if the predicate is an ellipsis - Emit cont_bb contents in case the
// no element matches the predicate
emit_cont_bb(ctx);
return Ok(None)
};
let result = generator.bool_to_i1(ctx, result);
let succ = ctx.ctx.append_basic_block(current, "then");
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);
}
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 elem_ptr = unsafe { ctx.builder.build_gep(list_content, &[i], "elem_ptr") };
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"));
ctx.builder.build_unconditional_branch(test_bb);
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"));
emit_cont_bb(ctx);
Ok(list.into())
Ok(Some(list.into()))
} else {
unreachable!()
}
@ -1101,14 +1140,16 @@ pub fn gen_binop_expr<'ctx, 'a, G: CodeGenerator>(
) -> Result<Option<ValueEnum<'ctx>>, String> {
let ty1 = ctx.unifier.get_representative(left.custom.unwrap());
let ty2 = ctx.unifier.get_representative(right.custom.unwrap());
let left_val = generator
.gen_expr(ctx, left)?
.unwrap()
.to_basic_value_enum(ctx, generator, left.custom.unwrap())?;
let right_val = generator
.gen_expr(ctx, right)?
.unwrap()
.to_basic_value_enum(ctx, generator, right.custom.unwrap())?;
let left_val = if let Some(v) = generator.gen_expr(ctx, left)? {
v.to_basic_value_enum(ctx, generator, left.custom.unwrap())?
} else {
return Ok(None)
};
let right_val = if let Some(v) = generator.gen_expr(ctx, right)? {
v.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
// 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 {
ExprKind::Constant { value, .. } => {
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() => {
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
let elements = elts
.iter()
.map(|x| {
generator
.gen_expr(ctx, x)
.map_or_else(
Err,
|v| v.unwrap().to_basic_value_enum(ctx, generator, x.custom.unwrap())
)
})
.map(|x| generator.gen_expr(ctx, x))
.take_while(|v| !matches!(v, Ok(None)))
.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() {
if let TypeEnum::TList { ty } = &*ctx.unifier.get_ty(expr.custom.unwrap()) {
ctx.get_llvm_type(generator, *ty)
@ -1277,14 +1323,19 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
arr_str_ptr.into()
}
ExprKind::Tuple { elts, .. } => {
let element_val = elts
let elements_val = elts
.iter()
.map(|x| {
generator
.gen_expr(ctx, x)
.map_or_else(Err, |v| v.unwrap().to_basic_value_enum(ctx, generator, x.custom.unwrap()))
})
.map(|x| generator.gen_expr(ctx, x))
.take_while(|v| !matches!(v, Ok(None)))
.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 tuple_ty = ctx.ctx.struct_type(&element_ty, false);
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, .. } => {
// note that we would handle class methods directly in calls
match generator.gen_expr(ctx, value)?.unwrap() {
ValueEnum::Static(v) => v.get_field(*attr, ctx).map_or_else(|| {
match generator.gen_expr(ctx, value)? {
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 index = ctx.get_attr_index(value.custom.unwrap(), *attr);
Ok(ValueEnum::Dynamic(ctx.build_gep_and_load(
@ -1312,7 +1363,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
None,
))) as Result<_, String>
}, Ok)?,
ValueEnum::Dynamic(v) => {
Some(ValueEnum::Dynamic(v)) => {
let index = ctx.get_attr_index(value.custom.unwrap(), *attr);
ValueEnum::Dynamic(ctx.build_gep_and_load(
v.into_pointer_value(),
@ -1320,15 +1371,16 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
None,
))
}
None => return Ok(None),
}
}
ExprKind::BoolOp { op, values } => {
// requires conditional branches for short-circuiting...
let left = generator
.gen_expr(ctx, &values[0])?
.unwrap()
.to_basic_value_enum(ctx, generator, values[0].custom.unwrap())?
.into_int_value();
let left = if let Some(v) = generator.gen_expr(ctx, &values[0])? {
v.to_basic_value_enum(ctx, generator, values[0].custom.unwrap())?.into_int_value()
} else {
return Ok(None)
};
let left = generator.bool_to_i1(ctx, left);
let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap();
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);
let a = ctx.ctx.i8_type().const_int(1, false);
ctx.builder.build_unconditional_branch(cont_bb);
ctx.builder.position_at_end(b_bb);
let b = generator
.gen_expr(ctx, &values[1])?
.unwrap()
.to_basic_value_enum(ctx, generator, values[1].custom.unwrap())?
.into_int_value();
let b = generator.bool_to_i8(ctx, b);
ctx.builder.build_unconditional_branch(cont_bb);
(a, b)
let b = if let Some(v) = generator.gen_expr(ctx, &values[1])? {
let b = v.to_basic_value_enum(ctx, generator, values[1].custom.unwrap())?.into_int_value();
let b = generator.bool_to_i8(ctx, b);
ctx.builder.build_unconditional_branch(cont_bb);
Some(b)
} else {
None
};
(Some(a), b)
}
Boolop::And => {
ctx.builder.position_at_end(a_bb);
let a = generator
.gen_expr(ctx, &values[1])?
.unwrap()
.to_basic_value_enum(ctx, generator, values[1].custom.unwrap())?
.into_int_value();
let a = generator.bool_to_i8(ctx, a);
ctx.builder.build_unconditional_branch(cont_bb);
let a = if let Some(v) = generator.gen_expr(ctx, &values[1])? {
let a = v.to_basic_value_enum(ctx, generator, values[1].custom.unwrap())?.into_int_value();
let a = generator.bool_to_i8(ctx, a);
ctx.builder.build_unconditional_branch(cont_bb);
Some(a)
} else {
None
};
ctx.builder.position_at_end(b_bb);
let b = ctx.ctx.i8_type().const_zero();
ctx.builder.build_unconditional_branch(cont_bb);
(a, b)
(a, Some(b))
}
};
ctx.builder.position_at_end(cont_bb);
let phi = ctx.builder.build_phi(ctx.ctx.i8_type(), "");
phi.add_incoming(&[(&a, a_bb), (&b, b_bb)]);
phi.as_basic_value().into()
match (a, b) {
(Some(a), Some(b)) => {
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 } => {
return gen_binop_expr(generator, ctx, left, op, right, expr.location, false);
}
ExprKind::UnaryOp { op, operand } => {
let ty = ctx.unifier.get_representative(operand.custom.unwrap());
let val =
generator.gen_expr(ctx, operand)?
.unwrap()
.to_basic_value_enum(ctx, generator, operand.custom.unwrap())?;
let val = if let Some(v) = generator.gen_expr(ctx, operand)? {
v.to_basic_value_enum(ctx, generator, operand.custom.unwrap())?
} else {
return Ok(None)
};
if ty == ctx.primitives.bool {
let val = val.into_int_value();
match op {
@ -1415,7 +1484,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
}
}
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)| {
let ty = ctx.unifier.get_representative(lhs.custom.unwrap());
let current =
@ -1427,23 +1496,15 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
ctx.primitives.uint64,
].contains(&ty);
let (lhs, rhs) = if let (
BasicValueEnum::IntValue(lhs),
BasicValueEnum::IntValue(rhs),
) = (
generator
.gen_expr(ctx, lhs)?
.unwrap()
.to_basic_value_enum(ctx, generator, lhs.custom.unwrap())?,
generator
.gen_expr(ctx, rhs)?
.unwrap()
.to_basic_value_enum(ctx, generator, rhs.custom.unwrap())?,
) {
(lhs, rhs)
} else {
unreachable!()
};
let BasicValueEnum::IntValue(lhs) = (match generator.gen_expr(ctx, lhs)? {
Some(v) => v.to_basic_value_enum(ctx, generator, lhs.custom.unwrap())?,
None => return Ok(None),
}) else { unreachable!() };
let BasicValueEnum::IntValue(rhs) = (match generator.gen_expr(ctx, rhs)? {
Some(v) => v.to_basic_value_enum(ctx, generator, rhs.custom.unwrap())?,
None => return Ok(None),
}) else { unreachable!() };
let op = match op {
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")
} else if ty == ctx.primitives.float {
let (lhs, rhs) = if let (
BasicValueEnum::FloatValue(lhs),
BasicValueEnum::FloatValue(rhs),
) = (
generator
.gen_expr(ctx, lhs)?
.unwrap()
.to_basic_value_enum(ctx, generator, lhs.custom.unwrap())?,
generator
.gen_expr(ctx, rhs)?
.unwrap()
.to_basic_value_enum(ctx, generator, rhs.custom.unwrap())?,
) {
(lhs, rhs)
} else {
unreachable!()
};
let BasicValueEnum::FloatValue(lhs) = (match generator.gen_expr(ctx, lhs)? {
Some(v) => v.to_basic_value_enum(ctx, generator, lhs.custom.unwrap())?,
None => return Ok(None),
}) else { unreachable!() };
let BasicValueEnum::FloatValue(rhs) = (match generator.gen_expr(ctx, rhs)? {
Some(v) => v.to_basic_value_enum(ctx, generator, rhs.custom.unwrap())?,
None => return Ok(None),
}) else { unreachable!() };
let op = match op {
ast::Cmpop::Eq | ast::Cmpop::Is => inkwell::FloatPredicate::OEQ,
ast::Cmpop::NotEq => inkwell::FloatPredicate::ONE,
@ -1505,16 +1559,18 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
unimplemented!()
};
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 } => {
let test = generator
.gen_expr(ctx, test)?
.unwrap()
.to_basic_value_enum(ctx, generator, test.custom.unwrap())?
.into_int_value();
let test = match generator.gen_expr(ctx, test)? {
Some(v) => v.to_basic_value_enum(ctx, generator, test.custom.unwrap())?.into_int_value(),
None => return Ok(None),
};
let test = generator.bool_to_i1(ctx, test);
let body_ty = body.custom.unwrap();
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 cont_bb = ctx.ctx.append_basic_block(current, "cont");
ctx.builder.build_conditional_branch(test, then_bb, else_bb);
ctx.builder.position_at_end(then_bb);
let a = generator.gen_expr(ctx, body)?;
match result {
None => None,
Some(v) => {
let a = a.unwrap().to_basic_value_enum(ctx, generator, body.custom.unwrap())?;
Some(ctx.builder.build_store(v, a))
}
};
ctx.builder.build_unconditional_branch(cont_bb);
if let Some(a) = a {
match result {
None => None,
Some(v) => {
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.position_at_end(else_bb);
let b = generator.gen_expr(ctx, orelse)?;
match result {
None => None,
Some(v) => {
let b = b.unwrap().to_basic_value_enum(ctx, generator, orelse.custom.unwrap())?;
Some(ctx.builder.build_store(v, b))
}
};
ctx.builder.build_unconditional_branch(cont_bb);
if let Some(b) = b {
match result {
None => None,
Some(v) => {
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.position_at_end(cont_bb);
match result {
None => return Ok(None),
Some(v) => return Ok(Some(ctx.builder.build_load(v, "if_exp_val_load").into()))
if let Some(v) = result {
ctx.builder.build_load(v, "if_exp_val_load").into()
} else {
return Ok(None)
}
}
ExprKind::Call { func, args, keywords } => {
let mut params = args
.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<_>, _>>()?;
if params.len() < args.len() {
return Ok(None)
}
let kw_iter = keywords.iter().map(|kw| {
Ok((
Some(*kw.node.arg.as_ref().unwrap()),
@ -1593,7 +1664,11 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
.map(|v| v.into()));
}
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, .. } =
&*ctx.unifier.get_ty(value.custom.unwrap())
{
@ -1691,18 +1766,20 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
}
ExprKind::Subscript { value, slice, .. } => {
if let TypeEnum::TList { ty } = &*ctx.unifier.get_ty(value.custom.unwrap()) {
let v = generator
.gen_expr(ctx, value)?
.unwrap()
.to_basic_value_enum(ctx, generator, value.custom.unwrap())?
.into_pointer_value();
let v = if let Some(v) = generator.gen_expr(ctx, value)? {
v.to_basic_value_enum(ctx, generator, value.custom.unwrap())?.into_pointer_value()
} else {
return Ok(None)
};
let ty = ctx.get_llvm_type(generator, *ty);
let arr_ptr = ctx.build_gep_and_load(v, &[zero, zero], Some("arr.addr"))
.into_pointer_value();
if let ExprKind::Slice { lower, upper, step } = &slice.node {
let one = int32.const_int(1, false);
let (start, end, step) =
handle_slice_indices(lower, upper, step, ctx, generator, v)?;
let Some((start, end, step)) =
handle_slice_indices(lower, upper, step, ctx, generator, v)? else {
return Ok(None)
};
let length = calculate_len_for_slice_range(
generator,
ctx,
@ -1723,8 +1800,10 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
step,
);
let res_array_ret = allocate_list(generator, ctx, ty, length, Some("ret"));
let res_ind =
handle_slice_indices(&None, &None, &None, ctx, generator, res_array_ret)?;
let Some(res_ind) =
handle_slice_indices(&None, &None, &None, ctx, generator, res_array_ret)? else {
return Ok(None)
};
list_slice_assignment(
generator,
ctx,
@ -1739,11 +1818,11 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
let len = ctx
.build_gep_and_load(v, &[zero, int32.const_int(1, false)], Some("len"))
.into_int_value();
let raw_index = generator
.gen_expr(ctx, slice)?
.unwrap()
.to_basic_value_enum(ctx, generator, slice.custom.unwrap())?
.into_int_value();
let raw_index = if let Some(v) = generator.gen_expr(ctx, slice)? {
v.to_basic_value_enum(ctx, generator, slice.custom.unwrap())?.into_int_value()
} else {
return Ok(None)
};
let raw_index = ctx.builder.build_int_s_extend(
raw_index,
generator.get_size_type(ctx.ctx),
@ -1786,15 +1865,12 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
} else {
unreachable!("tuple subscript must be const int after type check");
};
let v = generator
.gen_expr(ctx, value)?
.unwrap();
match v {
ValueEnum::Dynamic(v) => {
match generator.gen_expr(ctx, value)? {
Some(ValueEnum::Dynamic(v)) => {
let v = v.into_struct_value();
ctx.builder.build_extract_value(v, index, "tup_elem").unwrap().into()
}
ValueEnum::Static(v) => {
Some(ValueEnum::Static(v)) => {
match v.get_tuple_element(index) {
Some(v) => v,
None => {
@ -1805,12 +1881,19 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
}
}
}
None => return Ok(None),
}
} else {
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!(),
}))
}

View File

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

View File

@ -158,33 +158,41 @@ pub fn handle_slice_indices<'a, 'ctx, G: CodeGenerator>(
ctx: &mut CodeGenContext<'ctx, 'a>,
generator: &mut G,
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 zero = int32.const_zero();
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.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.as_ref().map_or_else(
|| Ok(int32.const_zero()),
|s| handle_slice_index_bound(s, ctx, generator, length),
)?,
if let Some(s) = s.as_ref() {
match 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(
|| Ok(length),
|e| handle_slice_index_bound(e, ctx, generator, length),
)?;
let e = if let Some(s) = e.as_ref() {
match handle_slice_index_bound(s, ctx, generator, length)? {
Some(v) => v,
None => return Ok(None),
}
} else {
length
};
ctx.builder.build_int_sub(e, one, "final_end")
},
one,
),
(s, e, Some(step)) => {
let step = generator
.gen_expr(ctx, step)?
.unwrap()
.to_basic_value_enum(ctx, generator, ctx.primitives.int32)?
.into_int_value();
let step = if let Some(v) = generator.gen_expr(ctx, step)? {
v.to_basic_value_enum(ctx, generator, ctx.primitives.int32)?.into_int_value()
} else {
return Ok(None)
};
// assert step != 0, throw exception if not
let not_zero = ctx.builder.build_int_compare(
IntPredicate::NE,
@ -205,7 +213,9 @@ pub fn handle_slice_indices<'a, 'ctx, G: CodeGenerator>(
(
match 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
.build_select(
ctx.builder.build_and(
@ -228,7 +238,9 @@ pub fn handle_slice_indices<'a, 'ctx, G: CodeGenerator>(
},
match 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
.build_select(
neg,
@ -243,7 +255,7 @@ pub fn handle_slice_indices<'a, 'ctx, G: CodeGenerator>(
step,
)
}
})
}))
}
/// 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>,
generator: &mut G,
length: IntValue<'ctx>,
) -> Result<IntValue<'ctx>, String> {
) -> Result<Option<IntValue<'ctx>>, String> {
const SYMBOL: &str = "__nac3_slice_index_bound";
let func = ctx.module.get_function(SYMBOL).unwrap_or_else(|| {
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)
});
let i = generator.gen_expr(ctx, i)?.unwrap().to_basic_value_enum(ctx, generator, i.custom.unwrap())?;
Ok(ctx
let i = if let Some(v) = generator.gen_expr(ctx, i)? {
v.to_basic_value_enum(ctx, generator, i.custom.unwrap())?
} else {
return Ok(None)
};
Ok(Some(ctx
.builder
.build_call(func, &[i.into(), length.into()], "bounded_ind")
.try_as_basic_value()
.left()
.unwrap()
.into_int_value())
.into_int_value()))
}
/// 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>,
pattern: &Expr<Option<Type>>,
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
// and we flatten nested tuples
Ok(match &pattern.node {
Ok(Some(match &pattern.node {
ExprKind::Name { id, .. } => match ctx.var_assignment.get(id) {
None => {
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, .. } => {
let index = ctx.get_attr_index(value.custom.unwrap(), *attr);
let val = generator.gen_expr(ctx, value)?.unwrap().to_basic_value_enum(
ctx,
generator,
value.custom.unwrap(),
)?;
let val = if let Some(v) = generator.gen_expr(ctx, value)? {
v.to_basic_value_enum(ctx, generator, value.custom.unwrap())?
} else {
return Ok(None)
};
let ptr = if let BasicValueEnum::PointerValue(v) = val {
v
} else {
@ -107,19 +107,19 @@ pub fn gen_store_target<'ctx, 'a, G: CodeGenerator>(
));
let i32_type = ctx.ctx.i32_type();
let zero = i32_type.const_zero();
let v = generator
.gen_expr(ctx, value)?
.unwrap()
.to_basic_value_enum(ctx, generator, value.custom.unwrap())?
.into_pointer_value();
let v = if let Some(v) = generator.gen_expr(ctx, value)? {
v.to_basic_value_enum(ctx, generator, value.custom.unwrap())?.into_pointer_value()
} else {
return Ok(None)
};
let len = ctx
.build_gep_and_load(v, &[zero, i32_type.const_int(1, false)], Some("len"))
.into_int_value();
let raw_index = generator
.gen_expr(ctx, slice)?
.unwrap()
.to_basic_value_enum(ctx, generator, slice.custom.unwrap())?
.into_int_value();
let raw_index = if let Some(v) = generator.gen_expr(ctx, slice)? {
v.to_basic_value_enum(ctx, generator, slice.custom.unwrap())?.into_int_value()
} else {
return Ok(None)
};
let raw_index = ctx.builder.build_int_s_extend(
raw_index,
generator.get_size_type(ctx.ctx),
@ -161,7 +161,7 @@ pub fn gen_store_target<'ctx, 'a, G: CodeGenerator>(
}
}
_ => unreachable!(),
})
}))
}
/// See [CodeGenerator::gen_assign].
@ -196,8 +196,10 @@ pub fn gen_assign<'ctx, 'a, G: CodeGenerator>(
.unwrap()
.to_basic_value_enum(ctx, generator, ls.custom.unwrap())?
.into_pointer_value();
let (start, end, step) =
handle_slice_indices(lower, upper, step, ctx, generator, ls)?;
let Some((start, end, step)) =
handle_slice_indices(lower, upper, step, ctx, generator, ls)? else {
return Ok(())
};
let value = value
.to_basic_value_enum(ctx, generator, target.custom.unwrap())?
.into_pointer_value();
@ -207,7 +209,9 @@ pub fn gen_assign<'ctx, 'a, G: CodeGenerator>(
} else {
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)
} else {
unreachable!()
@ -219,7 +223,9 @@ pub fn gen_assign<'ctx, 'a, G: CodeGenerator>(
} else {
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 {
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
let loop_bb = ctx.loop_target.replace((incr_bb, cont_bb));
let iter_val = generator.gen_expr(ctx, iter)?.unwrap().to_basic_value_enum(
ctx,
generator,
iter.custom.unwrap(),
)?;
let iter_val = if let Some(v) = generator.gen_expr(ctx, iter)? {
v.to_basic_value_enum(
ctx,
generator,
iter.custom.unwrap(),
)?
} else {
return Ok(())
};
if is_iterable_range_expr {
let iter_val = iter_val.into_pointer_value();
// Internal variable for loop; Cannot be assigned
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
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);
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));
ctx.builder.build_unconditional_branch(test_bb);
ctx.builder.position_at_end(test_bb);
let test = generator.gen_expr(ctx, test)?.unwrap().to_basic_value_enum(
ctx,
generator,
test.custom.unwrap(),
)?;
let test = if let Some(v) = generator.gen_expr(ctx, test)? {
v.to_basic_value_enum(ctx, generator, test.custom.unwrap())?
} else {
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 {
ctx.builder.build_conditional_branch(generator.bool_to_i1(ctx, test), body_bb, orelse_bb);
} else {
@ -478,13 +495,11 @@ pub fn gen_if<'ctx, 'a, G: CodeGenerator>(
};
ctx.builder.build_unconditional_branch(test_bb);
ctx.builder.position_at_end(test_bb);
let test = generator.gen_expr(ctx, test)?
.unwrap()
.to_basic_value_enum(ctx, generator, test.custom.unwrap())?;
if let BasicValueEnum::IntValue(test) = test {
let test = generator
.gen_expr(ctx, test)
.and_then(|v| v.map(|v| v.to_basic_value_enum(ctx, generator, test.custom.unwrap())).transpose())?;
if let Some(BasicValueEnum::IntValue(test)) = test {
ctx.builder.build_conditional_branch(generator.bool_to_i1(ctx, test), body_bb, orelse_bb);
} else {
unreachable!()
};
ctx.builder.position_at_end(body_bb);
generator.gen_block(ctx, body.iter())?;
@ -604,7 +619,7 @@ pub fn exn_constructor<'ctx, 'a>(
let msg = if !args.is_empty() {
args.remove(0).1.to_basic_value_enum(ctx, generator, ctx.primitives.str)?
} else {
empty_string
empty_string.unwrap()
};
ctx.builder.build_store(ptr, msg);
for i in [6, 7, 8].iter() {
@ -627,7 +642,7 @@ pub fn exn_constructor<'ctx, 'a>(
&[zero, int32.const_int(*i, false)],
"exn.str",
);
ctx.builder.build_store(ptr, empty_string);
ctx.builder.build_store(ptr, empty_string.unwrap());
}
// set ints to zero
for i in [2, 3].iter() {
@ -1036,14 +1051,17 @@ pub fn gen_return<'ctx, 'a, G: CodeGenerator>(
value: &Option<Box<Expr<Option<Type>>>>,
) -> Result<(), String> {
let func = ctx.builder.get_insert_block().and_then(|bb| bb.get_parent()).unwrap();
let value = value
.as_ref()
.map(|v_expr| {
generator.gen_expr(ctx, v_expr).and_then(|v| {
v.unwrap().to_basic_value_enum(ctx, generator, v_expr.custom.unwrap())
})
})
.transpose()?;
let value = if let Some(v_expr) = value.as_ref() {
if let Some(v) = generator.gen_expr(ctx, v_expr).transpose() {
Some(
v.and_then(|v| v.to_basic_value_enum(ctx, generator, v_expr.custom.unwrap()))?
)
} else {
return Ok(())
}
} else {
None
};
if let Some(return_target) = ctx.return_target {
if let Some(value) = 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, .. } => {
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)?;
}
}
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() {
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::Raise { exc, .. } => {
if let Some(exc) = exc {
let exc = generator.gen_expr(ctx, exc)?.unwrap().to_basic_value_enum(
ctx,
generator,
exc.custom.unwrap(),
)?;
let exc = if let Some(v) = generator.gen_expr(ctx, exc)? {
v.to_basic_value_enum(ctx, generator, exc.custom.unwrap())?
} else {
return Ok(())
};
gen_raise(generator, ctx, Some(&exc), stmt.location);
} else {
gen_raise(generator, ctx, None, stmt.location);
}
}
StmtKind::Assert { test, msg, .. } => {
let test = generator.gen_expr(ctx, test)?.unwrap().to_basic_value_enum(
ctx,
generator,
test.custom.unwrap(),
)?;
let test = if let Some(v) = generator.gen_expr(ctx, test)? {
v.to_basic_value_enum(ctx, generator, test.custom.unwrap())?
} else {
return Ok(())
};
let err_msg = match msg {
Some(msg) => generator.gen_expr(ctx, msg)?.unwrap().to_basic_value_enum(
ctx,
generator,
msg.custom.unwrap(),
)?,
Some(msg) => if let Some(v) = generator.gen_expr(ctx, msg)? {
v.to_basic_value_enum(ctx, generator, msg.custom.unwrap())?
} else {
return Ok(())
},
None => ctx.gen_string(generator, ""),
};
ctx.make_assert_impl(

View File

@ -1,11 +1,12 @@
use std::fmt::Debug;
use std::sync::Arc;
use std::{collections::HashMap, fmt::Display};
use std::rc::Rc;
use crate::typecheck::typedef::TypeEnum;
use crate::{
codegen::CodeGenContext,
toplevel::{DefinitionId, TopLevelDef},
toplevel::{DefinitionId, TopLevelDef, type_annotation::TypeAnnotation},
};
use crate::{
codegen::CodeGenerator,
@ -16,7 +17,7 @@ use crate::{
};
use inkwell::values::{BasicValueEnum, FloatValue, IntValue, PointerValue, StructValue};
use itertools::{chain, izip};
use nac3parser::ast::{Expr, Location, StrRef};
use nac3parser::ast::{Constant, Expr, Location, StrRef};
use parking_lot::RwLock;
#[derive(Clone, PartialEq, Debug)]
@ -33,6 +34,147 @@ pub enum SymbolValue {
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 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {

View File

@ -22,7 +22,7 @@ use inkwell::{
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(
name: &str,
@ -881,6 +881,33 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
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 {
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()))
}),
),
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(
primitives,
&var_map,
@ -1183,6 +1237,33 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
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({
let list_var = primitives.1.get_fresh_var(Some("L".into()), None);
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(
primitives,
&var_map,
"isnan",
"np_isnan",
boolean,
&[(float, "x")],
Box::new(|ctx, _, fun, args, generator| {
@ -1451,7 +1532,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_codegen(
primitives,
&var_map,
"isinf",
"np_isinf",
boolean,
&[(float, "x")],
Box::new(|ctx, _, fun, args, generator| {
@ -1471,7 +1552,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_intrinsic(
primitives,
&var_map,
"sin",
"np_sin",
float,
&[(float, "x")],
"llvm.sin.f64",
@ -1479,7 +1560,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_intrinsic(
primitives,
&var_map,
"cos",
"np_cos",
float,
&[(float, "x")],
"llvm.cos.f64",
@ -1487,7 +1568,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_intrinsic(
primitives,
&var_map,
"exp",
"np_exp",
float,
&[(float, "x")],
"llvm.exp.f64",
@ -1495,7 +1576,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_intrinsic(
primitives,
&var_map,
"exp2",
"np_exp2",
float,
&[(float, "x")],
"llvm.exp2.f64",
@ -1503,7 +1584,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_intrinsic(
primitives,
&var_map,
"log",
"np_log",
float,
&[(float, "x")],
"llvm.log.f64",
@ -1511,7 +1592,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_intrinsic(
primitives,
&var_map,
"log10",
"np_log10",
float,
&[(float, "x")],
"llvm.log10.f64",
@ -1519,7 +1600,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_intrinsic(
primitives,
&var_map,
"log2",
"np_log2",
float,
&[(float, "x")],
"llvm.log2.f64",
@ -1527,7 +1608,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_intrinsic(
primitives,
&var_map,
"fabs",
"np_fabs",
float,
&[(float, "x")],
"llvm.fabs.f64",
@ -1535,7 +1616,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_intrinsic(
primitives,
&var_map,
"sqrt",
"np_sqrt",
float,
&[(float, "x")],
"llvm.sqrt.f64",
@ -1543,7 +1624,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_intrinsic(
primitives,
&var_map,
"rint",
"np_rint",
float,
&[(float, "x")],
"llvm.roundeven.f64",
@ -1551,7 +1632,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern(
primitives,
&var_map,
"tan",
"np_tan",
float,
&[(float, "x")],
"tan",
@ -1560,7 +1641,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern(
primitives,
&var_map,
"arcsin",
"np_arcsin",
float,
&[(float, "x")],
"asin",
@ -1569,7 +1650,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern(
primitives,
&var_map,
"arccos",
"np_arccos",
float,
&[(float, "x")],
"acos",
@ -1578,7 +1659,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern(
primitives,
&var_map,
"arctan",
"np_arctan",
float,
&[(float, "x")],
"atan",
@ -1587,7 +1668,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern(
primitives,
&var_map,
"sinh",
"np_sinh",
float,
&[(float, "x")],
"sinh",
@ -1596,7 +1677,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern(
primitives,
&var_map,
"cosh",
"np_cosh",
float,
&[(float, "x")],
"cosh",
@ -1605,7 +1686,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern(
primitives,
&var_map,
"tanh",
"np_tanh",
float,
&[(float, "x")],
"tanh",
@ -1614,7 +1695,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern(
primitives,
&var_map,
"arcsinh",
"np_arcsinh",
float,
&[(float, "x")],
"asinh",
@ -1623,7 +1704,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern(
primitives,
&var_map,
"arccosh",
"np_arccosh",
float,
&[(float, "x")],
"acosh",
@ -1632,7 +1713,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern(
primitives,
&var_map,
"arctanh",
"np_arctanh",
float,
&[(float, "x")],
"atanh",
@ -1641,7 +1722,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern(
primitives,
&var_map,
"expm1",
"np_expm1",
float,
&[(float, "x")],
"expm1",
@ -1650,7 +1731,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern(
primitives,
&var_map,
"cbrt",
"np_cbrt",
float,
&[(float, "x")],
"cbrt",
@ -1659,7 +1740,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern(
primitives,
&var_map,
"erf",
"sp_spec_erf",
float,
&[(float, "z")],
"erf",
@ -1668,7 +1749,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern(
primitives,
&var_map,
"erfc",
"sp_spec_erfc",
float,
&[(float, "x")],
"erfc",
@ -1677,7 +1758,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_codegen(
primitives,
&var_map,
"gamma",
"sp_spec_gamma",
float,
&[(float, "z")],
Box::new(|ctx, _, fun, args, generator| {
@ -1695,7 +1776,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_codegen(
primitives,
&var_map,
"gammaln",
"sp_spec_gammaln",
float,
&[(float, "x")],
Box::new(|ctx, _, fun, args, generator| {
@ -1713,7 +1794,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_codegen(
primitives,
&var_map,
"j0",
"sp_spec_j0",
float,
&[(float, "x")],
Box::new(|ctx, _, fun, args, generator| {
@ -1731,7 +1812,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern(
primitives,
&var_map,
"j1",
"sp_spec_j1",
float,
&[(float, "x")],
"j1",
@ -1741,7 +1822,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern(
primitives,
&var_map,
"arctan2",
"np_arctan2",
float,
&[(float, "x1"), (float, "x2")],
"atan2",
@ -1750,7 +1831,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_intrinsic(
primitives,
&var_map,
"copysign",
"np_copysign",
float,
&[(float, "x1"), (float, "x2")],
"llvm.copysign.f64",
@ -1758,7 +1839,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_intrinsic(
primitives,
&var_map,
"fmax",
"np_fmax",
float,
&[(float, "x1"), (float, "x2")],
"llvm.maxnum.f64",
@ -1766,7 +1847,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_intrinsic(
primitives,
&var_map,
"fmin",
"np_fmin",
float,
&[(float, "x1"), (float, "x2")],
"llvm.minnum.f64",
@ -1774,7 +1855,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern(
primitives,
&var_map,
"ldexp",
"np_ldexp",
float,
&[(float, "x1"), (int32, "x2")],
"ldexp",
@ -1783,7 +1864,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern(
primitives,
&var_map,
"hypot",
"np_hypot",
float,
&[(float, "x1"), (float, "x2")],
"hypot",
@ -1792,7 +1873,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
create_fn_by_extern(
primitives,
&var_map,
"nextafter",
"np_nextafter",
float,
&[(float, "x1"), (float, "x2")],
"nextafter",
@ -1825,65 +1906,6 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
let ast_list: Vec<Option<ast::Stmt<()>>> =
(0..top_level_def_list.len()).map(|_| None).collect();
(
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",
],
)
izip!(top_level_def_list, ast_list).collect_vec()
}

View File

@ -53,7 +53,7 @@ impl TopLevelComposer {
core_config: ComposerConfig,
) -> (Self, HashMap<StrRef, DefinitionId>, HashMap<StrRef, Type>) {
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 mut unifier = primitives.1;
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_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 id = definition_ast_list.len() - id - 1;
let def = definition_ast_list[id].0.read();
if let TopLevelDef::Function { simple_name, signature, .. } = &*def {
assert!(name == *simple_name);
if let TopLevelDef::Function { name: func_name, simple_name, signature, .. } = &*def {
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_id.insert(name, DefinitionId(id));
} else if let TopLevelDef::Class { name, constructor, object_id, .. } = &*def
@ -546,6 +560,7 @@ impl TopLevelComposer {
&primitive_types,
b,
vec![(*class_def_id, class_type_vars.clone())].into_iter().collect(),
None,
)?;
if let TypeAnnotation::CustomClass { .. } = &base_ty {
@ -880,6 +895,7 @@ impl TopLevelComposer {
// NOTE: since only class need this, for function
// it should be fine to be empty map
HashMap::new(),
None,
)?;
let type_vars_within =
@ -947,6 +963,7 @@ impl TopLevelComposer {
// NOTE: since only class need this, for function
// it should be fine to be empty map
HashMap::new(),
None,
)?
};
@ -1144,6 +1161,7 @@ impl TopLevelComposer {
vec![(class_id, class_type_vars_def.clone())]
.into_iter()
.collect(),
None,
)?
};
// find type vars within this method parameter type annotation
@ -1207,6 +1225,7 @@ impl TopLevelComposer {
primitives,
result,
vec![(class_id, class_type_vars_def.clone())].into_iter().collect(),
None,
)?;
// find type vars within this return type annotation
let type_vars_within =
@ -1303,6 +1322,7 @@ impl TopLevelComposer {
primitives,
annotation.as_ref(),
vec![(class_id, class_type_vars_def.clone())].into_iter().collect(),
None,
)?;
// find type vars within this return type annotation
let type_vars_within =
@ -1721,7 +1741,7 @@ impl TopLevelComposer {
.iter()
.map(|(_, ty)| {
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;
no_ranges.push(rigid);

View File

@ -416,40 +416,6 @@ impl TopLevelComposer {
primitive: &PrimitiveStore,
unifier: &mut Unifier,
) -> 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(
found: &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) {
Err(format!(
"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
"}
],
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"
)]
#[test_case(
@ -417,7 +417,7 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
def __init__():
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"
)]
#[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"
)]
#[test_case(
@ -507,7 +507,7 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
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"
)]
fn test_analyze(source: Vec<&str>, res: Vec<&str>) {

View File

@ -1,3 +1,4 @@
use crate::symbol_resolver::SymbolValue;
use super::*;
#[derive(Clone, Debug)]
@ -12,6 +13,16 @@ pub enum TypeAnnotation {
// can only be CustomClassKind
Virtual(Box<TypeAnnotation>),
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>),
Tuple(Vec<TypeAnnotation>),
}
@ -47,6 +58,7 @@ impl TypeAnnotation {
}
)
}
Constant { value, .. } => format!("Const({value})"),
Virtual(ty) => format!("virtual[{}]", ty.stringify(unifier)),
List(ty) => format!("list[{}]", ty.stringify(unifier)),
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>(
resolver: &(dyn SymbolResolver + Send + Sync),
top_level_defs: &[Arc<RwLock<TopLevelDef>>],
@ -64,6 +82,7 @@ pub fn parse_ast_to_type_annotation_kinds<T>(
expr: &ast::Expr<T>,
// the key stores the type_var of this topleveldef::class, we only need this field here
locked: HashMap<DefinitionId, Vec<Type>>,
type_var: Option<Type>,
) -> Result<TypeAnnotation, String> {
let name_handle = |id: &StrRef,
unifier: &mut Unifier,
@ -127,7 +146,7 @@ pub fn parse_ast_to_type_annotation_kinds<T>(
slice: &ast::Expr<T>,
unifier: &mut Unifier,
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));
}
@ -161,7 +180,8 @@ pub fn parse_ast_to_type_annotation_kinds<T>(
}
let result = params_ast
.iter()
.map(|x| {
.enumerate()
.map(|(idx, x)| {
parse_ast_to_type_annotation_kinds(
resolver,
top_level_defs,
@ -172,6 +192,7 @@ pub fn parse_ast_to_type_annotation_kinds<T>(
locked.insert(obj_id, type_vars.clone());
locked.clone()
},
Some(type_vars[idx]),
)
})
.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 })
};
match &expr.node {
ast::ExprKind::Name { id, .. } => name_handle(id, unifier, locked),
// virtual
@ -205,6 +227,7 @@ pub fn parse_ast_to_type_annotation_kinds<T>(
primitives,
slice.as_ref(),
locked,
None,
)?;
if !matches!(def, TypeAnnotation::CustomClass { .. }) {
unreachable!("must be concretized custom class kind in the virtual")
@ -225,6 +248,7 @@ pub fn parse_ast_to_type_annotation_kinds<T>(
primitives,
slice.as_ref(),
locked,
None,
)?;
Ok(TypeAnnotation::List(def_ann.into()))
}
@ -242,6 +266,7 @@ pub fn parse_ast_to_type_annotation_kinds<T>(
primitives,
slice.as_ref(),
locked,
None,
)?;
let id =
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,
e,
locked.clone(),
None,
)
})
.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)),
}
}
@ -308,94 +359,130 @@ pub fn get_type_from_type_annotation_kinds(
TypeAnnotation::CustomClass { id: obj_id, params } => {
let def_read = top_level_defs[obj_id.0].read();
let class_def: &TopLevelDef = def_read.deref();
if let TopLevelDef::Class { fields, methods, type_vars, .. } = class_def {
if type_vars.len() != params.len() {
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 TopLevelDef::Class { fields, methods, type_vars, .. } = class_def else {
unreachable!("should be class def here")
};
let subst = {
// check for compatible range
// TODO: if allow type var to be applied(now this disallowed in the parse_to_type_annotation), need more check
let mut result: HashMap<u32, Type> = HashMap::new();
for (tvar, p) in type_vars.iter().zip(param_ty) {
if let TypeEnum::TVar { id, range, fields: None, name, loc } =
unifier.get_ty(*tvar).as_ref()
{
let ok: bool = {
// create a temp type var and unify to check compatibility
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 {
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
));
if type_vars.len() != params.len() {
return Err(format!(
"unexpected number of type parameters: expected {} but got {}",
type_vars.len(),
params.len()
))
}
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 = {
// check for compatible range
// TODO: if allow type var to be applied(now this disallowed in the parse_to_type_annotation), need more check
let mut result: HashMap<u32, Type> = HashMap::new();
for (tvar, p) in type_vars.iter().zip(param_ty) {
match unifier.get_ty(*tvar).as_ref() {
TypeEnum::TVar { id, range, fields: None, name, loc, is_const_generic: false } => {
let ok: bool = {
// create a temp type var and unify to check compatibility
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 {
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
};
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));
TypeEnum::TVar { id, range, name, loc, is_const_generic: true, .. } => {
let ty = range[0];
let ok: bool = {
// create a temp type var and unify to check compatibility
p == *tvar || {
let temp = unifier.get_fresh_const_generic_var(
ty,
*name,
*loc,
);
unifier.unify(temp.0, p).is_ok()
}
};
if ok {
result.insert(*id, p);
} else {
return Err(format!(
"cannot apply type {} to type variable {}",
unifier.stringify(p),
name.unwrap_or_else(|| format!("typevar{id}").into()),
))
}
}
_ => unreachable!("must be generic type var"),
}
Ok(ty)
}
} else {
unreachable!("should be class def here")
result
};
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::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) => {
let ty = get_type_from_type_annotation_kinds(
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));
}
}
TypeAnnotation::Primitive(..) => {}
TypeAnnotation::Primitive(..) | TypeAnnotation::Constant { .. } => {}
}
result
}

View File

@ -62,7 +62,7 @@ impl<'a> Inferencer<'a> {
) -> Result<(), String> {
// there are some cases where the custom field is None
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!(
"expected concrete type at {} but got {}",
expr.location,

View File

@ -964,6 +964,7 @@ impl<'a> Inferencer<'a> {
ast::Constant::Str(_) => Ok(self.primitives.str),
ast::Constant::None
=> 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),
}
}

View File

@ -134,6 +134,17 @@ pub enum TypeEnum {
range: Vec<Type>,
name: Option<StrRef>,
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.
@ -178,6 +189,7 @@ impl TypeEnum {
match self {
TypeEnum::TRigidVar { .. } => "TRigidVar",
TypeEnum::TVar { .. } => "TVar",
TypeEnum::TConstant { .. } => "TConstant",
TypeEnum::TTuple { .. } => "TTuple",
TypeEnum::TList { .. } => "TList",
TypeEnum::TObj { .. } => "TObj",
@ -263,6 +275,7 @@ impl Unifier {
fields: Some(fields),
name: None,
loc: None,
is_const_generic: false,
})
}
@ -336,7 +349,33 @@ impl Unifier {
let id = self.var_id + 1;
self.var_id += 1;
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
@ -412,7 +451,7 @@ impl Unifier {
pub fn is_concrete(&mut self, a: Type, allowed_typevars: &[Type]) -> bool {
use TypeEnum::*;
match &*self.get_ty(a) {
TRigidVar { .. } => true,
TRigidVar { .. } | TConstant { .. } => true,
TVar { .. } => allowed_typevars.iter().any(|b| self.unification_table.unioned(a, *b)),
TCall { .. } => false,
TList { ty } => self.is_concrete(*ty, allowed_typevars),
@ -560,8 +599,8 @@ impl Unifier {
};
match (&*ty_a, &*ty_b) {
(
TVar { fields: fields1, id, name: name1, loc: loc1, .. },
TVar { fields: fields2, id: id2, name: name2, loc: loc2, .. },
TVar { fields: fields1, id, name: name1, loc: loc1, is_const_generic: false, .. },
TVar { fields: fields2, id: id2, name: name2, loc: loc2, is_const_generic: false, .. },
) => {
let new_fields = match (fields1, fields2) {
(None, None) => None,
@ -616,10 +655,11 @@ impl Unifier {
range,
name: name1.or(*name2),
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.
// 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
@ -636,7 +676,7 @@ impl Unifier {
self.unify_impl(x, b, false)?;
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;
for (k, v) in fields.iter() {
match *k {
@ -666,7 +706,7 @@ impl Unifier {
self.unify_impl(x, b, false)?;
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() {
match *k {
RecordKey::Int(_) => {
@ -681,6 +721,35 @@ impl Unifier {
self.unify_impl(x, b, false)?;
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 }) => {
if ty1.len() != ty2.len() {
return Err(TypeError::new(TypeErrorKind::IncompatibleTypes(a, b), None));
@ -775,7 +844,14 @@ impl Unifier {
if id1 != id2 {
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() {
return Err(TypeError::new(TypeErrorKind::IncompatibleTypes(a, b), None));
};
@ -928,6 +1004,9 @@ impl Unifier {
};
n
}
TypeEnum::TConstant { value, .. } => {
format!("const({value})")
}
TypeEnum::TTuple { ty } => {
let mut fields =
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) {
// unify a and b together, and set the value to b's value.
let table = &mut self.unification_table;
let ty_b = table.probe_value(b).clone();
table.unify(a, b);
@ -1207,6 +1286,7 @@ impl Unifier {
range,
name: name2.or(*name),
loc: loc2.or(*loc),
is_const_generic: false,
};
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) {
printf("%ld\n", x);
printf("%lld\n", x);
}
void output_uint32(uint32_t x) {
@ -38,7 +38,7 @@ void output_uint32(uint32_t x) {
}
void output_uint64(uint64_t x) {
printf("%lu\n", x);
printf("%llu\n", x);
}
void output_float64(double x) {

View File

@ -6,9 +6,9 @@ import importlib.machinery
import math
import numpy as np
import pathlib
import scipy
from numpy import int32, int64, uint32, uint64
from scipy import special
from typing import TypeVar, Generic
T = TypeVar('T')
@ -44,6 +44,12 @@ def Some(v: T) -> Option[T]:
none = Option(None)
class _ConstGenericMarker:
pass
def ConstGeneric(name, constraint):
return TypeVar(name, _ConstGenericMarker, constraint)
def round_away_zero(x):
if x >= 0.0:
return math.floor(x + 0.5)
@ -99,6 +105,7 @@ def patch(module):
module.uint32 = uint32
module.uint64 = uint64
module.TypeVar = TypeVar
module.ConstGeneric = ConstGeneric
module.Generic = Generic
module.extern = extern
module.Option = Option
@ -108,52 +115,55 @@ def patch(module):
# Builtin Math functions
module.round = round_away_zero
module.round64 = round_away_zero
module.np_round = np.round
module.floor = math.floor
module.floor64 = math.floor
module.np_floor = np.floor
module.ceil = math.ceil
module.ceil64 = math.ceil
module.np_ceil = np.ceil
# NumPy Math functions
module.isnan = np.isnan
module.isinf = np.isinf
module.sin = np.sin
module.cos = np.cos
module.exp = np.exp
module.exp2 = np.exp2
module.log = np.log
module.log10 = np.log10
module.log2 = np.log2
module.fabs = np.fabs
module.trunc = np.trunc
module.sqrt = np.sqrt
module.rint = np.rint
module.tan = np.tan
module.arcsin = np.arcsin
module.arccos = np.arccos
module.arctan = np.arctan
module.sinh = np.sinh
module.cosh = np.cosh
module.tanh = np.tanh
module.arcsinh = np.arcsinh
module.arccosh = np.arccosh
module.arctanh = np.arctanh
module.expm1 = np.expm1
module.cbrt = np.cbrt
module.arctan2 = np.arctan2
module.copysign = np.copysign
module.fmax = np.fmax
module.fmin = np.fmin
module.ldexp = np.ldexp
module.hypot = np.hypot
module.nextafter = np.nextafter
module.np_isnan = np.isnan
module.np_isinf = np.isinf
module.np_sin = np.sin
module.np_cos = np.cos
module.np_exp = np.exp
module.np_exp2 = np.exp2
module.np_log = np.log
module.np_log10 = np.log10
module.np_log2 = np.log2
module.np_fabs = np.fabs
module.np_trunc = np.trunc
module.np_sqrt = np.sqrt
module.np_rint = np.rint
module.np_tan = np.tan
module.np_arcsin = np.arcsin
module.np_arccos = np.arccos
module.np_arctan = np.arctan
module.np_sinh = np.sinh
module.np_cosh = np.cosh
module.np_tanh = np.tanh
module.np_arcsinh = np.arcsinh
module.np_arccosh = np.arccosh
module.np_arctanh = np.arctanh
module.np_expm1 = np.expm1
module.np_cbrt = np.cbrt
module.np_arctan2 = np.arctan2
module.np_copysign = np.copysign
module.np_fmax = np.fmax
module.np_fmin = np.fmin
module.np_ldexp = np.ldexp
module.np_hypot = np.hypot
module.np_nextafter = np.nextafter
# SciPy Math Functions
module.erf = scipy.special.erf
module.erfc = scipy.special.erfc
module.gamma = scipy.special.gamma
module.gammaln = scipy.special.gammaln
module.j0 = scipy.special.j0
module.j1 = scipy.special.j1
module.sp_spec_erf = special.erf
module.sp_spec_erfc = special.erfc
module.sp_spec_gamma = special.gamma
module.sp_spec_gammaln = special.gammaln
module.sp_spec_j0 = special.j0
module.sp_spec_j1 = special.j1
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]:
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()]:
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()]:
output_bool(isinf(x))
output_bool(np_isinf(x))
def test_sin():
def test_np_sin():
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()]:
output_float64(sin(x))
output_float64(np_sin(x))
def test_cos():
def test_np_cos():
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()]:
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()]:
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()]:
output_float64(exp2(x))
output_float64(np_exp2(x))
def test_log():
def test_np_log():
e = dbl_e()
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()]:
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()]:
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()]:
output_float64(fabs(x))
output_float64(np_fabs(x))
def test_floor():
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]:
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():
for x in [-1.5, -0.5, 0.5, 1.5]:
output_int32(ceil(x))
@ -95,165 +103,172 @@ def test_ceil64():
for x in [-1.5, -0.5, 0.5, 1.5]:
output_int64(ceil64(x))
def test_sqrt():
for x in [1.0, 2.0, 4.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(sqrt(x))
def test_rint():
def test_np_ceil():
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()
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()]:
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()]:
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()]:
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()]:
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()]:
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()]:
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()]:
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()]:
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()]:
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()]:
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()]:
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()]:
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()]:
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()]:
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()]:
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()]:
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]:
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 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 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 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 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 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 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 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:
test_round()
test_round64()
test_isnan()
test_isinf()
test_sin()
test_cos()
test_exp()
test_exp2()
test_log()
test_log10()
test_log2()
test_fabs()
test_np_round()
test_np_isnan()
test_np_isinf()
test_np_sin()
test_np_cos()
test_np_exp()
test_np_exp2()
test_np_log()
test_np_log10()
test_np_log2()
test_np_fabs()
test_floor()
test_floor64()
test_np_floor()
test_ceil()
test_ceil64()
test_sqrt()
test_rint()
test_tan()
test_arcsin()
test_arccos()
test_arctan()
test_sinh()
test_cosh()
test_tanh()
test_arcsinh()
test_arccosh()
test_arctanh()
test_expm1()
test_cbrt()
test_erf()
test_erfc()
test_gamma()
test_gammaln()
test_j0()
test_j1()
test_arctan2()
test_copysign()
test_fmax()
test_fmin()
test_ldexp()
test_hypot()
test_nextafter()
test_np_ceil()
test_np_sqrt()
test_np_rint()
test_np_tan()
test_np_arcsin()
test_np_arccos()
test_np_arctan()
test_np_sinh()
test_np_cosh()
test_np_tanh()
test_np_arcsinh()
test_np_arccosh()
test_np_arctanh()
test_np_expm1()
test_np_cbrt()
test_sp_spec_erf()
test_sp_spec_erfc()
test_sp_spec_gamma()
test_sp_spec_gammaln()
test_sp_spec_j0()
test_sp_spec_j1()
test_np_arctan2()
test_np_copysign()
test_np_fmax()
test_np_fmin()
test_np_ldexp()
test_np_hypot()
test_np_nextafter()
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,
};
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::{
codegen::{
@ -25,7 +25,7 @@ use nac3core::{
},
};
use nac3parser::{
ast::{Expr, ExprKind, StmtKind},
ast::{Constant, Expr, ExprKind, StmtKind, StrRef},
parser,
};
@ -77,8 +77,20 @@ fn handle_typevar_definition(
unifier: &mut Unifier,
primitives: &PrimitiveStore,
) -> Result<Type, String> {
if let ExprKind::Call { func, args, .. } = &var.node {
if matches!(&func.node, ExprKind::Name { id, .. } if id == &"TypeVar".into()) {
let ExprKind::Call { func, args, .. } = &var.node else {
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
.iter()
.skip(1)
@ -90,22 +102,54 @@ fn handle_typevar_definition(
primitives,
x,
Default::default(),
None,
)?;
get_type_from_type_annotation_kinds(
def_list, unifier, primitives, &ty, &mut None
)
})
.collect::<Result<Vec<_>, _>>()?;
Ok(unifier.get_fresh_var_with_range(&constraints, None, None).0)
} else {
Err(format!(
"expression {:?} cannot be handled as a TypeVar in global scope",
var
))
let loc = func.location;
if constraints.len() == 1 {
return Err(format!("A single constraint is not allowed (at {})", loc))
}
Ok(unifier.get_fresh_var_with_range(&constraints, Some(generic_name), Some(loc)).0)
}
} else {
Err(format!(
"expression {:?} cannot be handled as a TypeVar in global scope",
ExprKind::Name { id, .. } if id == &"ConstGeneric".into() => {
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
))
}
@ -124,7 +168,7 @@ fn handle_assignment_pattern(
match &targets[0].node {
ExprKind::Name { id, .. } => {
if let Ok(var) = handle_typevar_definition(
value.borrow(),
value,
resolver,
def_list,
unifier,
@ -133,12 +177,12 @@ fn handle_assignment_pattern(
internal_resolver.add_id_type(*id, var);
Ok(())
} 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);
Ok(())
} 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].location,
))
@ -324,6 +368,7 @@ fn main() {
triple,
cpu: mcpu,
features: target_features,
reloc_mode: RelocMode::PIC,
..host_target_machine
},
};

View File

@ -1,16 +1,16 @@
pkgbase="mingw-w64-nac3artiq"
pkgname="mingw-w64-x86_64-nac3artiq"
pkgname="mingw-w64-clang-x86_64-nac3artiq"
pkgver=1.0
pkgrel=1
pkgdesc="New ARTIQ compiler 3"
arch=("any")
mingw_arch=("mingw64")
mingw_arch=("clang64")
url="https://m-labs.hk"
license=("LGPL")
source=("nac3artiq.pyd")
noextract=("nac3artiq.pyd")
sha256sums=("SKIP")
depends=("mingw-w64-x86_64-python")
depends=("mingw-w64-clang-x86_64-python")
prepare() {
true
@ -21,6 +21,6 @@ build() {
}
package() {
mkdir -p $pkgdir/mingw64/lib/python3.11/site-packages
cp ${srcdir}/nac3artiq.pyd $pkgdir/mingw64/lib/python3.11/site-packages
mkdir -p $pkgdir/clang64/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
abi3=false
lib_name=python3.11
lib_dir=${msys2-env}/mingw64/lib
lib_dir=${msys2-env}/clang64/lib
pointer_width=64
build_flags=WITH_THREAD
suppress_build_script_link_lines=false
@ -61,7 +61,7 @@ in rec {
''
export HOME=`mktemp -d`
export WINEDEBUG=-all
export WINEPATH=Z:${msys2-env}/mingw64/bin
export WINEPATH=Z:${msys2-env}/clang64/bin
${silenceFontconfig}
mkdir build
cd build
@ -77,7 +77,12 @@ in rec {
'';
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 {
name = "nac3artiq-msys2";
src = ../../.;
@ -89,9 +94,11 @@ in rec {
''
export HOME=`mktemp -d`
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}
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
'';
installPhase =
@ -100,6 +107,7 @@ in rec {
cp target/release/nac3artiq.dll $out/nac3artiq.pyd
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 =
''
wine64 cargo test --release
@ -127,7 +135,7 @@ in rec {
wine-msys2 = pkgs.writeShellScriptBin "wine-msys2"
''
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}
exec ${pkgs.wineWowPackages.stable}/bin/wine64 cmd
'';
@ -135,7 +143,7 @@ in rec {
''
export HOME=`mktemp -d`
export WINEDEBUG=-all
export WINEPATH=Z:${msys2-env}/mingw64/bin
export WINEPATH=Z:${msys2-env}/clang64/bin
${silenceFontconfig}
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
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
while read package; do

View File

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