Compare commits
10 Commits
569fae5d32
...
24359a519c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
24359a519c | ||
|
|
aa05650ec8 | ||
|
|
34ce6078ba | ||
|
|
e53fb108f4 | ||
|
|
14ef0237cb | ||
|
|
96daf482ca | ||
|
|
ad78170066 | ||
|
|
b1d8b6e1bf | ||
|
|
7e572b75ee | ||
|
|
bc21f9e79f |
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,3 @@
|
|||||||
dist*
|
dist*/
|
||||||
result
|
result
|
||||||
target
|
target
|
||||||
|
|||||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "inputs/real"]
|
||||||
|
path = inputs/private
|
||||||
|
url = git@github.com:georgefst/aoc-private-inputs.git
|
||||||
@ -1,4 +1,4 @@
|
|||||||
packages: .
|
packages: haskell
|
||||||
|
|
||||||
-- TODO a total hack
|
-- TODO a total hack
|
||||||
package garnet
|
package garnet
|
||||||
@ -15,7 +15,7 @@ source-repository-package
|
|||||||
type: git
|
type: git
|
||||||
location: https://github.com/well-typed/hs-bindgen
|
location: https://github.com/well-typed/hs-bindgen
|
||||||
tag: e2a9260678d9fa76dab602a5a07927acada3be4f
|
tag: e2a9260678d9fa76dab602a5a07927acada3be4f
|
||||||
subdir: c-expr-dsl c-expr-runtime hs-bindgen-runtime
|
subdir: c-expr-dsl c-expr-runtime hs-bindgen hs-bindgen-runtime
|
||||||
--sha256: 0nrs3iq0l5ha5kxyhqnlmvgi7734pmzyp3zf7p8s1gb21ylh4sy0
|
--sha256: 0nrs3iq0l5ha5kxyhqnlmvgi7734pmzyp3zf7p8s1gb21ylh4sy0
|
||||||
source-repository-package
|
source-repository-package
|
||||||
type: git
|
type: git
|
||||||
|
|||||||
@ -1,41 +0,0 @@
|
|||||||
-- TODO automate this sort of high level wrapper boilerplate
|
|
||||||
-- or look at upstream plans: https://github.com/well-typed/hs-bindgen/issues?q=state%3Aopen%20label%3A%22highlevel%22
|
|
||||||
module GarnetRs.Wrapped (
|
|
||||||
T (..),
|
|
||||||
Shape (..),
|
|
||||||
hello,
|
|
||||||
helloStruct,
|
|
||||||
helloShape,
|
|
||||||
) where
|
|
||||||
|
|
||||||
import Data.ByteString
|
|
||||||
import Data.Word
|
|
||||||
import Foreign
|
|
||||||
import Foreign.C
|
|
||||||
import GarnetRs qualified as Raw
|
|
||||||
import GarnetRs.Safe qualified as Raw
|
|
||||||
import HsBindgen.Runtime.PtrConst
|
|
||||||
|
|
||||||
data T = T
|
|
||||||
{ a :: Bool
|
|
||||||
, b :: Word8
|
|
||||||
}
|
|
||||||
convertT :: T -> Raw.T
|
|
||||||
convertT T{a, b} = Raw.T{a = CBool $ fromBool a, b}
|
|
||||||
|
|
||||||
data Shape
|
|
||||||
= Circle CDouble
|
|
||||||
| Rectangle CDouble CDouble
|
|
||||||
convertShape :: Shape -> Raw.Shape
|
|
||||||
convertShape = \case
|
|
||||||
Circle r -> Raw.Shape (Raw.Shape_Tag 0) $ Raw.set_shape_body_circle $ Raw.Circle_Body r
|
|
||||||
Rectangle w h -> Raw.Shape (Raw.Shape_Tag 1) $ Raw.set_shape_body_rectangle $ Raw.Rectangle_Body w h
|
|
||||||
|
|
||||||
hello :: ByteString -> IO ()
|
|
||||||
hello s = useAsCString s $ Raw.hello . unsafeFromPtr
|
|
||||||
|
|
||||||
helloStruct :: T -> IO ()
|
|
||||||
helloStruct = Raw.hello_struct . convertT
|
|
||||||
|
|
||||||
helloShape :: Shape -> IO ()
|
|
||||||
helloShape = Raw.hello_shape . convertShape
|
|
||||||
11
exe/Main.hs
11
exe/Main.hs
@ -1,11 +0,0 @@
|
|||||||
module Main (main) where
|
|
||||||
|
|
||||||
import GarnetRs.Wrapped
|
|
||||||
|
|
||||||
main :: IO ()
|
|
||||||
main = do
|
|
||||||
hello "Haskell"
|
|
||||||
helloStruct T{a = True, b = 42}
|
|
||||||
helloStruct T{a = False, b = maxBound}
|
|
||||||
helloShape $ Circle 3.14
|
|
||||||
helloShape $ Rectangle 10.0 5.0
|
|
||||||
132
flake.lock
generated
132
flake.lock
generated
@ -85,11 +85,11 @@
|
|||||||
},
|
},
|
||||||
"crane": {
|
"crane": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1771438068,
|
"lastModified": 1771121070,
|
||||||
"narHash": "sha256-nGBbXvEZVe/egCPVPFcu89RFtd8Rf6J+4RFoVCFec0A=",
|
"narHash": "sha256-aIlv7FRXF9q70DNJPI237dEDAznSKaXmL5lfK/Id/bI=",
|
||||||
"owner": "ipetkov",
|
"owner": "ipetkov",
|
||||||
"repo": "crane",
|
"repo": "crane",
|
||||||
"rev": "b5090e53e9d68c523a4bb9ad42b4737ee6747597",
|
"rev": "a2812c19f1ed2e5ed5ce2ef7109798b575c180e1",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -115,24 +115,6 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-parts": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs-lib": "nixpkgs-lib"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1769996383,
|
|
||||||
"narHash": "sha256-AnYjnFWgS49RlqX7LrC4uA+sCCDBj0Ry/WOJ5XWAsa0=",
|
|
||||||
"owner": "hercules-ci",
|
|
||||||
"repo": "flake-parts",
|
|
||||||
"rev": "57928607ea566b5db3ad13af0e57e921e6b12381",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "hercules-ci",
|
|
||||||
"repo": "flake-parts",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-utils": {
|
"flake-utils": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"systems": "systems"
|
"systems": "systems"
|
||||||
@ -154,11 +136,11 @@
|
|||||||
"hackage": {
|
"hackage": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1771461386,
|
"lastModified": 1771289625,
|
||||||
"narHash": "sha256-93hCxhNOq9/HAggfTTurLhllI0IiEWZ35jk6i/X/qEo=",
|
"narHash": "sha256-ySABvJf2NaxGc1mPSkwKjC8So9S906UgOYZVzX35Ng8=",
|
||||||
"owner": "input-output-hk",
|
"owner": "input-output-hk",
|
||||||
"repo": "hackage.nix",
|
"repo": "hackage.nix",
|
||||||
"rev": "b4f4537825a4db29c10541a50d7eb6c848bf0dca",
|
"rev": "808af568b7e14e1eced115e65825d2f50a608008",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -170,11 +152,11 @@
|
|||||||
"hackage-for-stackage": {
|
"hackage-for-stackage": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1771461376,
|
"lastModified": 1771288450,
|
||||||
"narHash": "sha256-aEuZkBpTaU0XBFiaIomicJDoWQaw84rYfKXI/r17V/w=",
|
"narHash": "sha256-2tCS6CXMHPo4Jsh4JopbYBoQXnTTp8MdZVAqPVmOIq4=",
|
||||||
"owner": "input-output-hk",
|
"owner": "input-output-hk",
|
||||||
"repo": "hackage.nix",
|
"repo": "hackage.nix",
|
||||||
"rev": "ca611068e77f15b96ecf71fae827e491c0b2dc3b",
|
"rev": "3049efd880816a3bb98b7b5fb4062045fcddd474",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -200,7 +182,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"haskell-nix": {
|
"haskellNix": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"HTTP": "HTTP",
|
"HTTP": "HTTP",
|
||||||
"cabal-32": "cabal-32",
|
"cabal-32": "cabal-32",
|
||||||
@ -228,7 +210,7 @@
|
|||||||
"hpc-coveralls": "hpc-coveralls",
|
"hpc-coveralls": "hpc-coveralls",
|
||||||
"iserv-proxy": "iserv-proxy",
|
"iserv-proxy": "iserv-proxy",
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"haskell-nix",
|
"haskellNix",
|
||||||
"nixpkgs-unstable"
|
"nixpkgs-unstable"
|
||||||
],
|
],
|
||||||
"nixpkgs-2305": "nixpkgs-2305",
|
"nixpkgs-2305": "nixpkgs-2305",
|
||||||
@ -242,11 +224,11 @@
|
|||||||
"stackage": "stackage"
|
"stackage": "stackage"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1771462666,
|
"lastModified": 1771289806,
|
||||||
"narHash": "sha256-z+pJFzbYa1ulNDUZdb0qLVVAdE0dqpnE51jqh2chA7c=",
|
"narHash": "sha256-s60Kb3cYr0t6LDQ/LmJr5vQN8Z4IY1Vfwq2keZW0VOM=",
|
||||||
"owner": "input-output-hk",
|
"owner": "input-output-hk",
|
||||||
"repo": "haskell.nix",
|
"repo": "haskell.nix",
|
||||||
"rev": "857ba7b65d9c1a8765ad1599834a8fe71cb09981",
|
"rev": "3331ba591ae02a41c638aeb6bea91d268b34cf8e",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -525,27 +507,6 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"hs-bindgen": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-parts": "flake-parts",
|
|
||||||
"libclang-bindings-src": "libclang-bindings-src",
|
|
||||||
"nixpkgs": "nixpkgs"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1770394582,
|
|
||||||
"narHash": "sha256-erbj5xqqJ/M0c99G0vjZvJtvoxYJ1PG7DDkw15MVLK8=",
|
|
||||||
"owner": "well-typed",
|
|
||||||
"repo": "hs-bindgen",
|
|
||||||
"rev": "e2a9260678d9fa76dab602a5a07927acada3be4f",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "well-typed",
|
|
||||||
"ref": "release-0.1-alpha",
|
|
||||||
"repo": "hs-bindgen",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"iserv-proxy": {
|
"iserv-proxy": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
@ -563,39 +524,6 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"libclang-bindings-src": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1770274896,
|
|
||||||
"narHash": "sha256-JnxJBo2L4URFD8JbpjnPG/ej/xKFe7y5ZpjnvIztwAM=",
|
|
||||||
"owner": "well-typed",
|
|
||||||
"repo": "libclang",
|
|
||||||
"rev": "155642a4a4a9f0414a058a8f08f39aa6c7bb57ed",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "well-typed",
|
|
||||||
"repo": "libclang",
|
|
||||||
"rev": "155642a4a4a9f0414a058a8f08f39aa6c7bb57ed",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1770169770,
|
|
||||||
"narHash": "sha256-awR8qIwJxJJiOmcEGgP2KUqYmHG4v/z8XpL9z8FnT1A=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "aa290c9891fa4ebe88f8889e59633d20cc06a5f2",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "nixpkgs-unstable",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs-2305": {
|
"nixpkgs-2305": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1705033721,
|
"lastModified": 1705033721,
|
||||||
@ -692,21 +620,6 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs-lib": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1769909678,
|
|
||||||
"narHash": "sha256-cBEymOf4/o3FD5AZnzC3J9hLbiZ+QDT/KDuyHXVJOpM=",
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "nixpkgs.lib",
|
|
||||||
"rev": "72716169fe93074c333e8d0173151350670b824c",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "nixpkgs.lib",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs-unstable": {
|
"nixpkgs-unstable": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1764587062,
|
"lastModified": 1764587062,
|
||||||
@ -744,11 +657,10 @@
|
|||||||
"inputs": {
|
"inputs": {
|
||||||
"crane": "crane",
|
"crane": "crane",
|
||||||
"flake-utils": "flake-utils",
|
"flake-utils": "flake-utils",
|
||||||
"haskell-nix": "haskell-nix",
|
"haskellNix": "haskellNix",
|
||||||
"hls-2-13": "hls-2-13",
|
"hls-2-13": "hls-2-13",
|
||||||
"hs-bindgen": "hs-bindgen",
|
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"haskell-nix",
|
"haskellNix",
|
||||||
"nixpkgs-2511"
|
"nixpkgs-2511"
|
||||||
],
|
],
|
||||||
"rust-overlay": "rust-overlay"
|
"rust-overlay": "rust-overlay"
|
||||||
@ -761,11 +673,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1771470520,
|
"lastModified": 1771297684,
|
||||||
"narHash": "sha256-PvytHcaYN5cPUll7FB70mXv1rRsIBRmu47fFfq3haxA=",
|
"narHash": "sha256-wieWskQxZLPlNXX06JEB0bMoS/ZYQ89xBzF0RL9lyLs=",
|
||||||
"owner": "oxalica",
|
"owner": "oxalica",
|
||||||
"repo": "rust-overlay",
|
"repo": "rust-overlay",
|
||||||
"rev": "a1d4cc1f264c45d3745af0d2ca5e59d460e58777",
|
"rev": "755d3669699a7c62aef35af187d75dc2728cfd85",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -777,11 +689,11 @@
|
|||||||
"stackage": {
|
"stackage": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1771460325,
|
"lastModified": 1771287554,
|
||||||
"narHash": "sha256-RRsGO7QVyuBtUTVqDiB7CYvFruj0Z/yxZK1JarkTqI4=",
|
"narHash": "sha256-76Kd5c2D4O8yL48eAejlGZlpQ/Exxnsz3V7qW+RkFzE=",
|
||||||
"owner": "input-output-hk",
|
"owner": "input-output-hk",
|
||||||
"repo": "stackage.nix",
|
"repo": "stackage.nix",
|
||||||
"rev": "29c0dcc517e04be238023064412312ad4443ddb2",
|
"rev": "e62b9d6269c6abfd8b976826da0dcc37f0a57010",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
35
flake.nix
35
flake.nix
@ -1,22 +1,28 @@
|
|||||||
{
|
{
|
||||||
inputs = {
|
inputs = {
|
||||||
haskell-nix.url = "github:input-output-hk/haskell.nix";
|
haskellNix.url = "github:input-output-hk/haskell.nix";
|
||||||
hls-2-13 = { url = "github:haskell/haskell-language-server/2.13.0.0"; flake = false; };
|
hls-2-13 = { url = "github:haskell/haskell-language-server/2.13.0.0"; flake = false; };
|
||||||
nixpkgs.follows = "haskell-nix/nixpkgs-2511";
|
nixpkgs.follows = "haskellNix/nixpkgs-2511";
|
||||||
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 = {
|
||||||
url = "github:oxalica/rust-overlay";
|
url = "github:oxalica/rust-overlay";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
hs-bindgen.url = "github:well-typed/hs-bindgen/release-0.1-alpha";
|
|
||||||
};
|
};
|
||||||
outputs =
|
outputs =
|
||||||
inputs@{ nixpkgs, ... }:
|
{ self
|
||||||
inputs.flake-utils.lib.eachSystem [ "x86_64-linux" ] (system:
|
, nixpkgs
|
||||||
|
, flake-utils
|
||||||
|
, haskellNix
|
||||||
|
, hls-2-13
|
||||||
|
, crane
|
||||||
|
, rust-overlay
|
||||||
|
}:
|
||||||
|
flake-utils.lib.eachSystem [ "x86_64-linux" ] (system:
|
||||||
let
|
let
|
||||||
overlays = [
|
overlays = [
|
||||||
inputs.haskell-nix.overlay
|
haskellNix.overlay
|
||||||
(final: _prev: {
|
(final: _prev: {
|
||||||
hixProject =
|
hixProject =
|
||||||
final.haskell-nix.hix.project {
|
final.haskell-nix.hix.project {
|
||||||
@ -27,18 +33,20 @@
|
|||||||
shell.tools.cabal = "latest";
|
shell.tools.cabal = "latest";
|
||||||
shell.withHoogle = false;
|
shell.withHoogle = false;
|
||||||
shell.tools.haskell-language-server = {
|
shell.tools.haskell-language-server = {
|
||||||
src = inputs.hls-2-13;
|
src = hls-2-13;
|
||||||
sha256map = {
|
sha256map = {
|
||||||
"https://github.com/snowleopard/alga"."d4e43fb42db05413459fb2df493361d5a666588a" = "0s1mlnl64wj7pkg3iipv5bb4syy3bhxwqzqv93zqlvkyfn64015i";
|
"https://github.com/snowleopard/alga"."d4e43fb42db05413459fb2df493361d5a666588a" = "0s1mlnl64wj7pkg3iipv5bb4syy3bhxwqzqv93zqlvkyfn64015i";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
(import inputs.rust-overlay)
|
(import rust-overlay)
|
||||||
];
|
];
|
||||||
pkgs = import nixpkgs { inherit system overlays; inherit (inputs.haskell-nix) config; };
|
pkgs = import nixpkgs { inherit system overlays; inherit (haskellNix) config; };
|
||||||
haskell = pkgs.hixProject.flake { };
|
haskell = pkgs.hixProject.flake { };
|
||||||
rust = (inputs.crane.mkLib pkgs).overrideToolchain (p: p.rust-bin.selectLatestNightlyWith (
|
# TODO we're not getting Rust libs from Nix
|
||||||
|
# i.e. running `cargo clean && cargo build` rebuilds dependencies
|
||||||
|
rust = (crane.mkLib pkgs).overrideToolchain (p: p.rust-bin.selectLatestNightlyWith (
|
||||||
toolchain: toolchain.default.override {
|
toolchain: toolchain.default.override {
|
||||||
extensions = [ "rust-src" ];
|
extensions = [ "rust-src" ];
|
||||||
targets = [ "x86_64-unknown-linux-gnu" ];
|
targets = [ "x86_64-unknown-linux-gnu" ];
|
||||||
@ -52,12 +60,13 @@
|
|||||||
(rust.devShell { })
|
(rust.devShell { })
|
||||||
];
|
];
|
||||||
packages = with pkgs; [
|
packages = with pkgs; [
|
||||||
|
llvmPackages.libclang
|
||||||
|
llvmPackages.llvm
|
||||||
bacon
|
bacon
|
||||||
ghcid
|
ghcid
|
||||||
inputs.hs-bindgen.packages.${system}.hs-bindgen-cli
|
|
||||||
rust-analyzer
|
rust-analyzer
|
||||||
rust-cbindgen
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
});
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,15 +3,23 @@ set -euo pipefail
|
|||||||
|
|
||||||
# TODO this is a complete vibe-coded hack, but the header patching at least is crucial
|
# TODO this is a complete vibe-coded hack, but the header patching at least is crucial
|
||||||
|
|
||||||
|
# TODO fully-vibed hack
|
||||||
|
# we should do a few things quite differently anyway
|
||||||
|
|
||||||
|
# generated Haskell code shouldn't be checked in as it's not portable
|
||||||
|
# does the TH way of using `hs-bindgen` help here?
|
||||||
|
# I guess we shouldn't check in the generated C header either
|
||||||
|
|
||||||
# Generate Haskell FFI bindings from Rust source code.
|
# Generate Haskell FFI bindings from Rust source code.
|
||||||
#
|
#
|
||||||
# Pipeline: cargo build -> cbindgen -> patch header -> hs-bindgen
|
# Pipeline: cargo build -> cbindgen -> patch header -> hs-bindgen
|
||||||
#
|
#
|
||||||
# Prerequisites: run inside the Nix dev shell (provides gcc, cabal, cbindgen, hs-bindgen-cli).
|
# Prerequisites: run inside the Nix dev shell (provides gcc, cabal, etc.)
|
||||||
|
# cbindgen is fetched via `nix run nixpkgs#rust-cbindgen`.
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
RUST_DIR="$SCRIPT_DIR/rust"
|
RUST_DIR="$SCRIPT_DIR/rust"
|
||||||
HASKELL_DIR="$SCRIPT_DIR"
|
HASKELL_DIR="$SCRIPT_DIR/haskell"
|
||||||
HEADER_NAME="garnet_rs.h"
|
HEADER_NAME="garnet_rs.h"
|
||||||
HEADER="$RUST_DIR/$HEADER_NAME"
|
HEADER="$RUST_DIR/$HEADER_NAME"
|
||||||
|
|
||||||
@ -21,7 +29,7 @@ cargo build --manifest-path "$RUST_DIR/Cargo.toml"
|
|||||||
|
|
||||||
# --- Step 2: Generate C header with cbindgen ---
|
# --- Step 2: Generate C header with cbindgen ---
|
||||||
echo "=== Running cbindgen ==="
|
echo "=== Running cbindgen ==="
|
||||||
cbindgen \
|
nix run nixpkgs#rust-cbindgen -- \
|
||||||
--lang c \
|
--lang c \
|
||||||
--crate garnet-rs \
|
--crate garnet-rs \
|
||||||
--output "$HEADER" \
|
--output "$HEADER" \
|
||||||
@ -89,7 +97,8 @@ pending_enum && /^typedef [A-Za-z0-9_]+ / {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{ print }
|
{ print }
|
||||||
' "$HEADER" > "${HEADER}.tmp" && mv "${HEADER}.tmp" "$HEADER"
|
' "$HEADER" > "${HEADER}.tmp"
|
||||||
|
mv "${HEADER}.tmp" "$HEADER"
|
||||||
|
|
||||||
echo " Patched header at $HEADER"
|
echo " Patched header at $HEADER"
|
||||||
|
|
||||||
@ -115,7 +124,7 @@ fi
|
|||||||
|
|
||||||
# --- Step 5: Run hs-bindgen ---
|
# --- Step 5: Run hs-bindgen ---
|
||||||
echo "=== Running hs-bindgen ==="
|
echo "=== Running hs-bindgen ==="
|
||||||
hs-bindgen-cli preprocess \
|
cabal run -- hs-bindgen-cli preprocess \
|
||||||
--overwrite-files --create-output-dirs \
|
--overwrite-files --create-output-dirs \
|
||||||
--unique-id com.garnet --enable-record-dot \
|
--unique-id com.garnet --enable-record-dot \
|
||||||
--hs-output-dir "$HASKELL_DIR/generated" --module GarnetRs \
|
--hs-output-dir "$HASKELL_DIR/generated" --module GarnetRs \
|
||||||
@ -124,4 +133,4 @@ hs-bindgen-cli preprocess \
|
|||||||
|
|
||||||
echo "=== Done ==="
|
echo "=== Done ==="
|
||||||
echo "Generated Haskell bindings in $HASKELL_DIR/generated/"
|
echo "Generated Haskell bindings in $HASKELL_DIR/generated/"
|
||||||
echo "Run 'cabal run' to test."
|
echo "Run 'cabal run garnet' to test."
|
||||||
|
|||||||
30
haskell/LICENSE
Normal file
30
haskell/LICENSE
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
Copyright (c) 2025, George Thomas
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following
|
||||||
|
disclaimer in the documentation and/or other materials provided
|
||||||
|
with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of George Thomas nor the names of other
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
32
haskell/exe/Main.hs
Normal file
32
haskell/exe/Main.hs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
module Main (main) where
|
||||||
|
|
||||||
|
import Data.ByteString
|
||||||
|
import Data.Word
|
||||||
|
import Foreign.C
|
||||||
|
import GarnetRs
|
||||||
|
import GarnetRs.Safe
|
||||||
|
import HsBindgen.Runtime.PtrConst
|
||||||
|
import Unsafe.Coerce
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
useAsCString "Haskell" $ hello . unsafeFromPtr
|
||||||
|
hello_struct $ convertT T'{a = True, b = 42}
|
||||||
|
hello_struct $ convertT T'{a = False, b = 42}
|
||||||
|
hello_shape $ convertShape $ Circle 3.14
|
||||||
|
hello_shape $ convertShape $ Rectangle 10.0 5.0
|
||||||
|
|
||||||
|
data T' = T'
|
||||||
|
{ a :: Bool
|
||||||
|
, b :: Word8
|
||||||
|
}
|
||||||
|
convertT T'{a, b} =
|
||||||
|
-- T{a = CBool $ unsafeCoerce @Bool @Word8 a, b}
|
||||||
|
T{a = CBool $ fromIntegral $ fromEnum a, b}
|
||||||
|
|
||||||
|
data Shape'
|
||||||
|
= Circle CDouble
|
||||||
|
| Rectangle CDouble CDouble
|
||||||
|
convertShape = \case
|
||||||
|
Circle r -> Shape (Shape_Tag 0) $ set_shape_body_circle $ Circle_Body r
|
||||||
|
Rectangle w h -> Shape (Shape_Tag 1) $ set_shape_body_rectangle $ Rectangle_Body w h
|
||||||
@ -1,11 +1,9 @@
|
|||||||
cabal-version: 3.0
|
cabal-version: 3.0
|
||||||
name: garnet
|
name: garnet
|
||||||
version: 0.1.0.0
|
version: 0.1.0.0
|
||||||
license: BSD-3-Clause
|
license-file: LICENSE
|
||||||
author: Patrick Aldis
|
author: Patrick Aldis
|
||||||
maintainer:
|
maintainer: patricktaldis@gmail.com
|
||||||
george.thomas@obsidian.systems
|
|
||||||
patrick.aldis@obsidian.systems
|
|
||||||
|
|
||||||
library garnet-generated
|
library garnet-generated
|
||||||
hs-source-dirs: generated
|
hs-source-dirs: generated
|
||||||
@ -23,8 +21,6 @@ library garnet-generated
|
|||||||
|
|
||||||
executable garnet
|
executable garnet
|
||||||
main-is: Main.hs
|
main-is: Main.hs
|
||||||
other-modules:
|
|
||||||
GarnetRs.Wrapped
|
|
||||||
hs-source-dirs: exe
|
hs-source-dirs: exe
|
||||||
default-language: GHC2024
|
default-language: GHC2024
|
||||||
default-extensions:
|
default-extensions:
|
||||||
@ -1,5 +1,3 @@
|
|||||||
#![allow(dead_code)]
|
|
||||||
|
|
||||||
use std::ffi::{CStr, c_char};
|
use std::ffi::{CStr, c_char};
|
||||||
|
|
||||||
fn say_hello(name: &str) {
|
fn say_hello(name: &str) {
|
||||||
@ -23,6 +21,7 @@ extern "C" fn hello_struct(t: T) -> () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C, u8)]
|
#[repr(C, u8)]
|
||||||
|
#[allow(dead_code)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum Shape {
|
enum Shape {
|
||||||
Circle { radius: f64 },
|
Circle { radius: f64 },
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user