Compare commits

..

19 Commits

Author SHA1 Message Date
George Thomas
569fae5d32 Move Haskell package to top level 2026-02-19 14:15:14 +00:00
George Thomas
dba9dbfc78 Rename Haskell.nix flake input 2026-02-19 14:11:45 +00:00
George Thomas
738315da88 Bump flake inputs 2026-02-19 14:11:45 +00:00
George Thomas
4606c040f8 Reformat 2026-02-19 14:11:45 +00:00
George Thomas
f539fe609a Refactor Nix flake inputs 2026-02-19 14:11:45 +00:00
George Thomas
577bc54ec4 Disable dead code warning for whole Rust file 2026-02-19 14:11:45 +00:00
George Thomas
ca87a67686 Call struct function with different arguments 2026-02-19 14:11:32 +00:00
George Thomas
e740db0a24 Create manual high level wrapper 2026-02-19 14:11:05 +00:00
George Thomas
7c988765fa Add Bash script dependencies to Nix shell 2026-02-19 13:57:14 +00:00
George Thomas
6a600f3aec Simplify use sites by passing by value 2026-02-19 13:57:14 +00:00
George Thomas
2e7770df7a Use ByteString 2026-02-19 13:57:14 +00:00
George Thomas
0f88ebe316 Add more complex data types 2026-02-19 13:57:14 +00:00
George Thomas
e434f0d4b0 Expose explicit C interface 2026-02-19 13:57:14 +00:00
George Thomas
60f5f23b2d Move Haskell executable in to subdirectory 2026-02-19 13:57:14 +00:00
George Thomas
400960b0be Remove empty other-modules 2026-02-19 13:57:14 +00:00
George Thomas
7bb41f6825 Call Rust from Haskell with cargo-cabal and hs-bindgen
See https://sraka.xyz/posts/hs-bindgen-introduction.html.

For now, this is a shell-based workflow, rather than using Nix to build everything, i.e. `nix develop` works but `nix build` doesn't. And `cargo build` has to be called manually to create the C library, rather than `cabal` being clever enough to invoke it itself.

We ran `cargo cabal init` from the `rust` directory (`nix shell github:yvan-sraka/cargo-cabal`), which generated `hsbindgen.toml` (which we use), and `Setup.lhs` (which just added `extra-lib-dirs`, and with the wrong paths, so we dspecify those statically instead in `garnet.cabal`). We also follow its advice to use `staticlib`.

Also, after we ran the first `cargo build` (requiring a `mkdir rust/src` before it would run), we took the generated the Haskell file, and moved the main contents in to `Main.hs` manually.
2026-02-19 13:57:14 +00:00
George Thomas
ff8826d758 Fix authorship info 2026-02-19 13:57:14 +00:00
George Thomas
4ed5c5e1ae Simplify .gitignore 2026-02-19 13:57:14 +00:00
George Thomas
f664efc0e2 Remove stray Git submodule config 2026-02-19 13:56:00 +00:00
16 changed files with 192 additions and 130 deletions

2
.gitignore vendored
View File

@ -1,3 +1,3 @@
dist*/ dist*
result result
target target

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "inputs/real"]
path = inputs/private
url = git@github.com:georgefst/aoc-private-inputs.git

View File

@ -1,4 +1,4 @@
packages: haskell packages: .
-- 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 hs-bindgen-runtime subdir: c-expr-dsl c-expr-runtime hs-bindgen-runtime
--sha256: 0nrs3iq0l5ha5kxyhqnlmvgi7734pmzyp3zf7p8s1gb21ylh4sy0 --sha256: 0nrs3iq0l5ha5kxyhqnlmvgi7734pmzyp3zf7p8s1gb21ylh4sy0
source-repository-package source-repository-package
type: git type: git

41
exe/GarnetRs/Wrapped.hs Normal file
View File

@ -0,0 +1,41 @@
-- 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 Normal file
View File

@ -0,0 +1,11 @@
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
View File

