Compare commits
No commits in common. "dev" and "main" have entirely different histories.
4
build
4
build
@ -1,12 +1,10 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
# generate this file from Nix config for now to avoid duplication?
|
|
||||||
|
|
||||||
cargo build --manifest-path ./rust/Cargo.toml
|
cargo build --manifest-path ./rust/Cargo.toml
|
||||||
|
|
||||||
BUNDLED_LIB_DIR=$(cabal list-bin . | sed -e 's=x/garnet/build/garnet/garnet=build=g')
|
BUNDLED_LIB_DIR=$(cabal list-bin . | sed -e 's=x/garnet/build/garnet/garnet=build=g')
|
||||||
mkdir -p $BUNDLED_LIB_DIR
|
mkdir -p $BUNDLED_LIB_DIR
|
||||||
ln -sf $(pwd)/rust/target/debug/libgarnet_rs.a $BUNDLED_LIB_DIR/libCgarnet_rs.a
|
ln -sf $(pwd)/rust/target/debug/libgarnet_rs.a $BUNDLED_LIB_DIR
|
||||||
|
|
||||||
cabal build
|
cabal build
|
||||||
|
|||||||
@ -1,5 +1,20 @@
|
|||||||
packages: .
|
packages: .
|
||||||
|
|
||||||
|
-- not on Hackage yet: https://well-typed.com/blog/2026/02/hs-bindgen-alpha
|
||||||
|
-- we've modified the stanzas from that post in order to use a more recent version
|
||||||
|
-- because we want record-dot support: https://github.com/well-typed/hs-bindgen/issues/1829#issuecomment-4081875451
|
||||||
|
source-repository-package
|
||||||
|
type: git
|
||||||
|
location: https://github.com/well-typed/hs-bindgen
|
||||||
|
tag: 6ca94188abd756a1fb4dd8a4037de3fa7dca0765
|
||||||
|
subdir: c-expr-dsl c-expr-runtime hs-bindgen hs-bindgen-runtime
|
||||||
|
--sha256: M+8tEZA8gsEc6gXnNdSbRpMBQ5LkH7sphcV1aR0fclA=
|
||||||
|
source-repository-package
|
||||||
|
type: git
|
||||||
|
location: https://github.com/well-typed/libclang
|
||||||
|
tag: d6e482df49b88375cf3075928a78ee86c2a068d4
|
||||||
|
--sha256: 175kjba915bh50wf03gi88njz03jp0n3wp7yq73hznkaly6bpwal
|
||||||
|
|
||||||
allow-newer:
|
allow-newer:
|
||||||
*:base,
|
*:base,
|
||||||
*:containers,
|
*:containers,
|
||||||
|
|||||||
@ -1,20 +1,13 @@
|
|||||||
module Main (main) where
|
module Main (main) where
|
||||||
|
|
||||||
import Data.Vector.Storable qualified as V
|
|
||||||
import GarnetRs.Wrapped
|
import GarnetRs.Wrapped
|
||||||
import System.IO
|
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = do
|
main = do
|
||||||
hello "Haskell"
|
hello "Haskell"
|
||||||
helloStruct T{a = True, b = 42}
|
helloStruct T{a = True, b = 42}
|
||||||
helloStruct T{a = False, b = maxBound}
|
helloStruct T{a = False, b = maxBound}
|
||||||
helloEnum E1
|
|
||||||
helloEnum E3
|
|
||||||
helloShape $ Circle 3.14
|
helloShape $ Circle 3.14
|
||||||
helloShape $ Rectangle 10.0 5.0
|
helloShape $ Rectangle 10.0 5.0
|
||||||
putStrLn $ "3 + 4 = " <> show (add 3 4)
|
putStrLn $ "3 + 4 = " <> show (add 3 4)
|
||||||
putStrLn $ "Tree sum: " <> show (sumTree (Fork (Fork (Leaf 1) (Fork (Leaf 2) (Leaf 3))) (Leaf 4)))
|
putStrLn $ "Tree sum: " <> show (sumTree (Fork (Fork (Leaf 1) (Fork (Leaf 2) (Leaf 3))) (Leaf 4)))
|
||||||
putStrLn $ "Slice sum: " <> show (sumSlice $ V.fromList [0 .. 5])
|
|
||||||
putStrLn "Nothing." >> printOptional Nothing
|
|
||||||
putStr "Something: " >> hFlush stdout >> printOptional (Just 67)
|
|
||||||
|
|||||||
189
flake.lock
generated
189
flake.lock
generated
@ -85,11 +85,11 @@
|
|||||||
},
|
},
|
||||||
"crane": {
|
"crane": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1774313767,
|
"lastModified": 1771438068,
|
||||||
"narHash": "sha256-hy0XTQND6avzGEUFrJtYBBpFa/POiiaGBr2vpU6Y9tY=",
|
"narHash": "sha256-nGBbXvEZVe/egCPVPFcu89RFtd8Rf6J+4RFoVCFec0A=",
|
||||||
"owner": "ipetkov",
|
"owner": "ipetkov",
|
||||||
"repo": "crane",
|
"repo": "crane",
|
||||||
"rev": "3d9df76e29656c679c744968b17fbaf28f0e923d",
|
"rev": "b5090e53e9d68c523a4bb9ad42b4737ee6747597",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -99,21 +99,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-compat": {
|
"flake-compat": {
|
||||||
"locked": {
|
|
||||||
"lastModified": 1767039857,
|
|
||||||
"narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "flake-compat",
|
|
||||||
"rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "flake-compat",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-compat_2": {
|
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1672831974,
|
"lastModified": 1672831974,
|
||||||
@ -151,11 +136,11 @@
|
|||||||
"hackage": {
|
"hackage": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1770685064,
|
"lastModified": 1771461386,
|
||||||
"narHash": "sha256-e2G/GFzIdTXosxq+3Z0OXbSUmXy9tDbZZ6wsmfy7Hf8=",
|
"narHash": "sha256-93hCxhNOq9/HAggfTTurLhllI0IiEWZ35jk6i/X/qEo=",
|
||||||
"owner": "input-output-hk",
|
"owner": "input-output-hk",
|
||||||
"repo": "hackage.nix",
|
"repo": "hackage.nix",
|
||||||
"rev": "84628a8e4b5d580766d49d62a5e2e065cbb8604e",
|
"rev": "b4f4537825a4db29c10541a50d7eb6c848bf0dca",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -167,11 +152,11 @@
|
|||||||
"hackage-for-stackage": {
|
"hackage-for-stackage": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1770683900,
|
"lastModified": 1771461376,
|
||||||
"narHash": "sha256-03cshwLY80e5jBUgNBmoFoiH1e3VvhAX+1ME4NVt5g4=",
|
"narHash": "sha256-aEuZkBpTaU0XBFiaIomicJDoWQaw84rYfKXI/r17V/w=",
|
||||||
"owner": "input-output-hk",
|
"owner": "input-output-hk",
|
||||||
"repo": "hackage.nix",
|
"repo": "hackage.nix",
|
||||||
"rev": "c7d9e737cd1e07136982e0df0f9aa12391e2c883",
|
"rev": "ca611068e77f15b96ecf71fae827e491c0b2dc3b",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -204,7 +189,7 @@
|
|||||||
"cabal-34": "cabal-34",
|
"cabal-34": "cabal-34",
|
||||||
"cabal-36": "cabal-36",
|
"cabal-36": "cabal-36",
|
||||||
"cardano-shell": "cardano-shell",
|
"cardano-shell": "cardano-shell",
|
||||||
"flake-compat": "flake-compat_2",
|
"flake-compat": "flake-compat",
|
||||||
"hackage": "hackage",
|
"hackage": "hackage",
|
||||||
"hackage-for-stackage": "hackage-for-stackage",
|
"hackage-for-stackage": "hackage-for-stackage",
|
||||||
"hackage-internal": "hackage-internal",
|
"hackage-internal": "hackage-internal",
|
||||||
@ -225,7 +210,6 @@
|
|||||||
"hpc-coveralls": "hpc-coveralls",
|
"hpc-coveralls": "hpc-coveralls",
|
||||||
"iserv-proxy": "iserv-proxy",
|
"iserv-proxy": "iserv-proxy",
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"nix-haskell",
|
|
||||||
"haskell-nix",
|
"haskell-nix",
|
||||||
"nixpkgs-unstable"
|
"nixpkgs-unstable"
|
||||||
],
|
],
|
||||||
@ -240,17 +224,16 @@
|
|||||||
"stackage": "stackage"
|
"stackage": "stackage"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1773942398,
|
"lastModified": 1771462666,
|
||||||
"narHash": "sha256-VFUyPaWqXN357StToBRFbOCZAP4n8iCfEh2ZV1dNH88=",
|
"narHash": "sha256-z+pJFzbYa1ulNDUZdb0qLVVAdE0dqpnE51jqh2chA7c=",
|
||||||
"owner": "ymeister",
|
"owner": "input-output-hk",
|
||||||
"repo": "haskell.nix",
|
"repo": "haskell.nix",
|
||||||
"rev": "9fa7c11202e16c8cd2743deed4d811da1cfb2e51",
|
"rev": "857ba7b65d9c1a8765ad1599834a8fe71cb09981",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "ymeister",
|
"owner": "input-output-hk",
|
||||||
"repo": "haskell.nix",
|
"repo": "haskell.nix",
|
||||||
"rev": "9fa7c11202e16c8cd2743deed4d811da1cfb2e51",
|
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -287,6 +270,23 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"hls-2-13": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1768552477,
|
||||||
|
"narHash": "sha256-Y4XVuyJZnZ++u+wSHlz7xnN9+nk29csahnXDC0QMiGM=",
|
||||||
|
"owner": "haskell",
|
||||||
|
"repo": "haskell-language-server",
|
||||||
|
"rev": "d744a66a853c287e671e06e62f2a58dd8e7a86d9",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "haskell",
|
||||||
|
"ref": "2.13.0.0",
|
||||||
|
"repo": "haskell-language-server",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"hls-2.0": {
|
"hls-2.0": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
@ -491,23 +491,6 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"hls-src": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1768552477,
|
|
||||||
"narHash": "sha256-Y4XVuyJZnZ++u+wSHlz7xnN9+nk29csahnXDC0QMiGM=",
|
|
||||||
"owner": "haskell",
|
|
||||||
"repo": "haskell-language-server",
|
|
||||||
"rev": "d744a66a853c287e671e06e62f2a58dd8e7a86d9",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "haskell",
|
|
||||||
"ref": "2.13.0.0",
|
|
||||||
"repo": "haskell-language-server",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"hpc-coveralls": {
|
"hpc-coveralls": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
@ -524,22 +507,6 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"hs-bindgen-src": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1776078838,
|
|
||||||
"narHash": "sha256-f8SE6IuACy8bzIX+EOYTpekaAI/TOQ3zTwJKJmHl3LY=",
|
|
||||||
"owner": "well-typed",
|
|
||||||
"repo": "hs-bindgen",
|
|
||||||
"rev": "ca714aca1ed941271ac248488c9a469554c5b470",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "well-typed",
|
|
||||||
"repo": "hs-bindgen",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"iserv-proxy": {
|
"iserv-proxy": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
@ -557,59 +524,6 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"libclang-src": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1775645278,
|
|
||||||
"narHash": "sha256-JWARcbqH432vWcCvQ2bagTXBka8sCRNAnK1qOmnLWKw=",
|
|
||||||
"owner": "well-typed",
|
|
||||||
"repo": "libclang",
|
|
||||||
"rev": "bf574efcb492d2738d8a82b6ce556f840ff92778",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "well-typed",
|
|
||||||
"repo": "libclang",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nix-haskell": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-compat": "flake-compat",
|
|
||||||
"haskell-nix": "haskell-nix",
|
|
||||||
"nixpkgs": "nixpkgs",
|
|
||||||
"reflex-platform": "reflex-platform"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1774408168,
|
|
||||||
"narHash": "sha256-do26Ik50yH8NYSxuhwzBwNKsxIN88GoovwioWPvCpJU=",
|
|
||||||
"owner": "reflex-frp",
|
|
||||||
"repo": "nix-haskell",
|
|
||||||
"rev": "d6a3bb8f96ff35fd0ae2a0d64f40b584c92aa493",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "reflex-frp",
|
|
||||||
"repo": "nix-haskell",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1769089682,
|
|
||||||
"narHash": "sha256-9yA/LIuAVQq0lXelrZPjLuLVuZdm03p8tfmHhnDIkms=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "078d69f03934859a181e81ba987c2bb033eebfc5",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "078d69f03934859a181e81ba987c2bb033eebfc5",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs-2305": {
|
"nixpkgs-2305": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1705033721,
|
"lastModified": 1705033721,
|
||||||
@ -739,34 +653,15 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"reflex-platform": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1760924715,
|
|
||||||
"narHash": "sha256-pUraGts8qa3R9jQqaVXevkC+nM07B8oF+LGF4xsyiJU=",
|
|
||||||
"owner": "reflex-frp",
|
|
||||||
"repo": "reflex-platform",
|
|
||||||
"rev": "4482ecb04c5939ac77c26d769d149dee12051a13",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "reflex-frp",
|
|
||||||
"repo": "reflex-platform",
|
|
||||||
"rev": "4482ecb04c5939ac77c26d769d149dee12051a13",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"crane": "crane",
|
"crane": "crane",
|
||||||
"flake-utils": "flake-utils",
|
"flake-utils": "flake-utils",
|
||||||
"hls-src": "hls-src",
|
"haskell-nix": "haskell-nix",
|
||||||
"hs-bindgen-src": "hs-bindgen-src",
|
"hls-2-13": "hls-2-13",
|
||||||
"libclang-src": "libclang-src",
|
|
||||||
"nix-haskell": "nix-haskell",
|
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"nix-haskell",
|
"haskell-nix",
|
||||||
"nixpkgs"
|
"nixpkgs-2511"
|
||||||
],
|
],
|
||||||
"rust-overlay": "rust-overlay"
|
"rust-overlay": "rust-overlay"
|
||||||
}
|
}
|
||||||
@ -778,11 +673,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1774408260,
|
"lastModified": 1771470520,
|
||||||
"narHash": "sha256-Jn9d9r85dmf3gTMnSRt6t+DP2nQ5uJns/MMXg2FpzfM=",
|
"narHash": "sha256-PvytHcaYN5cPUll7FB70mXv1rRsIBRmu47fFfq3haxA=",
|
||||||
"owner": "oxalica",
|
"owner": "oxalica",
|
||||||
"repo": "rust-overlay",
|
"repo": "rust-overlay",
|
||||||
"rev": "d6471ee5a8f470251e6e5b83a20a182eb6c46c9b",
|
"rev": "a1d4cc1f264c45d3745af0d2ca5e59d460e58777",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -794,11 +689,11 @@
|
|||||||
"stackage": {
|
"stackage": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1770596307,
|
"lastModified": 1771460325,
|
||||||
"narHash": "sha256-88b6YzeBaQr9ihSWAOxVGewCDfROKt2rOIHymadu3DI=",
|
"narHash": "sha256-RRsGO7QVyuBtUTVqDiB7CYvFruj0Z/yxZK1JarkTqI4=",
|
||||||
"owner": "input-output-hk",
|
"owner": "input-output-hk",
|
||||||
"repo": "stackage.nix",
|
"repo": "stackage.nix",
|
||||||
"rev": "ff21e9b6a976faed56963ae5fa5d5396dc48ea63",
|
"rev": "29c0dcc517e04be238023064412312ad4443ddb2",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
117
flake.nix
117
flake.nix
@ -1,10 +1,8 @@
|
|||||||
{
|
{
|
||||||
inputs = {
|
inputs = {
|
||||||
nix-haskell.url = "github:reflex-frp/nix-haskell";
|
haskell-nix.url = "github:input-output-hk/haskell.nix";
|
||||||
nixpkgs.follows = "nix-haskell/nixpkgs";
|
hls-2-13 = { url = "github:haskell/haskell-language-server/2.13.0.0"; flake = false; };
|
||||||
hls-src = { url = "github:haskell/haskell-language-server/2.13.0.0"; flake = false; };
|
nixpkgs.follows = "haskell-nix/nixpkgs-2511";
|
||||||
hs-bindgen-src = { url = "github:well-typed/hs-bindgen"; flake = false; };
|
|
||||||
libclang-src = { url = "github:well-typed/libclang"; flake = false; };
|
|
||||||
flake-utils.url = "github:numtide/flake-utils";
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
crane.url = "github:ipetkov/crane";
|
crane.url = "github:ipetkov/crane";
|
||||||
rust-overlay = {
|
rust-overlay = {
|
||||||
@ -13,96 +11,51 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
outputs =
|
outputs =
|
||||||
inputs:
|
inputs@{ nixpkgs, ... }:
|
||||||
inputs.flake-utils.lib.eachSystem [ "x86_64-linux" ] (system:
|
inputs.flake-utils.lib.eachSystem [ "x86_64-linux" ] (system:
|
||||||
let
|
let
|
||||||
pkgs = haskell.nixpkgs.extend (import inputs.rust-overlay);
|
overlays = [
|
||||||
crane = (inputs.crane.mkLib pkgs).overrideToolchain (p: p.rust-bin.selectLatestNightlyWith (
|
inputs.haskell-nix.overlay
|
||||||
|
(final: _prev: {
|
||||||
|
hixProject =
|
||||||
|
final.haskell-nix.hix.project {
|
||||||
|
src = ./.;
|
||||||
|
evalSystem = "x86_64-linux";
|
||||||
|
name = "garnet";
|
||||||
|
compiler-nix-name = "ghc9141";
|
||||||
|
shell.tools.cabal = "latest";
|
||||||
|
shell.withHoogle = false;
|
||||||
|
shell.tools.haskell-language-server = {
|
||||||
|
src = inputs.hls-2-13;
|
||||||
|
sha256map = {
|
||||||
|
"https://github.com/snowleopard/alga"."d4e43fb42db05413459fb2df493361d5a666588a" = "0s1mlnl64wj7pkg3iipv5bb4syy3bhxwqzqv93zqlvkyfn64015i";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
})
|
||||||
|
(import inputs.rust-overlay)
|
||||||
|
];
|
||||||
|
pkgs = import nixpkgs { inherit system overlays; inherit (inputs.haskell-nix) config; };
|
||||||
|
haskell = pkgs.hixProject.flake { };
|
||||||
|
rust = (inputs.crane.mkLib pkgs).overrideToolchain (p: p.rust-bin.selectLatestNightlyWith (
|
||||||
toolchain: toolchain.default.override {
|
toolchain: toolchain.default.override {
|
||||||
extensions = [ "rust-src" "rust-analyzer" ];
|
extensions = [ "rust-src" ];
|
||||||
targets = [ "x86_64-unknown-linux-gnu" ];
|
targets = [ "x86_64-unknown-linux-gnu" ];
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
addLibcIncludeDir =
|
|
||||||
''
|
|
||||||
export C_INCLUDE_PATH="${pkgs.stdenv.cc.libc.dev}/include''${C_INCLUDE_PATH:+:$C_INCLUDE_PATH}"
|
|
||||||
'';
|
|
||||||
haskell = (import inputs.nix-haskell { inherit system inputs; } {
|
|
||||||
name = "garnet";
|
|
||||||
src = ./.;
|
|
||||||
compiler-nix-name = "ghc914";
|
|
||||||
source-repository-packages = {
|
|
||||||
# not on Hackage yet: https://well-typed.com/blog/2026/02/hs-bindgen-alpha
|
|
||||||
# we're using more recent versions than in that post, because we want record-dot support:
|
|
||||||
# https://github.com/well-typed/hs-bindgen/issues/1829#issuecomment-4081875451
|
|
||||||
c-expr-dsl = inputs.hs-bindgen-src + "/c-expr-dsl";
|
|
||||||
c-expr-runtime = inputs.hs-bindgen-src + "/c-expr-runtime";
|
|
||||||
hs-bindgen = inputs.hs-bindgen-src + "/hs-bindgen";
|
|
||||||
hs-bindgen-runtime = inputs.hs-bindgen-src + "/hs-bindgen-runtime";
|
|
||||||
libclang-bindings = inputs.libclang-src;
|
|
||||||
};
|
|
||||||
overrides = [
|
|
||||||
({ pkgs, ... }: {
|
|
||||||
packages.libclang-bindings.components.library = {
|
|
||||||
build-tools = [ pkgs.llvmPackages.llvm ];
|
|
||||||
libs = [ pkgs.llvmPackages.libclang ];
|
|
||||||
};
|
|
||||||
packages.garnet.components.library = {
|
|
||||||
preBuild = addLibcIncludeDir;
|
|
||||||
# try removing?
|
|
||||||
preConfigure = ''
|
|
||||||
mkdir -p rust/target/debug
|
|
||||||
ln -s ${garnet-rs}/include/garnet_rs.h rust/target/debug/garnet_rs.h
|
|
||||||
'';
|
|
||||||
preInstall = ''
|
|
||||||
cp ${garnet-rs}/lib/libCgarnet_rs.a dist/build/libCgarnet_rs.a
|
|
||||||
'';
|
|
||||||
configureFlags = [ "--extra-lib-dirs=${garnet-rs}/lib" ];
|
|
||||||
};
|
|
||||||
})
|
|
||||||
];
|
|
||||||
shell = {
|
|
||||||
tools = {
|
|
||||||
cabal = "latest";
|
|
||||||
haskell-language-server = {
|
|
||||||
src = inputs.hls-src;
|
|
||||||
sha256map = {
|
|
||||||
"https://github.com/snowleopard/alga" = {
|
|
||||||
"d4e43fb42db05413459fb2df493361d5a666588a" = "0s1mlnl64wj7pkg3iipv5bb4syy3bhxwqzqv93zqlvkyfn64015i";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
withHoogle = false;
|
|
||||||
withHaddock = true;
|
|
||||||
shellHook = addLibcIncludeDir;
|
|
||||||
};
|
|
||||||
});
|
|
||||||
garnet-rs = crane.buildPackage {
|
|
||||||
src = crane.cleanCargoSource ./rust;
|
|
||||||
doCheck = false;
|
|
||||||
installPhaseCommand = ''
|
|
||||||
mkdir -p $out/lib $out/include
|
|
||||||
cp target/release/libgarnet_rs.a $out/lib/libCgarnet_rs.a
|
|
||||||
cp target/release/garnet_rs.h $out/include/
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
in
|
in
|
||||||
rec {
|
{
|
||||||
defaultPackage = packages.garnet-exe;
|
|
||||||
packages = let garnet = haskell.project.haskell-nix.hsPkgs.garnet; in {
|
|
||||||
inherit garnet-rs;
|
|
||||||
garnet-exe = garnet.components.exes.garnet;
|
|
||||||
garnet-lib = garnet.components.library;
|
|
||||||
};
|
|
||||||
devShells.default = pkgs.mkShell {
|
devShells.default = pkgs.mkShell {
|
||||||
inputsFrom = [
|
inputsFrom = [
|
||||||
haskell.project.haskell-nix.shell
|
haskell.devShells.default
|
||||||
(crane.devShell { })
|
(rust.devShell { })
|
||||||
];
|
];
|
||||||
packages = with pkgs; [
|
packages = with pkgs; [
|
||||||
bacon
|
bacon
|
||||||
ghcid
|
ghcid
|
||||||
|
llvmPackages.libclang
|
||||||
|
llvmPackages.llvm
|
||||||
|
rust-analyzer
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
28
garnet.cabal
28
garnet.cabal
@ -6,21 +6,6 @@ author: Patrick Aldis
|
|||||||
maintainer:
|
maintainer:
|
||||||
george.thomas@obsidian.systems
|
george.thomas@obsidian.systems
|
||||||
patrick.aldis@obsidian.systems
|
patrick.aldis@obsidian.systems
|
||||||
-- aha, nice, this does fix recompilation checking
|
|
||||||
extra-source-files:
|
|
||||||
rust/target/debug/garnet_rs.h
|
|
||||||
-- that could be problematic given file is gitignored? unfortunately this doesn't work
|
|
||||||
-- tbf, I haven't even looked up the docs, just saw the autocompletion
|
|
||||||
-- extra-tmp-files:
|
|
||||||
-- rust/target/debug/garnet_rs.h
|
|
||||||
|
|
||||||
-- actually maybe this is pointless given we always need debug path anyway in `extra-source-files`
|
|
||||||
-- plus we have it in `Raw.hs`
|
|
||||||
flag dev
|
|
||||||
default:
|
|
||||||
False
|
|
||||||
manual:
|
|
||||||
True
|
|
||||||
|
|
||||||
common common
|
common common
|
||||||
default-language: GHC2024
|
default-language: GHC2024
|
||||||
@ -37,20 +22,17 @@ common common
|
|||||||
NoMonomorphismRestriction
|
NoMonomorphismRestriction
|
||||||
OverloadedRecordDot
|
OverloadedRecordDot
|
||||||
OverloadedStrings
|
OverloadedStrings
|
||||||
PatternSynonyms
|
|
||||||
RecordWildCards
|
RecordWildCards
|
||||||
ViewPatterns
|
ViewPatterns
|
||||||
ghc-options:
|
ghc-options:
|
||||||
-Wall
|
-Wall
|
||||||
-fdefer-type-errors
|
-fdefer-type-errors
|
||||||
build-depends:
|
build-depends:
|
||||||
base,
|
|
||||||
bytestring,
|
bytestring,
|
||||||
extra,
|
extra,
|
||||||
mtl,
|
mtl,
|
||||||
process,
|
process,
|
||||||
text,
|
text,
|
||||||
vector,
|
|
||||||
|
|
||||||
library
|
library
|
||||||
import: common
|
import: common
|
||||||
@ -58,16 +40,13 @@ library
|
|||||||
GarnetRs.Raw
|
GarnetRs.Raw
|
||||||
GarnetRs.Wrapped
|
GarnetRs.Wrapped
|
||||||
hs-source-dirs: lib
|
hs-source-dirs: lib
|
||||||
-- if flag (dev)
|
|
||||||
-- include-dirs: rust/target/debug
|
|
||||||
include-dirs: rust/target/debug
|
include-dirs: rust/target/debug
|
||||||
-- HLS gives up entirely when the header is malformed if we do this
|
extra-bundled-libraries: garnet_rs
|
||||||
-- and anyway, I don't think it gives us dependency tracking like `extra-source-files` does
|
|
||||||
-- includes: garnet_rs.h
|
|
||||||
extra-bundled-libraries: Cgarnet_rs
|
|
||||||
build-depends:
|
build-depends:
|
||||||
|
base,
|
||||||
hs-bindgen,
|
hs-bindgen,
|
||||||
hs-bindgen-runtime,
|
hs-bindgen-runtime,
|
||||||
|
primitive,
|
||||||
template-haskell,
|
template-haskell,
|
||||||
|
|
||||||
executable garnet
|
executable garnet
|
||||||
@ -79,4 +58,5 @@ executable garnet
|
|||||||
-rtsopts
|
-rtsopts
|
||||||
-with-rtsopts=-N
|
-with-rtsopts=-N
|
||||||
build-depends:
|
build-depends:
|
||||||
|
base,
|
||||||
garnet,
|
garnet,
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
{-# LANGUAGE CApiFFI #-}
|
{-# LANGUAGE CApiFFI #-}
|
||||||
{-# LANGUAGE DerivingVia #-}
|
{-# LANGUAGE DerivingVia #-}
|
||||||
|
{-# LANGUAGE FieldSelectors #-}
|
||||||
{-# LANGUAGE MagicHash #-}
|
{-# LANGUAGE MagicHash #-}
|
||||||
{-# LANGUAGE PatternSynonyms #-}
|
{-# LANGUAGE PatternSynonyms #-}
|
||||||
{-# LANGUAGE TemplateHaskell #-}
|
{-# LANGUAGE TemplateHaskell #-}
|
||||||
@ -29,10 +30,19 @@ import HsBindgen.TH
|
|||||||
import Language.Haskell.TH
|
import Language.Haskell.TH
|
||||||
import System.Process
|
import System.Process
|
||||||
|
|
||||||
|
do
|
||||||
|
systemDirs <- -- TODO bit of a hack
|
||||||
|
map (Dir . T.unpack . T.strip)
|
||||||
|
. concatMap (takeWhile (maybe False ((== ' ') . fst) . T.uncons) . dropWhile T.null . T.lines)
|
||||||
|
. drop 1
|
||||||
|
. T.splitOn "search starts here:"
|
||||||
|
. T.pack
|
||||||
|
. thd3
|
||||||
|
<$> runIO (readProcessWithExitCode "cpp" ["-v"] "")
|
||||||
withHsBindgen
|
withHsBindgen
|
||||||
def
|
def
|
||||||
{ clang = def{extraIncludeDirs = [Pkg "rust/target/debug"]}
|
{ clang = def{extraIncludeDirs = Pkg "rust/target/debug" : systemDirs}
|
||||||
, fieldNamingStrategy = OmitFieldPrefixes
|
, fieldNamingStrategy = EnableRecordDot
|
||||||
}
|
}
|
||||||
def
|
def
|
||||||
$ hashInclude "garnet_rs.h"
|
$ hashInclude "garnet_rs.h"
|
||||||
|
|||||||
@ -2,29 +2,19 @@
|
|||||||
-- or look at upstream plans: https://github.com/well-typed/hs-bindgen/issues?q=state%3Aopen%20label%3A%22highlevel%22
|
-- or look at upstream plans: https://github.com/well-typed/hs-bindgen/issues?q=state%3Aopen%20label%3A%22highlevel%22
|
||||||
module GarnetRs.Wrapped (
|
module GarnetRs.Wrapped (
|
||||||
T (..),
|
T (..),
|
||||||
Raw.E (..),
|
|
||||||
-- TODO hmm, we don't really want to have to list all of these...
|
|
||||||
-- is there an option to make them not be patterns at all?
|
|
||||||
pattern Raw.E1,
|
|
||||||
pattern Raw.E2,
|
|
||||||
pattern Raw.E3,
|
|
||||||
Shape (..),
|
Shape (..),
|
||||||
BTree (..),
|
BTree (..),
|
||||||
hello,
|
hello,
|
||||||
helloStruct,
|
helloStruct,
|
||||||
helloEnum,
|
|
||||||
helloShape,
|
helloShape,
|
||||||
add,
|
add,
|
||||||
sumTree,
|
sumTree,
|
||||||
sumSlice,
|
|
||||||
printOptional,
|
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Control.Monad.Cont
|
import Control.Monad.Cont
|
||||||
import Control.Monad.Trans
|
import Control.Monad.Trans
|
||||||
import Data.ByteString
|
import Data.ByteString
|
||||||
import Data.Function
|
import Data.Function
|
||||||
import Data.Vector.Storable qualified as V
|
|
||||||
import Data.Word
|
import Data.Word
|
||||||
import Foreign
|
import Foreign
|
||||||
import Foreign.C
|
import Foreign.C
|
||||||
@ -44,8 +34,8 @@ data Shape
|
|||||||
| Rectangle CDouble CDouble
|
| Rectangle CDouble CDouble
|
||||||
convertShape :: Shape -> Raw.Shape
|
convertShape :: Shape -> Raw.Shape
|
||||||
convertShape = \case
|
convertShape = \case
|
||||||
Circle r -> Raw.Shape Raw.Circle $ Raw.set_shape_circle_circle $ Raw.Circle_Body r
|
Circle r -> Raw.Shape Raw.Circle $ Raw.set_shape_body_circle $ Raw.Circle_Body r
|
||||||
Rectangle w h -> Raw.Shape Raw.Rectangle $ Raw.set_shape_circle_rectangle $ Raw.Rectangle_Body w h
|
Rectangle w h -> Raw.Shape Raw.Rectangle $ Raw.set_shape_body_rectangle $ Raw.Rectangle_Body w h
|
||||||
|
|
||||||
data BTree a
|
data BTree a
|
||||||
= Leaf a
|
= Leaf a
|
||||||
@ -53,38 +43,27 @@ data BTree a
|
|||||||
withBTree :: BTree Int64 -> (Raw.BTreeC -> IO a) -> IO a
|
withBTree :: BTree Int64 -> (Raw.BTreeC -> IO a) -> IO a
|
||||||
withBTree =
|
withBTree =
|
||||||
runContT . fix \f -> \case
|
runContT . fix \f -> \case
|
||||||
Leaf v -> pure $ Raw.BTreeC Raw.Leaf $ Raw.set_bTreeC_leaf_leaf $ Raw.Leaf_Body v
|
Leaf v -> pure $ Raw.BTreeC Raw.Leaf $ Raw.set_bTreeC_body_leaf $ Raw.Leaf_Body v
|
||||||
Fork l r -> do
|
Fork l r -> do
|
||||||
lRaw <- f l
|
lRaw <- f l
|
||||||
rRaw <- f r
|
rRaw <- f r
|
||||||
lPtr <- ContT alloca
|
lPtr <- ContT alloca
|
||||||
rPtr <- ContT alloca
|
rPtr <- ContT alloca
|
||||||
lift $ poke lPtr lRaw >> poke rPtr rRaw
|
lift $ poke lPtr lRaw >> poke rPtr rRaw
|
||||||
pure . Raw.BTreeC Raw.Fork . Raw.set_bTreeC_leaf_fork $
|
pure . Raw.BTreeC Raw.Fork . Raw.set_bTreeC_body_fork $
|
||||||
Raw.Fork_Body (unsafeFromPtr lPtr) (unsafeFromPtr rPtr)
|
Raw.Fork_Body (unsafeFromPtr lPtr) (unsafeFromPtr rPtr)
|
||||||
|
|
||||||
hello :: ByteString -> IO ()
|
hello :: ByteString -> IO ()
|
||||||
hello bs = useAsCString bs \ptr -> Raw.hello $ unsafeFromPtr ptr
|
hello s = useAsCString s $ Raw.hello . unsafeFromPtr
|
||||||
|
|
||||||
helloStruct :: T -> IO ()
|
helloStruct :: T -> IO ()
|
||||||
helloStruct t = with (convertT t) \ptr -> Raw.hello_struct $ unsafeFromPtr ptr
|
helloStruct = Raw.hello_struct . convertT
|
||||||
|
|
||||||
helloEnum :: Raw.E -> IO ()
|
|
||||||
helloEnum e = with e \ptr -> Raw.hello_enum $ unsafeFromPtr ptr
|
|
||||||
|
|
||||||
helloShape :: Shape -> IO ()
|
helloShape :: Shape -> IO ()
|
||||||
helloShape s = with (convertShape s) \ptr -> Raw.hello_shape $ unsafeFromPtr ptr
|
helloShape = Raw.hello_shape . convertShape
|
||||||
|
|
||||||
add :: Int64 -> Int64 -> Int64
|
add :: Int64 -> Int64 -> Int64
|
||||||
add = Raw.add
|
add = Raw.add
|
||||||
|
|
||||||
sumTree :: BTree Int64 -> Int64
|
sumTree :: BTree Int64 -> Int64
|
||||||
sumTree t = unsafePerformIO $ withBTree t \tc -> with tc \ptr -> Raw.sum_tree $ unsafeFromPtr ptr
|
sumTree = unsafePerformIO . flip withBTree Raw.sum_tree
|
||||||
|
|
||||||
sumSlice :: V.Vector Int64 -> Int64
|
|
||||||
sumSlice v = unsafePerformIO $ V.unsafeWith v \ptr -> Raw.sum_slice (unsafeFromPtr ptr) (fromIntegral $ V.length v)
|
|
||||||
|
|
||||||
printOptional :: Maybe Int8 -> IO ()
|
|
||||||
printOptional = \case
|
|
||||||
Nothing -> Raw.print_optional $ unsafeFromPtr nullPtr
|
|
||||||
Just t -> with t \ptr -> Raw.print_optional $ unsafeFromPtr ptr
|
|
||||||
|
|||||||
@ -1,36 +1,43 @@
|
|||||||
use std::env;
|
use std::env;
|
||||||
|
use std::fs;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// this doesn't make _much_ difference really, since this is our only Rust source file
|
|
||||||
// but it seems it's probably better than not having it
|
|
||||||
// what we really want is to tell Rust to only regenerate the header file if the Rust code actually compiles
|
|
||||||
// but we don't have that flexibility
|
|
||||||
// and it's an issue because cbindgen tries to be fault-tolerant in some ways that don't even seem to make sense
|
|
||||||
//
|
|
||||||
// e.g. mis-spell "Option" as "Option" and you get
|
|
||||||
// void print_optional(Optio<const int8_t*> x);
|
|
||||||
// instead of
|
|
||||||
// void print_optional(const int8_t *x);
|
|
||||||
// and that's only an issue because in HLS TH dependent-file watching gives up after an error
|
|
||||||
// i.e. once the containing splice has thrown an exception once, the containing file needs a manual edit to kick it
|
|
||||||
// and that's really not helped by Rust Analyzer mostly only showing diagnostics on save
|
|
||||||
// P.S. strings to stdout?! what a terrible API
|
|
||||||
// don't get me started in the discoverability of actually then using the terminal for debugging:
|
|
||||||
// println!("cargo::warning={:?}", env::var("OUT_DIR"));
|
|
||||||
println!("cargo::rerun-if-changed=lib.rs");
|
|
||||||
let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
|
let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
|
||||||
let profile = env::var("PROFILE").unwrap();
|
let profile = env::var("PROFILE").unwrap();
|
||||||
cbindgen::Builder::new()
|
|
||||||
|
let bindings = cbindgen::Builder::new()
|
||||||
.with_crate(&crate_dir)
|
.with_crate(&crate_dir)
|
||||||
.with_language(cbindgen::Language::C)
|
.with_language(cbindgen::Language::C)
|
||||||
.with_style(cbindgen::Style::Tag)
|
.with_style(cbindgen::Style::Tag)
|
||||||
.generate()
|
.generate()
|
||||||
.expect("Unable to generate bindings")
|
.expect("Unable to generate bindings");
|
||||||
.write_to_file(
|
|
||||||
|
// TODO vibe-coded workaround for hs-bindgen issue:
|
||||||
|
// https://github.com/well-typed/hs-bindgen/issues/1649#issuecomment-3994425922
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
bindings.write(&mut buf);
|
||||||
|
let header = String::from_utf8(buf).unwrap();
|
||||||
|
let mut patched = String::new();
|
||||||
|
let mut saw_union = false;
|
||||||
|
for line in header.lines() {
|
||||||
|
if line == " };" && saw_union {
|
||||||
|
patched.push_str(" } body;\n");
|
||||||
|
saw_union = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if line == " union {" {
|
||||||
|
saw_union = true;
|
||||||
|
}
|
||||||
|
patched.push_str(line);
|
||||||
|
patched.push('\n');
|
||||||
|
}
|
||||||
|
fs::write(
|
||||||
PathBuf::from(&crate_dir)
|
PathBuf::from(&crate_dir)
|
||||||
.join("target")
|
.join("target")
|
||||||
.join(&profile)
|
.join(&profile)
|
||||||
.join("garnet_rs.h"),
|
.join("garnet_rs.h"),
|
||||||
);
|
patched,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|||||||
37
rust/lib.rs
37
rust/lib.rs
@ -3,7 +3,6 @@
|
|||||||
use std::{
|
use std::{
|
||||||
ffi::{CStr, c_char},
|
ffi::{CStr, c_char},
|
||||||
ops::Add,
|
ops::Add,
|
||||||
slice,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fn say_hello(name: &str) {
|
fn say_hello(name: &str) {
|
||||||
@ -11,7 +10,7 @@ fn say_hello(name: &str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
extern "C" fn hello(c: *const c_char) {
|
extern "C" fn hello(c: *const c_char) -> () {
|
||||||
say_hello(unsafe { CStr::from_ptr(c) }.to_str().unwrap())
|
say_hello(unsafe { CStr::from_ptr(c) }.to_str().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,23 +22,10 @@ struct T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
extern "C" fn hello_struct(t: &T) {
|
extern "C" fn hello_struct(t: T) -> () {
|
||||||
say_hello(&format!("{:?}", t))
|
say_hello(&format!("{:?}", t))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum E {
|
|
||||||
E1,
|
|
||||||
E2,
|
|
||||||
E3,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
extern "C" fn hello_enum(e: &E) {
|
|
||||||
say_hello(&format!("{:?}", e))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum Shape {
|
enum Shape {
|
||||||
@ -48,7 +34,7 @@ enum Shape {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
extern "C" fn hello_shape(s: &Shape) {
|
extern "C" fn hello_shape(s: Shape) -> () {
|
||||||
say_hello(&format!("{:?}", s))
|
say_hello(&format!("{:?}", s))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,19 +78,6 @@ enum BTreeC {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
extern "C" fn sum_tree(t: &BTreeC) -> i64 {
|
extern "C" fn sum_tree(t: BTreeC) -> i64 {
|
||||||
(unsafe { std::mem::transmute::<_, &BTree<i64>>(t) }).sum()
|
(unsafe { std::mem::transmute::<_, &BTree<i64>>(&t) }).sum()
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
extern "C" fn sum_slice(v: *const i64, s: usize) -> i64 {
|
|
||||||
unsafe { slice::from_raw_parts(v, s) }.iter().sum()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
extern "C" fn print_optional(x: Option<&i8>) -> () {
|
|
||||||
match x {
|
|
||||||
Some(x) => println!("{}", x / 2),
|
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user