@ -85,11 +85,11 @@
}, },
"crane": { "crane": {
"locked": { "locked": {
"lastModified": 1771121070, "lastModified": 1771438068,
"narHash": "sha256-aIlv7FRXF9q70DNJPI237dEDAznSKaXmL5lfK/Id/bI=", "narHash": "sha256-nGBbXvEZVe/egCPVPFcu89RFtd8Rf6J+4RFoVCFec0A=",
"owner": "ipetkov", "owner": "ipetkov",
"repo": "crane", "repo": "crane",
"rev": "a2812c19f1ed2e5ed5ce2ef7109798b575c180e1", "rev": "b5090e53e9d68c523a4bb9ad42b4737ee6747597",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -115,6 +115,24 @@
"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"
@ -136,11 +154,11 @@
"hackage": { "hackage": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1771289625, "lastModified": 1771461386,
"narHash": "sha256-ySABvJf2NaxGc1mPSkwKjC8So9S906UgOYZVzX35Ng8=", "narHash": "sha256-93hCxhNOq9/HAggfTTurLhllI0IiEWZ35jk6i/X/qEo=",
"owner": "input-output-hk", "owner": "input-output-hk",
"repo": "hackage.nix", "repo": "hackage.nix",
"rev": "808af568b7e14e1eced115e65825d2f50a608008", "rev": "b4f4537825a4db29c10541a50d7eb6c848bf0dca",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -152,11 +170,11 @@
"hackage-for-stackage": { "hackage-for-stackage": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1771288450, "lastModified": 1771461376,
"narHash": "sha256-2tCS6CXMHPo4Jsh4JopbYBoQXnTTp8MdZVAqPVmOIq4=", "narHash": "sha256-aEuZkBpTaU0XBFiaIomicJDoWQaw84rYfKXI/r17V/w=",
"owner": "input-output-hk", "owner": "input-output-hk",
"repo": "hackage.nix", "repo": "hackage.nix",
"rev": "3049efd880816a3bb98b7b5fb4062045fcddd474", "rev": "ca611068e77f15b96ecf71fae827e491c0b2dc3b",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -182,7 +200,7 @@
"type": "github" "type": "github"
} }
}, },
"haskellNix": { "haskell-nix": {
"inputs": { "inputs": {
"HTTP": "HTTP", "HTTP": "HTTP",
"cabal-32": "cabal-32", "cabal-32": "cabal-32",
@ -210,7 +228,7 @@
"hpc-coveralls": "hpc-coveralls", "hpc-coveralls": "hpc-coveralls",
"iserv-proxy": "iserv-proxy", "iserv-proxy": "iserv-proxy",
"nixpkgs": [ "nixpkgs": [
"haskellNix", "haskell-nix",
"nixpkgs-unstable" "nixpkgs-unstable"
], ],
"nixpkgs-2305": "nixpkgs-2305", "nixpkgs-2305": "nixpkgs-2305",
@ -224,11 +242,11 @@
"stackage": "stackage" "stackage": "stackage"
}, },
"locked": { "locked": {
"lastModified": 1771289806, "lastModified": 1771462666,
"narHash": "sha256-s60Kb3cYr0t6LDQ/LmJr5vQN8Z4IY1Vfwq2keZW0VOM=", "narHash": "sha256-z+pJFzbYa1ulNDUZdb0qLVVAdE0dqpnE51jqh2chA7c=",
"owner": "input-output-hk", "owner": "input-output-hk",
"repo": "haskell.nix", "repo": "haskell.nix",
"rev": "3331ba591ae02a41c638aeb6bea91d268b34cf8e", "rev": "857ba7b65d9c1a8765ad1599834a8fe71cb09981",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -507,6 +525,27 @@
"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": {
@ -524,6 +563,39 @@
"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,
@ -620,6 +692,21 @@
"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,
@ -657,10 +744,11 @@
"inputs": { "inputs": {
"crane": "crane", "crane": "crane",
"flake-utils": "flake-utils", "flake-utils": "flake-utils",
"haskellNix": "haskellNix", "haskell-nix": "haskell-nix",
"hls-2-13": "hls-2-13", "hls-2-13": "hls-2-13",
"hs-bindgen": "hs-bindgen",
"nixpkgs": [ "nixpkgs": [
"haskellNix", "haskell-nix",
"nixpkgs-2511" "nixpkgs-2511"
], ],
"rust-overlay": "rust-overlay" "rust-overlay": "rust-overlay"
@ -673,11 +761,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1771297684, "lastModified": 1771470520,
"narHash": "sha256-wieWskQxZLPlNXX06JEB0bMoS/ZYQ89xBzF0RL9lyLs=", "narHash": "sha256-PvytHcaYN5cPUll7FB70mXv1rRsIBRmu47fFfq3haxA=",
"owner": "oxalica", "owner": "oxalica",
"repo": "rust-overlay", "repo": "rust-overlay",
"rev": "755d3669699a7c62aef35af187d75dc2728cfd85", "rev": "a1d4cc1f264c45d3745af0d2ca5e59d460e58777",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -689,11 +777,11 @@
"stackage": { "stackage": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1771287554, "lastModified": 1771460325,
"narHash": "sha256-76Kd5c2D4O8yL48eAejlGZlpQ/Exxnsz3V7qW+RkFzE=", "narHash": "sha256-RRsGO7QVyuBtUTVqDiB7CYvFruj0Z/yxZK1JarkTqI4=",
"owner": "input-output-hk", "owner": "input-output-hk",
"repo": "stackage.nix", "repo": "stackage.nix",
"rev": "e62b9d6269c6abfd8b976826da0dcc37f0a57010", "rev": "29c0dcc517e04be238023064412312ad4443ddb2",
"type": "github" "type": "github"
}, },
"original": { "original": {

View File

@ -1,28 +1,22 @@
{ {
inputs = { inputs = {
haskellNix.url = "github:input-output-hk/haskell.nix"; haskell-nix.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 = "haskellNix/nixpkgs-2511"; nixpkgs.follows = "haskell-nix/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 =
{ self inputs@{ nixpkgs, ... }:
, nixpkgs inputs.flake-utils.lib.eachSystem [ "x86_64-linux" ] (system:
, flake-utils
, haskellNix
, hls-2-13
, crane
, rust-overlay
}:
flake-utils.lib.eachSystem [ "x86_64-linux" ] (system:
let let
overlays = [ overlays = [
haskellNix.overlay inputs.haskell-nix.overlay
(final: _prev: { (final: _prev: {
hixProject = hixProject =
final.haskell-nix.hix.project { final.haskell-nix.hix.project {
@ -33,20 +27,18 @@
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 = hls-2-13; src = inputs.hls-2-13;
sha256map = { sha256map = {
"https://github.com/snowleopard/alga"."d4e43fb42db05413459fb2df493361d5a666588a" = "0s1mlnl64wj7pkg3iipv5bb4syy3bhxwqzqv93zqlvkyfn64015i"; "https://github.com/snowleopard/alga"."d4e43fb42db05413459fb2df493361d5a666588a" = "0s1mlnl64wj7pkg3iipv5bb4syy3bhxwqzqv93zqlvkyfn64015i";
}; };
}; };
}; };
}) })
(import rust-overlay) (import inputs.rust-overlay)
]; ];
pkgs = import nixpkgs { inherit system overlays; inherit (haskellNix) config; }; pkgs = import nixpkgs { inherit system overlays; inherit (inputs.haskell-nix) config; };
haskell = pkgs.hixProject.flake { }; haskell = pkgs.hixProject.flake { };
# TODO we're not getting Rust libs from Nix rust = (inputs.crane.mkLib pkgs).overrideToolchain (p: p.rust-bin.selectLatestNightlyWith (
# 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" ];
@ -60,13 +52,12 @@
(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
]; ];
}; };
} });
);
} }

View File

@ -1,9 +1,11 @@
cabal-version: 3.0 cabal-version: 3.0
name: garnet name: garnet
version: 0.1.0.0 version: 0.1.0.0
license-file: LICENSE license: BSD-3-Clause
author: Patrick Aldis author: Patrick Aldis
maintainer: patricktaldis@gmail.com maintainer:
george.thomas@obsidian.systems
patrick.aldis@obsidian.systems
library garnet-generated library garnet-generated
hs-source-dirs: generated hs-source-dirs: generated
@ -21,6 +23,8 @@ 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:

View File

@ -3,23 +3,15 @@ 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, etc.) # Prerequisites: run inside the Nix dev shell (provides gcc, cabal, cbindgen, hs-bindgen-cli).
# 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" HASKELL_DIR="$SCRIPT_DIR"
HEADER_NAME="garnet_rs.h" HEADER_NAME="garnet_rs.h"
HEADER="$RUST_DIR/$HEADER_NAME" HEADER="$RUST_DIR/$HEADER_NAME"
@ -29,7 +21,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 ==="
nix run nixpkgs#rust-cbindgen -- \ cbindgen \
--lang c \ --lang c \
--crate garnet-rs \ --crate garnet-rs \
--output "$HEADER" \ --output "$HEADER" \
@ -97,8 +89,7 @@ pending_enum && /^typedef [A-Za-z0-9_]+ / {
} }
{ print } { print }
' "$HEADER" > "${HEADER}.tmp" ' "$HEADER" > "${HEADER}.tmp" && mv "${HEADER}.tmp" "$HEADER"
mv "${HEADER}.tmp" "$HEADER"
echo " Patched header at $HEADER" echo " Patched header at $HEADER"
@ -124,7 +115,7 @@ fi
# --- Step 5: Run hs-bindgen --- # --- Step 5: Run hs-bindgen ---
echo "=== Running hs-bindgen ===" echo "=== Running hs-bindgen ==="
cabal run -- hs-bindgen-cli preprocess \ 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 \
@ -133,4 +124,4 @@ cabal run -- 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 garnet' to test." echo "Run 'cabal run' to test."

View File

@ -1,30 +0,0 @@
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.

View File

@ -1,32 +0,0 @@
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

View File

@ -1,3 +1,5 @@
#![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) {
@ -21,7 +23,6 @@ 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 },