From fda7977b1157902d0ff769964a2bee2f6e35c215 Mon Sep 17 00:00:00 2001 From: GuillaumeGen Date: Tue, 6 Dec 2022 16:21:06 +0100 Subject: [PATCH 01/41] Building the most strightforward tests with GHC Bindist compiled with Hadrian --- WORKSPACE | 15 + examples/split.patch | 2 +- haskell/c2hs.bzl | 1 + haskell/ghc.BUILD.tpl | 21 + haskell/ghc_bindist_hadrian.bzl | 439 ++++++++++++++++++ haskell/private/actions/process_hsc_file.bzl | 1 + haskell/private/packages.bzl | 2 +- haskell/private/runghc.bzl | 2 +- haskell/repl.bzl | 6 +- haskell/toolchain.bzl | 112 ++++- .../haskell_module/attr_merging/Plugin.hs | 1 + 11 files changed, 594 insertions(+), 8 deletions(-) create mode 100644 haskell/ghc_bindist_hadrian.bzl diff --git a/WORKSPACE b/WORKSPACE index 35cf2a413..86f4d75a9 100755 --- a/WORKSPACE +++ b/WORKSPACE @@ -86,6 +86,21 @@ load("@rules_haskell_npm//:repositories.bzl", "npm_repositories") npm_repositories() +load( + "@rules_haskell//haskell:ghc_bindist_hadrian.bzl", + "haskell_register_ghc_bindists_hadrian", +) + +haskell_register_ghc_bindists_hadrian( + url = "file:///home/guillaume/ExternalPrograms/ghc/_build/bindist/ghc-9.2.5-x86_64-unknown-linux.tar.xz", + sha256 = "e27724de38998dd6c3fb46ac5df4cf6818d779c1b749ea1afcd0b64e55b8217e", + strip_prefix = "ghc-9.2.5-x86_64-unknown-linux", + version = "9.2.5", + target = "x86_64-unknown-linux", + cabalopts = test_cabalopts, + ghcopts = test_ghcopts, +) + register_toolchains( "//tests:protobuf-toolchain", "//tests:protobuf-toolchain-osx_arm64", diff --git a/examples/split.patch b/examples/split.patch index c8ae893f7..3e887871a 100644 --- a/examples/split.patch +++ b/examples/split.patch @@ -7,7 +7,7 @@ index a60b284..1941c2f 100644 Library ghc-options: -Wall - build-depends: base <4.12 -+ build-depends: base <5 ++ build-depends: base <6 exposed-modules: Data.List.Split, Data.List.Split.Internals default-language: Haskell2010 Hs-source-dirs: src diff --git a/haskell/c2hs.bzl b/haskell/c2hs.bzl index 424a70122..c33de11f2 100644 --- a/haskell/c2hs.bzl +++ b/haskell/c2hs.bzl @@ -80,6 +80,7 @@ def _c2hs_library_impl(ctx): depset(cc.files), depset(hs.toolchain.bindir), depset(hs.toolchain.libdir), + depset(hs.toolchain.includedir), set.to_depset(version_macro_headers), inputs, ]), diff --git a/haskell/ghc.BUILD.tpl b/haskell/ghc.BUILD.tpl index 7af10a66e..76cc502e4 100644 --- a/haskell/ghc.BUILD.tpl +++ b/haskell/ghc.BUILD.tpl @@ -12,6 +12,10 @@ load( "haskell_import", "haskell_toolchain", ) +load( + "@rules_haskell//haskell:ghc_bindist_hadrian.bzl", + "copy_filegroups_to_this_package", +) package(default_visibility = ["//visibility:public"]) @@ -24,6 +28,11 @@ filegroup( srcs = glob(["bin/*"]), ) +filegroup( + name = "include", + srcs = glob(["include/**"]), +) + filegroup( name = "lib", srcs = glob(["lib/**"]), @@ -34,6 +43,18 @@ filegroup( srcs = glob(["%{docdir}/**"]), ) +# Since Bazel regular rules generate files in the "execroots" and GHC requires some files to be next to each other, +# one has to move all the files coming from the GHC bindist tarball to an execroot. +# These copied versions of the files are the 'generated_*_filegroup' targets. + +%{generated_bin_filegroup} + +%{generated_lib_filegroup} + +%{generated_include_filegroup} + +%{generated_docdir_filegroup} + # Expose embedded MinGW toolchain when on Windows. filegroup( diff --git a/haskell/ghc_bindist_hadrian.bzl b/haskell/ghc_bindist_hadrian.bzl new file mode 100644 index 000000000..dc7916406 --- /dev/null +++ b/haskell/ghc_bindist_hadrian.bzl @@ -0,0 +1,439 @@ +"""Workspace rules (GHC binary distributions)""" + +load("@bazel_tools//tools/cpp:lib_cc_configure.bzl", "get_cpu_value") +load("@rules_sh//sh:posix.bzl", "sh_posix_configure") +load( + ":private/pkgdb_to_bzl.bzl", + "pkgdb_to_bzl", +) +load(":private/versions.bzl", "check_bazel_version") +load( + ":private/workspace_utils.bzl", + "define_rule", + "find_python", + "resolve_labels", +) + +# A rule to copy a filegroup to the current execroot. +# This rule is generic and should probably be moved in its own file. +# Borrowed from https://github.com/lewish/asciiflow/blob/master/copy_files.bzl + +def _copy_filegroup_impl(ctx): + all_input_files = depset(ctx.files.srcs).to_list() + + all_outputs = [] + for f in all_input_files: + output_path = f.short_path + out = ctx.actions.declare_file(output_path) + all_outputs.append(out) + ctx.actions.run_shell( + outputs=[out], + inputs=depset([f]), + arguments=[f.path, out.path], + command="mkdir -p $(dirname $2) && cp $1 $2") + + return [ + DefaultInfo( + files=depset(all_outputs), + runfiles=ctx.runfiles(files=all_outputs)) + ] + + +copy_filegroups_to_this_package = rule( + implementation=_copy_filegroup_impl, + attrs={ + "srcs": attr.label_list(), + }, +) + +# Targets are of the form x86_64-unknown-linux. +def _split_target(target): + arch, _, os = target.split("-") + return (arch, os) + +# Main function. +# It fills the template ghc.BUILD.tpl with the targets specific to the platform the build is done on. +def _ghc_bindist_hadrian_impl(ctx): + filepaths = resolve_labels(ctx, [ + "@rules_haskell//haskell:ghc.BUILD.tpl", + "@rules_haskell//haskell:private/pkgdb_to_bzl.py", + ]) + _, os = _split_target(ctx.attr.target) + unpack_dir = "" + + ctx.download_and_extract( + url = ctx.attr.url, + output = unpack_dir, + sha256 = ctx.attr.sha256, + type = "tar.xz", + stripPrefix = ctx.attr.strip_prefix, + ) + + bindir = "bin" + libdir = "lib" + docdir = "docs" + + # The bindist requires patching invalid haddock paths. See Makefile of GHC: + # https://gitlab.haskell.org/ghc/ghc/-/blob/ghc-9.2.3-release/hadrian/bindist/Makefile#L54-74 + result = ctx.execute(["bash", "-c", """\ +set -euo pipefail +find {lib}/package.conf.d -name "*.conf" -print0 | \\ + xargs -0 sed -i.bak 's|\\${{pkgroot}}/\\.\\./\\.\\.|${{pkgroot}}/..|' +find {lib}/package.conf.d -name "rts-*.conf" -print0 | \\ + xargs -0 sed -i.bak2 's|haddock-html:.*$|haddock-html:|' +""".format( + lib = libdir, + )]) + if result.return_code != 0: + fail(result.stderr) + + # Since Bazel regular rules generate files in the "execroots" and GHC requires some files to be next to eachothers, + # one has to move all the files coming from the GHC bindist tarball (which is unpacked by a repository rule) to an execroot. + # These copied versions of the files are the 'generated_*_filegroup' targets. + + + generated_bin_filegroup = define_rule( + "copy_filegroups_to_this_package", + name = "generated_bin_filegroup", + srcs = [":bin"], + ) + + generated_lib_filegroup = define_rule( + "copy_filegroups_to_this_package", + name = "generated_lib_filegroup", + srcs = [":lib"], + ) + + generated_docdir_filegroup = define_rule( + "copy_filegroups_to_this_package", + name = "generated_docdir_filegroup", + srcs = [":{}".format(docdir)], + ) + + generated_include_filegroup = define_rule( + "copy_filegroups_to_this_package", + name = "generated_include_filegroup", + srcs = [":{}".format(docdir)], + ) + + toolchain_libraries = pkgdb_to_bzl(ctx, filepaths, libdir)["file_content"] + locale = ctx.attr.locale or ("en_US.UTF-8" if os == "darwin" else "C.UTF-8") + toolchain = define_rule( + "haskell_toolchain", + name = "toolchain-impl", + tools = [":generated_bin_filegroup"], + tools_path = repr(bindir), + libraries = "toolchain_libraries", + # See Note [GHC toolchain files] + libdir = [":generated_lib_filegroup"], + docdir = [":generated_docdir_filegroup"], + includedir = [":generated_include_filegroup"], + libdir_path = repr(libdir), + docdir_path = repr(docdir), + version = repr(ctx.attr.version), + static_runtime = os == "windows", + fully_static_link = False, # XXX not yet supported for bindists. + ghcopts = ctx.attr.ghcopts, + haddock_flags = ctx.attr.haddock_flags, + repl_ghci_args = ctx.attr.repl_ghci_args, + cabalopts = ctx.attr.cabalopts, + locale = repr(locale), + hadrian_bindist = True, + ) + ctx.template( + "BUILD", + filepaths["@rules_haskell//haskell:ghc.BUILD.tpl"], + substitutions = { + "%{toolchain_libraries}": toolchain_libraries, + "%{toolchain}": toolchain, + "%{docdir}": docdir, + "%{generated_bin_filegroup}": generated_bin_filegroup, + "%{generated_lib_filegroup}": generated_lib_filegroup, + "%{generated_docdir_filegroup}": generated_docdir_filegroup, + "%{generated_include_filegroup}": generated_include_filegroup, + }, + executable = False, + ) + +_ghc_bindist_hadrian = repository_rule( + _ghc_bindist_hadrian_impl, + local = False, + attrs = { + "url": attr.string(), + "sha256": attr.string(), + "strip_prefix": attr.string(), + "version": attr.string( + doc = "The binary distribution's GHC version", + ), + "target": attr.string(mandatory = True), + "ghcopts": attr.string_list(), + "haddock_flags": attr.string_list(), + "repl_ghci_args": attr.string_list(), + "cabalopts": attr.string_list(), + "patches": attr.label_list( + default = [], + doc = + "A list of files that are to be applied as patches afer " + + "extracting the archive.", + ), + "patch_tool": attr.string( + default = "patch", + doc = "The patch(1) utility to use.", + ), + "patch_args": attr.string_list( + default = ["-p0"], + doc = "The arguments given to the patch tool", + ), + "patch_cmds": attr.string_list( + default = [], + doc = "Sequence of commands to be applied after patches are applied.", + ), + "locale": attr.string( + mandatory = False, + ), + "_relpath_script": attr.label( + allow_single_file = True, + default = Label("@rules_haskell//haskell:assets/relpath.sh"), + ), + }, +) + +def _ghc_bindist_hadrian_toolchain_impl(ctx): + arch, os = _split_target(ctx.attr.target) + os_constraint = { + "darwin": "osx", + "linux": "linux", + "windows": "windows", + }.get(os) + cpu_constraint = { + "amd64": "x86_64", + "arm64": "arm64", + "x86_64": "x86_64", + }.get(arch) + exec_constraints = [ + "@platforms//os:{}".format(os_constraint), + "@platforms//cpu:{}".format(cpu_constraint), + ] + target_constraints = exec_constraints + ctx.file( + "BUILD", + executable = False, + content = """ +toolchain( + name = "toolchain", + toolchain_type = "@rules_haskell//haskell:toolchain", + toolchain = "@{bindist_name}//:toolchain-impl", + exec_compatible_with = {exec_constraints}, + target_compatible_with = {target_constraints}, +) + """.format( + bindist_name = ctx.attr.bindist_name, + exec_constraints = exec_constraints, + target_constraints = target_constraints, + ), + ) + +_ghc_bindist_hadrian_toolchain = repository_rule( + _ghc_bindist_hadrian_toolchain_impl, + local = False, + attrs = { + "bindist_name": attr.string(), + "target": attr.string(), + }, +) + +def ghc_bindist_hadrian( + name, + url, + sha256, + strip_prefix, + version, + target, + ghcopts = None, + haddock_flags = None, + repl_ghci_args = None, + cabalopts = None, + locale = None): + + bindist_name = name + toolchain_name = "{}-toolchain".format(name) + + # We want the toolchain definition to be tucked away in a separate + # repository, that way `bazel build //...` will not match it (and + # e.g. build the Windows toolchain even on Linux). At the same + # time, we don't want the definition in the bindist repository, + # because then we need to download the bindist first before we can + # see the toolchain definition. The solution is to add the + # toolchain definition in its own special repository. + _ghc_bindist_hadrian( + name = bindist_name, + url = url, + sha256 = sha256, + strip_prefix = strip_prefix, + version = version, + ghcopts = ghcopts, + haddock_flags = haddock_flags, + repl_ghci_args = repl_ghci_args, + cabalopts = cabalopts, + target = target, + locale = locale, + ) + _ghc_bindist_hadrian_toolchain( + name = toolchain_name, + bindist_name = bindist_name, + target = target, + ) + native.register_toolchains("@{}//:toolchain".format(toolchain_name)) + +def haskell_register_ghc_bindists_hadrian( + url, + sha256, + strip_prefix, + version, + target, + ghcopts = None, + haddock_flags = None, + repl_ghci_args = None, + cabalopts = None, + locale = None): + ghc_bindist_hadrian( + name = "rules_haskell_ghc_{}".format(target), + url = url, + sha256 = sha256, + strip_prefix = strip_prefix, + target = target, + version = version, + ghcopts = ghcopts, + haddock_flags = haddock_flags, + repl_ghci_args = repl_ghci_args, + cabalopts = cabalopts, + locale = locale, + ) + local_sh_posix_repo_name = "rules_haskell_sh_posix_local" + if local_sh_posix_repo_name not in native.existing_rules(): + sh_posix_configure(name = local_sh_posix_repo_name) + local_python_repo_name = "rules_haskell_python_local" + if local_python_repo_name not in native.existing_rules(): + _configure_python3_toolchain(name = local_python_repo_name) + +def _configure_python3_toolchain_impl(repository_ctx): + cpu = get_cpu_value(repository_ctx) + python3_path = find_python(repository_ctx) + if check_bazel_version("4.2.0")[0]: + stub_shebang = """stub_shebang = "#!{python3_path}",""".format( + python3_path = python3_path, + ) + else: + stub_shebang = "" + repository_ctx.file("BUILD.bazel", executable = False, content = """ +load( + "@bazel_tools//tools/python:toolchain.bzl", + "py_runtime_pair", +) +py_runtime( + name = "python3_runtime", + interpreter_path = "{python3}", + python_version = "PY3", + {stub_shebang} +) +py_runtime_pair( + name = "py_runtime_pair", + py3_runtime = ":python3_runtime", +) +toolchain( + name = "toolchain", + toolchain = ":py_runtime_pair", + toolchain_type = "@bazel_tools//tools/python:toolchain_type", + exec_compatible_with = [ + "@platforms//cpu:x86_64", + "@platforms//os:{os}", + ], + target_compatible_with = [ + "@platforms//cpu:x86_64", + "@platforms//os:{os}", + ], +) +""".format( + python3 = python3_path, + os = { + "darwin": "osx", + "x64_windows": "windows", + }.get(cpu, "linux"), + stub_shebang = stub_shebang, + )) + +_config_python3_toolchain = repository_rule( + _configure_python3_toolchain_impl, + configure = True, + environ = ["PATH"], +) + +def _configure_python3_toolchain(name): + """Autoconfigure python3 toolchain for GHC bindist + `rules_haskell` requires Python 3 to build Haskell targets. Under Nix we + use `rules_nixpkgs`'s `nixpkgs_python_configure` repository rule to use a + nixpkgs provisioned Python toolchain. However, outside of Nix we have to + rely on whatever Python toolchain is installed on the system. + Bazel provides `@bazel_tools//tools/python:autodetecting_toolchain` for + this purpose. However, in its current form, that toolchain does not + support Python toolchains installed outside of standard system paths + such as `/usr/bin:/bin:/usr/sbin`. The reason is that the toolchain does + not look for a Python interpreter in a repository rule. Instead it uses + wrapper scripts that look for a Python interpreter in `$PATH` within the + sandboxed build actions. + On MacOS, which, at the time of writing, only includes Python 2.7, users + will want to install Python 3 in a non-system path, e.g. via homebrew or + py_env. The auto detecting toolchain will not find this interpreter and + builds will fail with the following error: + ``` + Error occurred while attempting to use the default Python toolchain (@rules_python//python:autodetecting_toolchain). + According to '/usr/bin/python -V', version is 'Python 2.7.10', but we need version 3. PATH is: + /usr/bin:/bin:/usr/sbin + Please ensure an interpreter with version 3 is available on this platform as 'python3' or 'python', or else register an appropriate Python toolchain as per the documentation for py_runtime_pair (https://github.com/bazelbuild/rules_python/blob/master/docs/python.md#py_runtime_pair). + Note that prior to Bazel 0.27, there was no check to ensure that the interpreter's version matched the version declared by the target (#4815). If your build worked prior to Bazel 0.27, and you're sure your targets do not require Python 3, you can opt out of this version check by using the non-strict autodetecting toolchain instead of the standard autodetecting toolchain. This can be done by passing the flag `--extra_toolchains=@rules_python//python:autodetecting_toolchain_nonstrict` on the command line or adding it to your bazelrc. + ``` + This function defines a custom auto detcting Python toolchain that looks for + a Python 3 interpreter within a repository rule, so that Bazel's sandboxing + does not restrict the visible installation paths. It then registers an + appropriate Python toolchain, so that build actions themselves can still be + sandboxed. + """ + _config_python3_toolchain(name = name) + native.register_toolchains("@{}//:toolchain".format(name)) + +# Note [GHC toolchain files] +# ~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# The GHC distribution includes various files that may be required during +# compilation, or may be referenced by template Haskell code. These files +# need to be tracked by Bazel and declared as inputs to the relevant actions +# to ensure that they are present in the build sandbox. +# +# Surprisingly, builds succeed with little to none of such files declared as +# inputs. In case of the nixpkgs toolchain this is not surprising, as the +# files will all be present in the Nix store. However, files of the bindist +# toolchain are fully tracked by Bazel and one would expect errors due to +# missing files if they are not declared. +# +# The first instance of such an error occurred with the GHC bindist on +# BazelCI [1] and shortly after on the GitHub actions CI pipeline. However, +# only the `lib/settings` file was reported missing. In that instance it was +# sufficient to track `lib/settings` as an explicit build input to avoid this +# error. +# +# However, the issue re-appeared on the Bazel@HEAD CI pipeline [2]. It turns +# out that the failing builds were referencing the `lib/settings` file in a +# different sandbox working directory. I.e. build actions were leaking absolute +# paths to the sandbox working directory in build artifacts. In this case the +# `ghc-paths` package was the root of the issue. It uses a custom Cabal setup +# that hard codes the path to the GHC installation. In the GHC bindist case +# this path lies within the sandbox working directory and may no longer be +# valid in later build actions or at runtime. +# +# To avoid this type of issue we provide a Bazel compatible replacement of the +# `ghc-paths` package in `//tools/ghc-paths`. Refer to +# `//tools/ghc-paths:README.md` and [3] for further information. +# +# [1]: https://github.com/tweag/rules_haskell/issues/1470 +# [2]: https://github.com/tweag/rules_haskell/issues/1495 +# [3]: https://github.com/tweag/rules_haskell/pull/1508 diff --git a/haskell/private/actions/process_hsc_file.bzl b/haskell/private/actions/process_hsc_file.bzl index a5eaf5d3f..6a3232c28 100644 --- a/haskell/private/actions/process_hsc_file.bzl +++ b/haskell/private/actions/process_hsc_file.bzl @@ -68,6 +68,7 @@ def process_hsc_file(hs, cc, hsc_flags, hsc_inputs, hsc_file): depset(cc.files), depset(hsc_inputs), depset(hs.toolchain.bindir), + depset(hs.toolchain.includedir), ]), input_manifests = cc.manifests, outputs = [hs_out], diff --git a/haskell/private/packages.bzl b/haskell/private/packages.bzl index b479db754..79731967d 100644 --- a/haskell/private/packages.bzl +++ b/haskell/private/packages.bzl @@ -153,7 +153,7 @@ def ghc_pkg_recache(hs, posix, conf_file): # Make the call to ghc-pkg and use the package configuration file hs.actions.run( - inputs = depset(direct = [conf_file]), + inputs = depset(direct = [conf_file] + hs.toolchain.libdir), outputs = [cache_file], mnemonic = "HaskellRegisterPackage", progress_message = "HaskellRegisterPackage {}".format(conf_file.short_path), diff --git a/haskell/private/runghc.bzl b/haskell/private/runghc.bzl index 37e87fb39..c1470893a 100644 --- a/haskell/private/runghc.bzl +++ b/haskell/private/runghc.bzl @@ -17,7 +17,7 @@ def _runghc_wrapper_impl(ctx): hs_toolchain = ctx.toolchains["@rules_haskell//haskell:toolchain"] f = hs_toolchain.tools.runghc - runghc_runfile_path = paths.join(f.owner.workspace_name, f.owner.package, f.owner.name) + runghc_runfile_path = paths.join(f.owner.workspace_name, f.owner.package, hs_toolchain.tools_path, "runghc") runghc_wrapper_file = ctx.actions.declare_file(ctx.label.name) ctx.actions.write( output = runghc_wrapper_file, diff --git a/haskell/repl.bzl b/haskell/repl.bzl index 98b348d2e..a98224885 100644 --- a/haskell/repl.bzl +++ b/haskell/repl.bzl @@ -488,9 +488,9 @@ def _haskell_repl_impl(ctx): is_executable = True, substitutions = { "%{ENV}": render_env(env), - "%{TOOL}": hs.tools.ghci.path, + "%{TOOL}": hs.tools.ghc.path, "%{OUTPUT}": paths.dirname(output.path), - "%{ARGS}": "(" + " ".join( + "%{ARGS}": "--interactive (" + " ".join( args + [ shell.quote(a) for a in quote_args @@ -502,7 +502,7 @@ def _haskell_repl_impl(ctx): runfiles = [ ctx.runfiles( files = [ - hs.tools.ghci, + hs.tools.ghc, ghci_repl_script, ], transitive_files = inputs, diff --git a/haskell/toolchain.bzl b/haskell/toolchain.bzl index 69dee76e7..677fcf8d9 100644 --- a/haskell/toolchain.bzl +++ b/haskell/toolchain.bzl @@ -20,13 +20,14 @@ load(":private/actions/package.bzl", "package") load(":cc.bzl", "ghc_cc_program_args") load(":private/validate_attrs.bzl", "check_deprecated_attribute_usage") load(":private/context.bzl", "append_to_path") +load(":private/path_utils.bzl", "truly_relativize") load( "//haskell/asterius:asterius_config.bzl", "ASTERIUS_BINARIES", "asterius_tools_config", ) -_GHC_BINARIES = ["ghc", "ghc-pkg", "hsc2hs", "haddock", "ghci", "runghc", "hpc"] +_GHC_BINARIES = ["ghc", "ghc-pkg", "hsc2hs", "haddock", "runghc", "hpc"] def _run_ghc( hs, @@ -287,11 +288,13 @@ def _haskell_toolchain_impl(ctx): platform_common.ToolchainInfo( name = ctx.label.name, tools = struct(**tools_struct_args), + tools_path = ctx.attr.tools_path, bindir = ctx.files.tools, - libdir = libdir, + libdir = libdir + [ctx.file.settings] if ctx.attr.settings else libdir, libdir_path = libdir_path, docdir = docdir, docdir_path = docdir_path, + includedir = ctx.files.includedir, ghcopts = ctx.attr.ghcopts, repl_ghci_args = ctx.attr.repl_ghci_args, haddock_flags = ctx.attr.haddock_flags, @@ -336,6 +339,10 @@ common_attrs = { "tools": attr.label_list( mandatory = True, ), + "tools_path": attr.string( + doc = "The path to the bin/ folder containing the binaries (`ghc`, `haddock`...) ran by bazel rules. Do not specify this for a globally installed GHC distribution, e.g. a Nix provided one.", + mandatory = False, + ), "libraries": attr.label_list( mandatory = True, ), @@ -351,6 +358,10 @@ common_attrs = { "docdir_path": attr.string( doc = "The absolute path to GHC's docdir. C.f. `GHC.Paths.docdir` from `ghc-paths`. Specify this if `docdir` is left empty. One of `docdir` or `docdir_path` is required.", ), + "includedir": attr.label_list( + doc = "The files contained in the GHC include/ folder that Bazel should track. Do not specify this for a globally installed GHC distribution, e.g. a Nix provided one.", + mandatory = False, + ), "ghcopts": attr.string_list(), "repl_ghci_args": attr.string_list(), "haddock_flags": attr.string_list(), @@ -376,6 +387,11 @@ common_attrs = { allow_single_file = True, ), "asterius_binaries": attr.label(), + "settings": attr.label( + default = None, + allow_single_file = True, + doc = "The lib/settings file for Hadrian bindist.", + ), "_cc_wrapper": attr.label( cfg = "exec", default = Label("@rules_haskell//haskell:cc_wrapper"), @@ -423,6 +439,79 @@ _haskell_toolchain = rule( ), ) +def _hadrian_bindist_settings_impl(ctx): + cc = find_cc_toolchain(ctx) + posix = ctx.toolchains["@rules_sh//sh/posix:toolchain_type"] + settings_file = ctx.actions.declare_file("lib/settings") + outdir = paths.normalize(paths.join( + ctx.bin_dir.path, + ctx.label.workspace_root, + paths.dirname(ctx.build_file_path), + )) + workspace_root = ctx.label.workspace_root + args = ctx.actions.args() + ctx.actions.run_shell( + outputs = [settings_file], + inputs = [ctx.file.configure, ctx.file.makefile] + ctx.files.srcs, + mnemonic = "GhcMakeSettings", + command = """\ +pwd +ls -R +export AR={ar} +export CC={cc} +export LD={ld} +export NM={nm} +export OBJCOPY={objcopy} +export OBJDUMP={objdump} +export CPP={cpp} +export STRIP={strip} +export PATH="${{LD%/*}}:$PATH" +mkdir -p {outdir}/mk +cp {workspace_root}/mk/project.mk {outdir}/mk +(cd {outdir} && {configure} && {make} -f {makefile} lib/settings) +""".format( + outdir = outdir, + workspace_root = workspace_root, + configure = truly_relativize(ctx.file.configure.path, outdir), + ar = cc.ar_executable, + cc = cc.compiler_executable, + ld = cc.ld_executable, + nm = cc.nm_executable, + objcopy = cc.objcopy_executable, + objdump = cc.objdump_executable, + cpp = cc.preprocessor_executable, + strip = cc.strip_executable, + srcs = [src.path for src in ctx.files.srcs], + make = posix.commands["make"], + makefile = truly_relativize(ctx.file.makefile.path, outdir), + ), + progress_message = "Generating GHC settings file", + ) + + return [DefaultInfo( + files = depset(direct = [settings_file]), + )] + +_hadrian_bindist_settings = rule( + _hadrian_bindist_settings_impl, + attrs = { + "configure": attr.label( + allow_single_file = True, + ), + "makefile": attr.label( + allow_single_file = True, + ), + "srcs": attr.label_list( + allow_files = True, + ), + }, + fragments = ["cpp"], + toolchains = [ + "@rules_cc//cc:toolchain_type", + "@rules_sh//sh/posix:toolchain_type", + ], +) + def haskell_toolchain( name, version, @@ -431,6 +520,7 @@ def haskell_toolchain( tools, libraries, asterius_binaries = None, + hadrian_bindist = False, compiler_flags = [], ghcopts = [], repl_ghci_args = [], @@ -481,6 +571,7 @@ def haskell_toolchain( libraries: The set of libraries that come with GHC. Requires haskell_import targets. asterius_binaries: An optional filegroup containing asterius binaries. If present the toolchain will target WebAssembly and only use binaries from `tools` if needed to complete the toolchain. + hadrian_bindist: Whether the toolchain is based on a Hadrian generated GHC bindist. ghcopts: A collection of flags that will be passed to GHC on every invocation. compiler_flags: DEPRECATED. Use new name ghcopts. repl_ghci_args: A collection of flags that will be passed to GHCI on repl invocation. It extends the `ghcopts` collection.\\ @@ -504,6 +595,22 @@ def haskell_toolchain( new_attr_value = ghcopts, ) + if hadrian_bindist: + _hadrian_bindist_settings( + name = "settings", + configure = "configure", + makefile = "Makefile", + srcs = [ + "config.guess", + "config.sub", + "install-sh", + "mk/config.mk.in", + "mk/install.mk.in", + "mk/project.mk", + ], + ) + + toolchain_rule = _ahc_haskell_toolchain if asterius_binaries else _haskell_toolchain toolchain_rule( name = name, @@ -513,6 +620,7 @@ def haskell_toolchain( tools = tools, libraries = libraries, ghcopts = ghcopts, + settings = ":settings" if hadrian_bindist else None, repl_ghci_args = corrected_ghci_args, haddock_flags = haddock_flags, cabalopts = cabalopts, diff --git a/rules_haskell_tests/tests/haskell_module/attr_merging/Plugin.hs b/rules_haskell_tests/tests/haskell_module/attr_merging/Plugin.hs index f86eefa09..b63f1690e 100644 --- a/rules_haskell_tests/tests/haskell_module/attr_merging/Plugin.hs +++ b/rules_haskell_tests/tests/haskell_module/attr_merging/Plugin.hs @@ -11,6 +11,7 @@ import GHC.Core.Opt.Monad import GHC.Plugins import GHC.Types.Literal import GHC.Unit.Module.ModGuts +-- import GHC.Plugins TODO import System.Process (readProcess) From 6adb278dddbf852153e1a67ba96c8d677a970060 Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Fri, 28 Apr 2023 11:24:34 +0200 Subject: [PATCH 02/41] Use GHC 9.6.1 which is built with Hadrian --- WORKSPACE | 11 +++++++---- haskell/toolchain.bzl | 5 +++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/WORKSPACE b/WORKSPACE index 86f4d75a9..4086a96c9 100755 --- a/WORKSPACE +++ b/WORKSPACE @@ -91,11 +91,14 @@ load( "haskell_register_ghc_bindists_hadrian", ) +load( + "non_module_deps_1.bzl", "test_cabalopts", "test_ghcopts" +) haskell_register_ghc_bindists_hadrian( - url = "file:///home/guillaume/ExternalPrograms/ghc/_build/bindist/ghc-9.2.5-x86_64-unknown-linux.tar.xz", - sha256 = "e27724de38998dd6c3fb46ac5df4cf6818d779c1b749ea1afcd0b64e55b8217e", - strip_prefix = "ghc-9.2.5-x86_64-unknown-linux", - version = "9.2.5", + url = "https://downloads.haskell.org/~ghc/9.6.1/ghc-9.6.1-x86_64-deb9-linux.tar.xz", + sha256 = "3c727e93a82ff039fbedd6645518859849130a0fc93b7181cd69a41800aa639c", + strip_prefix = "ghc-9.6.1-x86_64-unknown-linux", + version = "9.6.1", target = "x86_64-unknown-linux", cabalopts = test_cabalopts, ghcopts = test_ghcopts, diff --git a/haskell/toolchain.bzl b/haskell/toolchain.bzl index 677fcf8d9..fd52c4c70 100644 --- a/haskell/toolchain.bzl +++ b/haskell/toolchain.bzl @@ -504,6 +504,11 @@ _hadrian_bindist_settings = rule( "srcs": attr.label_list( allow_files = True, ), + "_cc_toolchain": attr.label( + default = Label( + "@rules_cc//cc:current_cc_toolchain", + ), + ), }, fragments = ["cpp"], toolchains = [ From 988e08c7e0e2ec44354547a75239ca428374410c Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Mon, 15 May 2023 08:48:21 +0200 Subject: [PATCH 03/41] examples: Update primitive to version 0.8.0 This is needed to support GHC >= 9.4 --- examples/primitive/BUILD.bazel | 6 + examples/primitive/Control/Monad/Primitive.hs | 120 ++-- examples/primitive/Data/Primitive.hs | 54 +- examples/primitive/Data/Primitive/Array.hs | 383 ++++++------ .../primitive/Data/Primitive/ByteArray.hs | 551 ++++++++++-------- .../Data/Primitive/Internal/Operations.hs | 51 +- examples/primitive/Data/Primitive/MVar.hs | 94 ++- examples/primitive/Data/Primitive/MachDeps.hs | 7 +- examples/primitive/Data/Primitive/MutVar.hs | 45 +- .../primitive/Data/Primitive/PrimArray.hs | 404 +++++++++---- examples/primitive/Data/Primitive/PrimVar.hs | 167 ++++++ examples/primitive/Data/Primitive/Ptr.hs | 39 +- .../primitive/Data/Primitive/SmallArray.hs | 438 ++++++-------- examples/primitive/Data/Primitive/Types.hs | 228 +++++--- examples/primitive/cbits/primitive-memops.c | 11 +- examples/primitive/cbits/primitive-memops.h | 30 +- examples/primitive/changelog.md | 101 ++++ examples/primitive/test/main.hs | 104 ++-- 18 files changed, 1743 insertions(+), 1090 deletions(-) create mode 100644 examples/primitive/Data/Primitive/PrimVar.hs diff --git a/examples/primitive/BUILD.bazel b/examples/primitive/BUILD.bazel index 7e2cd7f3d..4ccdaff1e 100644 --- a/examples/primitive/BUILD.bazel +++ b/examples/primitive/BUILD.bazel @@ -7,10 +7,14 @@ load( haskell_toolchain_library(name = "base") +haskell_toolchain_library(name = "deepseq") + haskell_toolchain_library(name = "ghc-prim") haskell_toolchain_library(name = "rts") +haskell_toolchain_library(name = "template-haskell") + cc_library( name = "memops", srcs = ["cbits/primitive-memops.c"], @@ -28,8 +32,10 @@ haskell_library( visibility = ["//visibility:public"], deps = [ ":base", + ":deepseq", ":ghc-prim", ":memops", + ":template-haskell", "//transformers", ], ) diff --git a/examples/primitive/Control/Monad/Primitive.hs b/examples/primitive/Control/Monad/Primitive.hs index 567c129fc..dea2681df 100644 --- a/examples/primitive/Control/Monad/Primitive.hs +++ b/examples/primitive/Control/Monad/Primitive.hs @@ -1,6 +1,7 @@ {-# LANGUAGE CPP, MagicHash, UnboxedTuples, TypeFamilies #-} {-# LANGUAGE FlexibleContexts, FlexibleInstances, UndecidableInstances #-} {-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE MultiParamTypeClasses #-} {-# OPTIONS_GHC -fno-warn-deprecations #-} -- | @@ -11,52 +12,48 @@ -- Maintainer : Roman Leshchinskiy -- Portability : non-portable -- --- Primitive state-transformer monads --- +-- Primitive state-transformer monads. module Control.Monad.Primitive ( PrimMonad(..), RealWorld, primitive_, PrimBase(..), + MonadPrim, + MonadPrimBase, liftPrim, primToPrim, primToIO, primToST, ioToPrim, stToPrim, unsafePrimToPrim, unsafePrimToIO, unsafePrimToST, unsafeIOToPrim, unsafeSTToPrim, unsafeInlinePrim, unsafeInlineIO, unsafeInlineST, - touch, evalPrim, unsafeInterleave, unsafeDupableInterleave, noDuplicate + touch, keepAlive, evalPrim, unsafeInterleave, unsafeDupableInterleave, noDuplicate ) where -import GHC.Exts ( State#, RealWorld, noDuplicate#, touch# ) -import GHC.Base ( realWorld# ) -#if MIN_VERSION_base(4,4,0) -import GHC.Base ( seq# ) -#else -import Control.Exception (evaluate) +import GHC.Exts ( State#, RealWorld, noDuplicate#, touch# +#if defined(HAVE_KEEPALIVE) + , keepAlive# #endif -#if MIN_VERSION_base(4,2,0) + , unsafeCoerce#, realWorld#, seq# ) import GHC.IO ( IO(..) ) -#else -import GHC.IOBase ( IO(..) ) -#endif -import GHC.Exts ( unsafeCoerce# ) import GHC.ST ( ST(..) ) -import Control.Monad.Trans.Class (lift) -#if !MIN_VERSION_base(4,8,0) -import Data.Monoid (Monoid) +#if __GLASGOW_HASKELL__ >= 802 +import qualified Control.Monad.ST.Lazy as L #endif +import Control.Monad.Trans.Class (lift) + import Control.Monad.Trans.Cont ( ContT ) import Control.Monad.Trans.Identity ( IdentityT (IdentityT) ) -import Control.Monad.Trans.List ( ListT ) import Control.Monad.Trans.Maybe ( MaybeT ) -import Control.Monad.Trans.Error ( ErrorT, Error) import Control.Monad.Trans.Reader ( ReaderT ) import Control.Monad.Trans.State ( StateT ) import Control.Monad.Trans.Writer ( WriterT ) import Control.Monad.Trans.RWS ( RWST ) -#if MIN_VERSION_transformers(0,4,0) -import Control.Monad.Trans.Except ( ExceptT ) +#if !MIN_VERSION_transformers(0,6,0) +import Control.Monad.Trans.List ( ListT ) +import Control.Monad.Trans.Error ( ErrorT, Error) #endif +import Control.Monad.Trans.Except ( ExceptT ) + #if MIN_VERSION_transformers(0,5,3) import Control.Monad.Trans.Accum ( AccumT ) import Control.Monad.Trans.Select ( SelectT ) @@ -71,12 +68,12 @@ import qualified Control.Monad.Trans.RWS.Strict as Strict ( RWST ) import qualified Control.Monad.Trans.State.Strict as Strict ( StateT ) import qualified Control.Monad.Trans.Writer.Strict as Strict ( WriterT ) --- | Class of monads which can perform primitive state-transformer actions +-- | Class of monads which can perform primitive state-transformer actions. class Monad m => PrimMonad m where - -- | State token type + -- | State token type. type PrimState m - -- | Execute a primitive operation + -- | Execute a primitive operation. primitive :: (State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a -- | Class of primitive monads for state-transformer actions. @@ -87,10 +84,10 @@ class Monad m => PrimMonad m where -- -- @since 0.6.0.0 class PrimMonad m => PrimBase m where - -- | Expose the internal structure of the monad + -- | Expose the internal structure of the monad. internal :: m a -> State# (PrimState m) -> (# State# (PrimState m), a #) --- | Execute a primitive operation with no result +-- | Execute a primitive operation with no result. primitive_ :: PrimMonad m => (State# (PrimState m) -> State# (PrimState m)) -> m () {-# INLINE primitive_ #-} @@ -102,6 +99,7 @@ instance PrimMonad IO where type PrimState IO = RealWorld primitive = IO {-# INLINE primitive #-} + instance PrimBase IO where internal (IO p) = p {-# INLINE internal #-} @@ -122,18 +120,20 @@ instance PrimBase m => PrimBase (IdentityT m) where internal (IdentityT m) = internal m {-# INLINE internal #-} +#if !MIN_VERSION_transformers(0,6,0) instance PrimMonad m => PrimMonad (ListT m) where type PrimState (ListT m) = PrimState m primitive = lift . primitive {-# INLINE primitive #-} -instance PrimMonad m => PrimMonad (MaybeT m) where - type PrimState (MaybeT m) = PrimState m +instance (Error e, PrimMonad m) => PrimMonad (ErrorT e m) where + type PrimState (ErrorT e m) = PrimState m primitive = lift . primitive {-# INLINE primitive #-} +#endif -instance (Error e, PrimMonad m) => PrimMonad (ErrorT e m) where - type PrimState (ErrorT e m) = PrimState m +instance PrimMonad m => PrimMonad (MaybeT m) where + type PrimState (MaybeT m) = PrimState m primitive = lift . primitive {-# INLINE primitive #-} @@ -171,24 +171,20 @@ instance (Monoid w, PrimMonad m) => PrimMonad (CPS.RWST r w s m) where {-# INLINE primitive #-} #endif -#if MIN_VERSION_transformers(0,4,0) instance PrimMonad m => PrimMonad (ExceptT e m) where type PrimState (ExceptT e m) = PrimState m primitive = lift . primitive {-# INLINE primitive #-} -#endif #if MIN_VERSION_transformers(0,5,3) -- | @since 0.6.3.0 instance ( Monoid w , PrimMonad m -# if !(MIN_VERSION_base(4,8,0)) - , Functor m -# endif ) => PrimMonad (AccumT w m) where type PrimState (AccumT w m) = PrimState m primitive = lift . primitive {-# INLINE primitive #-} + instance PrimMonad m => PrimMonad (SelectT r m) where type PrimState (SelectT r m) = PrimState m primitive = lift . primitive @@ -214,10 +210,40 @@ instance PrimMonad (ST s) where type PrimState (ST s) = s primitive = ST {-# INLINE primitive #-} + instance PrimBase (ST s) where internal (ST p) = p {-# INLINE internal #-} +-- see https://gitlab.haskell.org/ghc/ghc/commit/2f5cb3d44d05e581b75a47fec222577dfa7a533e +-- for why we only support an instance for ghc >= 8.2 +#if __GLASGOW_HASKELL__ >= 802 +-- @since 0.7.1.0 +instance PrimMonad (L.ST s) where + type PrimState (L.ST s) = s + primitive = L.strictToLazyST . primitive + {-# INLINE primitive #-} + +-- @since 0.7.1.0 +instance PrimBase (L.ST s) where + internal = internal . L.lazyToStrictST + {-# INLINE internal #-} +#endif + +-- | 'PrimMonad''s state token type can be annoying to handle +-- in constraints. This typeclass lets users (visually) notice +-- 'PrimState' equality constraints less, by witnessing that +-- @s ~ 'PrimState' m@. +class (PrimMonad m, s ~ PrimState m) => MonadPrim s m +instance (PrimMonad m, s ~ PrimState m) => MonadPrim s m + +-- | 'PrimBase''s state token type can be annoying to handle +-- in constraints. This typeclass lets users (visually) notice +-- 'PrimState' equality constraints less, by witnessing that +-- @s ~ 'PrimState' m@. +class (PrimBase m, MonadPrim s m) => MonadPrimBase s m +instance (PrimBase m, MonadPrim s m) => MonadPrimBase s m + -- | Lifts a 'PrimBase' into another 'PrimMonad' with the same underlying state -- token type. liftPrim @@ -288,14 +314,23 @@ unsafeIOToPrim :: PrimMonad m => IO a -> m a {-# INLINE unsafeIOToPrim #-} unsafeIOToPrim = unsafePrimToPrim +-- | See 'unsafeInlineIO'. This function is not recommended for the same +-- reasons. unsafeInlinePrim :: PrimBase m => m a -> a {-# INLINE unsafeInlinePrim #-} unsafeInlinePrim m = unsafeInlineIO (unsafePrimToIO m) +-- | Generally, do not use this function. It is the same as +-- @accursedUnutterablePerformIO@ from @bytestring@ and is well behaved under +-- narrow conditions. See the documentation of that function to get an idea +-- of when this is sound. In most cases @GHC.IO.Unsafe.unsafeDupablePerformIO@ +-- should be preferred. unsafeInlineIO :: IO a -> a {-# INLINE unsafeInlineIO #-} unsafeInlineIO m = case internal m realWorld# of (# _, r #) -> r +-- | See 'unsafeInlineIO'. This function is not recommended for the same +-- reasons. Prefer @runST@ when @s@ is free. unsafeInlineST :: ST s a -> a {-# INLINE unsafeInlineST #-} unsafeInlineST = unsafeInlinePrim @@ -305,17 +340,20 @@ touch :: PrimMonad m => a -> m () touch x = unsafePrimToPrim $ (primitive (\s -> case touch# x s of { s' -> (# s', () #) }) :: IO ()) +keepAlive :: PrimBase m => a -> (a -> m r) -> m r +#if defined(HAVE_KEEPALIVE) +{-# INLINE keepAlive #-} +keepAlive x k = unsafeIOToPrim $ primitive $ \s0 -> keepAlive# x s0 $ internal $ unsafePrimToIO $ k x +#else +{-# NOINLINE keepAlive #-} +keepAlive x k = k x <* touch x +#endif + -- | Create an action to force a value; generalizes 'Control.Exception.evaluate' -- -- @since 0.6.2.0 evalPrim :: forall a m . PrimMonad m => a -> m a -#if MIN_VERSION_base(4,4,0) evalPrim a = primitive (\s -> seq# a s) -#else --- This may or may not work so well, but there's probably nothing better to do. -{-# NOINLINE evalPrim #-} -evalPrim a = unsafePrimToPrim (evaluate a :: IO a) -#endif noDuplicate :: PrimMonad m => m () #if __GLASGOW_HASKELL__ >= 802 diff --git a/examples/primitive/Data/Primitive.hs b/examples/primitive/Data/Primitive.hs index 0db9bd831..57dfc612e 100644 --- a/examples/primitive/Data/Primitive.hs +++ b/examples/primitive/Data/Primitive.hs @@ -1,5 +1,6 @@ {-# LANGUAGE MagicHash #-} {-# OPTIONS_GHC -fno-warn-duplicate-exports #-} + -- | -- Module : Data.Primitive -- Copyright : (c) Roman Leshchinskiy 2009-2012 @@ -8,19 +9,19 @@ -- Maintainer : Roman Leshchinskiy -- Portability : non-portable -- --- Reexports all primitive operations --- -module Data.Primitive ( - -- * Re-exports - module Data.Primitive.Types - ,module Data.Primitive.Array - ,module Data.Primitive.ByteArray - ,module Data.Primitive.SmallArray - ,module Data.Primitive.PrimArray - ,module Data.Primitive.MutVar +-- Reexports all primitive operations. + +module Data.Primitive + ( -- * Re-exports + module Data.Primitive.Types + , module Data.Primitive.Array + , module Data.Primitive.ByteArray + , module Data.Primitive.SmallArray + , module Data.Primitive.PrimArray + , module Data.Primitive.MutVar -- * Naming Conventions -- $namingConventions -) where + ) where import Data.Primitive.Types import Data.Primitive.Array @@ -39,21 +40,22 @@ of the variants of the array indexing function are: > indexPrimArray :: Prim a => PrimArray a -> Int -> a In a few places, where the language sounds more natural, the array type -is instead used as a prefix. For example, @Data.Primitive.SmallArray@ -exports @smallArrayFromList@, which would sound unnatural if it used +is instead used as a prefix. For example, "Data.Primitive.SmallArray" +exports 'smallArrayFromList', which would sound unnatural if it used @SmallArray@ as a suffix instead. -This library provides several functions traversing, building, and filtering +This library provides several functions for traversing, building, and filtering arrays. These functions are suffixed with an additional character to -indicate their the nature of their effectfulness: +indicate the nature of their effectfulness: * No suffix: A non-effectful pass over the array. -* @-A@ suffix: An effectful pass over the array, where the effect is 'Applicative'. -* @-P@ suffix: An effectful pass over the array, where the effect is 'PrimMonad'. +* @A@ suffix: An effectful pass over the array, where the effect is 'Applicative'. +* @P@ suffix: An effectful pass over the array, where the effect is 'Control.Monad.Primitive.PrimMonad'. Additionally, an apostrophe can be used to indicate strictness in the elements. -The variants with an apostrophe are used in @Data.Primitive.Array@ but not -in @Data.Primitive.PrimArray@ since the array type it provides is always strict in the element. +The variants with an apostrophe are used in "Data.Primitive.Array" but not +in "Data.Primitive.PrimArray" since the array type it provides is always strict in the element anyway. + For example, there are three variants of the function that filters elements from a primitive array. @@ -61,17 +63,17 @@ from a primitive array. > filterPrimArrayA :: (Prim a, Applicative f) => (a -> f Bool) -> PrimArray a -> f (PrimArray a) > filterPrimArrayP :: (Prim a, PrimMonad m) => (a -> m Bool) -> PrimArray a -> m (PrimArray a) -As long as the effectful context is a monad that is sufficiently affine -the behaviors of the 'Applicative' and 'PrimMonad' variants produce the same results -and differ only in their strictness. Monads that are sufficiently affine -include: +As long as the effectful context is a monad that is sufficiently affine, +the behaviors of the 'Applicative' and 'Control.Monad.Primitive.PrimMonad' +variants produce the same results and differ only in their strictness. +Monads that are sufficiently affine include: * 'IO' and 'ST' * Any combination of 'MaybeT', 'ExceptT', 'StateT' and 'Writer' on top of another sufficiently affine monad. -* Any Monad which does not include backtracking or other mechanism where an effect can -happen more than once is an Affine Monad in the sense we care about. ContT, LogicT, ListT are all -examples of search/control monads which are NOT affine: they can run a sub computation more than once. +* Any Monad which does not include backtracking or other mechanisms where an effect can + happen more than once is an affine Monad in the sense we care about. @ContT@, @LogicT@, @ListT@ are all + examples of search/control monads which are NOT affine: they can run a sub computation more than once. There is one situation where the names deviate from effectful suffix convention described above. Throughout the haskell ecosystem, the 'Applicative' variant of diff --git a/examples/primitive/Data/Primitive/Array.hs b/examples/primitive/Data/Primitive/Array.hs index a70720fb6..a2cc26b6e 100644 --- a/examples/primitive/Data/Primitive/Array.hs +++ b/examples/primitive/Data/Primitive/Array.hs @@ -1,6 +1,7 @@ {-# LANGUAGE CPP, MagicHash, UnboxedTuples, DeriveDataTypeable, BangPatterns #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE TemplateHaskellQuotes #-} -- | -- Module : Data.Primitive.Array @@ -11,64 +12,47 @@ -- Portability : non-portable -- -- Primitive arrays of boxed values. --- module Data.Primitive.Array ( Array(..), MutableArray(..), newArray, readArray, writeArray, indexArray, indexArrayM, indexArray##, - freezeArray, thawArray, runArray, + freezeArray, thawArray, runArray, createArray, unsafeFreezeArray, unsafeThawArray, sameMutableArray, copyArray, copyMutableArray, cloneArray, cloneMutableArray, sizeofArray, sizeofMutableArray, + emptyArray, fromListN, fromList, + arrayFromListN, arrayFromList, mapArray', traverseArrayP ) where +import Control.DeepSeq import Control.Monad.Primitive -import GHC.Base ( Int(..) ) -import GHC.Exts -#if (MIN_VERSION_base(4,7,0)) - hiding (toList) -#endif +import GHC.Exts hiding (toList) import qualified GHC.Exts as Exts -#if (MIN_VERSION_base(4,7,0)) -import GHC.Exts (fromListN, fromList) -#endif import Data.Typeable ( Typeable ) import Data.Data - (Data(..), DataType, mkDataType, Constr, mkConstr, Fixity(..), constrIndex) -import Data.Primitive.Internal.Compat ( isTrue#, mkNoRepType ) + (Data(..), DataType, mkDataType, mkNoRepType, Constr, mkConstr, Fixity(..), constrIndex) -import Control.Monad.ST(ST,runST) +import Control.Monad.ST (ST, runST) import Control.Applicative -import Control.Monad (MonadPlus(..), when) +import Control.Monad (MonadPlus(..), when, liftM2) import qualified Control.Monad.Fail as Fail import Control.Monad.Fix -#if MIN_VERSION_base(4,4,0) +import qualified Data.Foldable as Foldable import Control.Monad.Zip -#endif import Data.Foldable (Foldable(..), toList) -#if !(MIN_VERSION_base(4,8,0)) -import Data.Traversable (Traversable(..)) -import Data.Monoid -#endif -#if MIN_VERSION_base(4,9,0) import qualified GHC.ST as GHCST import qualified Data.Foldable as F import Data.Semigroup -#endif -#if MIN_VERSION_base(4,8,0) import Data.Functor.Identity -#endif -#if MIN_VERSION_base(4,10,0) -import GHC.Exts (runRW#) -#elif MIN_VERSION_base(4,9,0) +#if !MIN_VERSION_base(4,10,0) import GHC.Base (runRW#) #endif @@ -77,31 +61,71 @@ import Text.ParserCombinators.ReadPrec (ReadPrec) import qualified Text.ParserCombinators.ReadPrec as RdPrc import Text.ParserCombinators.ReadP -#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,4,0) -import Data.Functor.Classes (Eq1(..),Ord1(..),Show1(..),Read1(..)) -#endif -import Control.Monad (liftM2) +import Data.Functor.Classes (Eq1(..), Ord1(..), Show1(..), Read1(..)) +import Language.Haskell.TH.Syntax (Lift (..)) --- | Boxed arrays +-- | Boxed arrays. data Array a = Array { array# :: Array# a } deriving ( Typeable ) +instance Lift a => Lift (Array a) where +#if MIN_VERSION_template_haskell(2,16,0) + liftTyped ary = case lst of + [] -> [|| Array (emptyArray# (##)) ||] + [x] -> [|| pure $! x ||] + x : xs -> [|| unsafeArrayFromListN' len x xs ||] +#else + lift ary = case lst of + [] -> [| Array (emptyArray# (##)) |] + [x] -> [| pure $! x |] + x : xs -> [| unsafeArrayFromListN' len x xs |] +#endif + where + len = length ary + lst = toList ary + +-- | Strictly create an array from a nonempty list (represented as +-- a first element and a list of the rest) of a known length. If the length +-- of the list does not match the given length, this makes demons fly +-- out of your nose. We use it in the 'Lift' instance. If you edit the +-- splice and break it, you get to keep both pieces. +unsafeArrayFromListN' :: Int -> a -> [a] -> Array a +unsafeArrayFromListN' n y ys = + createArray n y $ \ma -> + let go !_ix [] = return () + go !ix (!x : xs) = do + writeArray ma ix x + go (ix+1) xs + in go 1 ys + +#if MIN_VERSION_deepseq(1,4,3) +instance NFData1 Array where + liftRnf r = Foldable.foldl' (\_ -> r) () +#endif + +instance NFData a => NFData (Array a) where + rnf = Foldable.foldl' (\_ -> rnf) () + -- | Mutable boxed arrays associated with a primitive state token. data MutableArray s a = MutableArray { marray# :: MutableArray# s a } deriving ( Typeable ) +-- | The number of elements in an immutable array. sizeofArray :: Array a -> Int sizeofArray a = I# (sizeofArray# (array# a)) {-# INLINE sizeofArray #-} +-- | The number of elements in a mutable array. sizeofMutableArray :: MutableArray s a -> Int sizeofMutableArray a = I# (sizeofMutableArray# (marray# a)) {-# INLINE sizeofMutableArray #-} -- | Create a new mutable array of the specified size and initialise all -- elements with the given value. +-- +-- /Note:/ this function does not check if the input is non-negative. newArray :: PrimMonad m => Int -> a -> m (MutableArray (PrimState m) a) {-# INLINE newArray #-} newArray (I# n#) x = primitive @@ -111,16 +135,22 @@ newArray (I# n#) x = primitive in (# s'# , ma #)) -- | Read a value from the array at the given index. +-- +-- /Note:/ this function does not do bounds checking. readArray :: PrimMonad m => MutableArray (PrimState m) a -> Int -> m a {-# INLINE readArray #-} readArray arr (I# i#) = primitive (readArray# (marray# arr) i#) -- | Write a value to the array at the given index. +-- +-- /Note:/ this function does not do bounds checking. writeArray :: PrimMonad m => MutableArray (PrimState m) a -> Int -> a -> m () {-# INLINE writeArray #-} writeArray arr (I# i#) x = primitive_ (writeArray# (marray# arr) i# x) -- | Read a value from the immutable array at the given index. +-- +-- /Note:/ this function does not do bounds checking. indexArray :: Array a -> Int -> a {-# INLINE indexArray #-} indexArray arr (I# i#) = case indexArray# (array# arr) i# of (# x #) -> x @@ -128,6 +158,8 @@ indexArray arr (I# i#) = case indexArray# (array# arr) i# of (# x #) -> x -- | Read a value from the immutable array at the given index, returning -- the result in an unboxed unary tuple. This is currently used to implement -- folds. +-- +-- /Note:/ this function does not do bounds checking. indexArray## :: Array a -> Int -> (# a #) indexArray## arr (I# i) = indexArray# (array# arr) i {-# INLINE indexArray## #-} @@ -141,7 +173,7 @@ indexArray## arr (I# i) = indexArray# (array# arr) i -- > writeArray marr i (indexArray arr i) ... -- > ... -- --- But since primitive arrays are lazy, the calls to 'indexArray' will not be +-- But since the arrays are lazy, the calls to 'indexArray' will not be -- evaluated. Rather, @marr@ will be filled with thunks each of which would -- retain a reference to @arr@. This is definitely not what we want! -- @@ -155,6 +187,7 @@ indexArray## arr (I# i) = indexArray# (array# arr) i -- Now, indexing is executed immediately although the returned element is -- still not evaluated. -- +-- /Note:/ this function does not do bounds checking. indexArrayM :: Monad m => Array a -> Int -> m a {-# INLINE indexArrayM #-} indexArrayM arr (I# i#) @@ -164,6 +197,9 @@ indexArrayM arr (I# i#) -- -- This operation makes a copy of the specified section, so it is safe to -- continue using the mutable array afterward. +-- +-- /Note:/ The provided array should contain the full subrange +-- specified by the two Ints, but this is not checked. freezeArray :: PrimMonad m => MutableArray (PrimState m) a -- ^ source @@ -189,6 +225,9 @@ unsafeFreezeArray arr -- -- This operation makes a copy of the specified slice, so it is safe to use the -- immutable array afterward. +-- +-- /Note:/ The provided array should contain the full subrange +-- specified by the two Ints, but this is not checked. thawArray :: PrimMonad m => Array a -- ^ source @@ -217,6 +256,8 @@ sameMutableArray arr brr = isTrue# (sameMutableArray# (marray# arr) (marray# brr)) -- | Copy a slice of an immutable array to a mutable array. +-- +-- /Note:/ this function does not do bounds or overlap checking. copyArray :: PrimMonad m => MutableArray (PrimState m) a -- ^ destination array -> Int -- ^ offset into destination array @@ -225,26 +266,12 @@ copyArray :: PrimMonad m -> Int -- ^ number of elements to copy -> m () {-# INLINE copyArray #-} -#if __GLASGOW_HASKELL__ > 706 --- NOTE: copyArray# and copyMutableArray# are slightly broken in GHC 7.6.* and earlier copyArray (MutableArray dst#) (I# doff#) (Array src#) (I# soff#) (I# len#) = primitive_ (copyArray# src# soff# dst# doff# len#) -#else -copyArray !dst !doff !src !soff !len = go 0 - where - go i | i < len = do - x <- indexArrayM src (soff+i) - writeArray dst (doff+i) x - go (i+1) - | otherwise = return () -#endif --- | Copy a slice of a mutable array to another array. The two arrays must --- not be the same when using this library with GHC versions 7.6 and older. --- In GHC 7.8 and newer, overlapping arrays will behave correctly. +-- | Copy a slice of a mutable array to another array. The two arrays may overlap. -- --- Note: The order of arguments is different from that of 'copyMutableArray#'. The primop --- has the source first while this wrapper has the destination first. +-- /Note:/ this function does not do bounds or overlap checking. copyMutableArray :: PrimMonad m => MutableArray (PrimState m) a -- ^ destination array -> Int -- ^ offset into destination array @@ -253,23 +280,14 @@ copyMutableArray :: PrimMonad m -> Int -- ^ number of elements to copy -> m () {-# INLINE copyMutableArray #-} -#if __GLASGOW_HASKELL__ > 706 --- NOTE: copyArray# and copyMutableArray# are slightly broken in GHC 7.6.* and earlier copyMutableArray (MutableArray dst#) (I# doff#) (MutableArray src#) (I# soff#) (I# len#) = primitive_ (copyMutableArray# src# soff# dst# doff# len#) -#else -copyMutableArray !dst !doff !src !soff !len = go 0 - where - go i | i < len = do - x <- readArray src (soff+i) - writeArray dst (doff+i) x - go (i+1) - | otherwise = return () -#endif --- | Return a newly allocated Array with the specified subrange of the --- provided Array. The provided Array should contain the full subrange +-- | Return a newly allocated 'Array' with the specified subrange of the +-- provided 'Array'. +-- +-- /Note:/ The provided array should contain the full subrange -- specified by the two Ints, but this is not checked. cloneArray :: Array a -- ^ source array -> Int -- ^ offset into destination array @@ -279,9 +297,12 @@ cloneArray :: Array a -- ^ source array cloneArray (Array arr#) (I# off#) (I# len#) = case cloneArray# arr# off# len# of arr'# -> Array arr'# --- | Return a newly allocated MutableArray. with the specified subrange of --- the provided MutableArray. The provided MutableArray should contain the +-- | Return a newly allocated 'MutableArray'. with the specified subrange of +-- the provided 'MutableArray'. The provided 'MutableArray' should contain the -- full subrange specified by the two Ints, but this is not checked. +-- +-- /Note:/ The provided array should contain the full subrange +-- specified by the two Ints, but this is not checked. cloneMutableArray :: PrimMonad m => MutableArray (PrimState m) a -- ^ source array -> Int -- ^ offset into destination array @@ -292,48 +313,15 @@ cloneMutableArray (MutableArray arr#) (I# off#) (I# len#) = primitive (\s# -> case cloneMutableArray# arr# off# len# s# of (# s'#, arr'# #) -> (# s'#, MutableArray arr'# #)) +-- | The empty 'Array'. emptyArray :: Array a emptyArray = runST $ newArray 0 (die "emptyArray" "impossible") >>= unsafeFreezeArray {-# NOINLINE emptyArray #-} -#if !MIN_VERSION_base(4,9,0) -createArray - :: Int - -> a - -> (forall s. MutableArray s a -> ST s ()) - -> Array a -createArray 0 _ _ = emptyArray -createArray n x f = runArray $ do - mary <- newArray n x - f mary - pure mary - -runArray - :: (forall s. ST s (MutableArray s a)) - -> Array a -runArray m = runST $ m >>= unsafeFreezeArray - -#else /* Below, runRW# is available. */ - --- This low-level business is designed to work with GHC's worker-wrapper --- transformation. A lot of the time, we don't actually need an Array --- constructor. By putting it on the outside, and being careful about --- how we special-case the empty array, we can make GHC smarter about this. --- The only downside is that separately created 0-length arrays won't share --- their Array constructors, although they'll share their underlying --- Array#s. -createArray - :: Int - -> a - -> (forall s. MutableArray s a -> ST s ()) - -> Array a -createArray 0 _ _ = Array (emptyArray# (# #)) -createArray n x f = runArray $ do - mary <- newArray n x - f mary - pure mary - +-- | Execute the monadic action and freeze the resulting array. +-- +-- > runArray m = runST $ m >>= unsafeFreezeArray runArray :: (forall s. ST s (MutableArray s a)) -> Array a @@ -352,7 +340,33 @@ unST (GHCST.ST f) = f emptyArray# :: (# #) -> Array# a emptyArray# _ = case emptyArray of Array ar -> ar {-# NOINLINE emptyArray# #-} -#endif + +-- | Create an array of the given size with a default value, +-- apply the monadic function and freeze the result. If the +-- size is 0, return 'emptyArray' (rather than a new copy thereof). +-- +-- > createArray 0 _ _ = emptyArray +-- > createArray n x f = runArray $ do +-- > mary <- newArray n x +-- > f mary +-- > pure mary +createArray + :: Int + -> a + -> (forall s. MutableArray s a -> ST s ()) + -> Array a +-- This low-level business is designed to work with GHC's worker-wrapper +-- transformation. A lot of the time, we don't actually need an Array +-- constructor. By putting it on the outside, and being careful about +-- how we special-case the empty array, we can make GHC smarter about this. +-- The only downside is that separately created 0-length arrays won't share +-- their Array constructors, although they'll share their underlying +-- Array#s. +createArray 0 _ _ = Array (emptyArray# (# #)) +createArray n x f = runArray $ do + mary <- newArray n x + f mary + pure mary die :: String -> String -> a @@ -363,20 +377,14 @@ arrayLiftEq p a1 a2 = sizeofArray a1 == sizeofArray a2 && loop (sizeofArray a1 - where loop i | i < 0 = True | (# x1 #) <- indexArray## a1 i , (# x2 #) <- indexArray## a2 i - , otherwise = p x1 x2 && loop (i-1) + , otherwise = p x1 x2 && loop (i - 1) instance Eq a => Eq (Array a) where a1 == a2 = arrayLiftEq (==) a1 a2 -#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,4,0) -- | @since 0.6.4.0 instance Eq1 Array where -#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,5,0) liftEq = arrayLiftEq -#else - eq1 = arrayLiftEq (==) -#endif -#endif instance Eq (MutableArray s a) where ma1 == ma2 = isTrue# (sameMutableArray# (marray# ma1) (marray# ma2)) @@ -389,22 +397,16 @@ arrayLiftCompare elemCompare a1 a2 = loop 0 | i < mn , (# x1 #) <- indexArray## a1 i , (# x2 #) <- indexArray## a2 i - = elemCompare x1 x2 `mappend` loop (i+1) + = elemCompare x1 x2 `mappend` loop (i + 1) | otherwise = compare (sizeofArray a1) (sizeofArray a2) -- | Lexicographic ordering. Subject to change between major versions. instance Ord a => Ord (Array a) where compare a1 a2 = arrayLiftCompare compare a1 a2 -#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,4,0) -- | @since 0.6.4.0 instance Ord1 Array where -#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,5,0) liftCompare = arrayLiftCompare -#else - compare1 = arrayLiftCompare compare -#endif -#endif instance Foldable Array where -- Note: we perform the array lookups eagerly so we won't @@ -416,7 +418,7 @@ instance Foldable Array where go i | i == sz = z | (# x #) <- indexArray## ary i - = f x (go (i+1)) + = f x (go (i + 1)) in go 0 {-# INLINE foldr #-} foldl f = \z !ary -> @@ -424,7 +426,7 @@ instance Foldable Array where go i | i < 0 = z | (# x #) <- indexArray## ary i - = f (go (i-1)) x + = f (go (i - 1)) x in go (sizeofArray ary - 1) {-# INLINE foldl #-} foldr1 f = \ !ary -> @@ -433,7 +435,7 @@ instance Foldable Array where go i = case indexArray## ary i of (# x #) | i == sz -> x - | otherwise -> f x (go (i+1)) + | otherwise -> f x (go (i + 1)) in if sz < 0 then die "foldr1" "empty array" else go 0 @@ -449,13 +451,12 @@ instance Foldable Array where then die "foldl1" "empty array" else go sz {-# INLINE foldl1 #-} -#if MIN_VERSION_base(4,6,0) foldr' f = \z !ary -> let go i !acc | i == -1 = acc | (# x #) <- indexArray## ary i - = go (i-1) (f x acc) + = go (i - 1) (f x acc) in go (sizeofArray ary - 1) z {-# INLINE foldr' #-} foldl' f = \z !ary -> @@ -464,11 +465,9 @@ instance Foldable Array where go i !acc | i == sz = acc | (# x #) <- indexArray## ary i - = go (i+1) (f acc x) + = go (i + 1) (f acc x) in go 0 z {-# INLINE foldl' #-} -#endif -#if MIN_VERSION_base(4,8,0) null a = sizeofArray a == 0 {-# INLINE null #-} length = sizeofArray @@ -481,7 +480,7 @@ instance Foldable Array where go i !e | i == sz = e | (# x #) <- indexArray## ary i - = go (i+1) (max e x) + = go (i + 1) (max e x) {-# INLINE maximum #-} minimum ary | sz == 0 = die "minimum" "empty array" | (# frst #) <- indexArray## ary 0 @@ -490,15 +489,14 @@ instance Foldable Array where go i !e | i == sz = e | (# x #) <- indexArray## ary i - = go (i+1) (min e x) + = go (i + 1) (min e x) {-# INLINE minimum #-} sum = foldl' (+) 0 {-# INLINE sum #-} product = foldl' (*) 1 {-# INLINE product #-} -#endif -newtype STA a = STA {_runSTA :: forall s. MutableArray# s a -> ST s (Array a)} +newtype STA a = STA { _runSTA :: forall s. MutableArray# s a -> ST s (Array a) } runSTA :: Int -> STA a -> Array a runSTA !sz = \ (STA m) -> runST $ newArray_ sz >>= \ ar -> m (marray# ar) @@ -530,8 +528,8 @@ traverseArray f = \ !ary -> writeArray (MutableArray mary) i b >> m mary) (f x) (go (i + 1)) in if len == 0 - then pure emptyArray - else runSTA len <$> go 0 + then pure emptyArray + else runSTA len <$> go 0 {-# INLINE [1] traverseArray #-} {-# RULES @@ -539,19 +537,15 @@ traverseArray f = \ !ary -> traverseArrayP f "traverse/IO" forall (f :: a -> IO b). traverseArray f = traverseArrayP f - #-} -#if MIN_VERSION_base(4,8,0) -{-# RULES "traverse/Id" forall (f :: a -> Identity b). traverseArray f = (coerce :: (Array a -> Array (Identity b)) -> Array a -> Identity (Array b)) (fmap f) #-} -#endif -- | This is the fastest, most straightforward way to traverse -- an array, but it only works correctly with a sufficiently -- "affine" 'PrimMonad' instance. In particular, it must only produce --- *one* result array. 'Control.Monad.Trans.List.ListT'-transformed +-- /one/ result array. 'Control.Monad.Trans.List.ListT'-transformed -- monads, for example, will not work right at all. traverseArrayP :: PrimMonad m @@ -586,10 +580,12 @@ mapArray' f a = -- We use indexArrayM here so that we will perform the -- indexing eagerly even if f is lazy. let !y = f x - writeArray mb i y >> go (i+1) + writeArray mb i y >> go (i + 1) in go 0 {-# INLINE mapArray' #-} +-- | Create an array from a list of a known length. If the length +-- of the list does not match the given length, this throws an exception. arrayFromListN :: Int -> [a] -> Array a arrayFromListN n l = createArray n (die "fromListN" "uninitialized element") $ \sma -> @@ -603,22 +599,15 @@ arrayFromListN n l = else die "fromListN" "list length greater than specified size" in go 0 l +-- | Create an array from a list. arrayFromList :: [a] -> Array a arrayFromList l = arrayFromListN (length l) l -#if MIN_VERSION_base(4,7,0) instance Exts.IsList (Array a) where type Item (Array a) = a fromListN = arrayFromListN fromList = arrayFromList toList = toList -#else -fromListN :: Int -> [a] -> Array a -fromListN = arrayFromListN - -fromList :: [a] -> Array a -fromList = arrayFromList -#endif instance Functor Array where fmap f a = @@ -627,47 +616,48 @@ instance Functor Array where = return () | otherwise = do x <- indexArrayM a i - writeArray mb i (f x) >> go (i+1) + writeArray mb i (f x) >> go (i + 1) in go 0 -#if MIN_VERSION_base(4,8,0) e <$ a = createArray (sizeofArray a) e (\ !_ -> pure ()) -#endif instance Applicative Array where pure x = runArray $ newArray 1 x - ab <*> a = createArray (szab*sza) (die "<*>" "impossible") $ \mb -> + + ab <*> a = createArray (szab * sza) (die "<*>" "impossible") $ \mb -> let go1 i = when (i < szab) $ do f <- indexArrayM ab i - go2 (i*sza) f 0 - go1 (i+1) + go2 (i * sza) f 0 + go1 (i + 1) go2 off f j = when (j < sza) $ do x <- indexArrayM a j writeArray mb (off + j) (f x) go2 off f (j + 1) in go1 0 - where szab = sizeofArray ab ; sza = sizeofArray a - a *> b = createArray (sza*szb) (die "*>" "impossible") $ \mb -> - let go i | i < sza = copyArray mb (i * szb) b 0 szb + where szab = sizeofArray ab; sza = sizeofArray a + + a *> b = createArray (sza * szb) (die "*>" "impossible") $ \mb -> + let go i | i < sza = copyArray mb (i * szb) b 0 szb *> go (i + 1) | otherwise = return () - in go 0 - where sza = sizeofArray a ; szb = sizeofArray b - a <* b = createArray (sza*szb) (die "<*" "impossible") $ \ma -> - let fill off i e | i < szb = writeArray ma (off+i) e >> fill off (i+1) e + in go 0 + where sza = sizeofArray a; szb = sizeofArray b + + a <* b = createArray (sza * szb) (die "<*" "impossible") $ \ma -> + let fill off i e | i < szb = writeArray ma (off + i) e >> fill off (i + 1) e | otherwise = return () go i | i < sza = do x <- indexArrayM a i - fill (i*szb) 0 x >> go (i+1) + fill (i * szb) 0 x >> go (i + 1) | otherwise = return () - in go 0 - where sza = sizeofArray a ; szb = sizeofArray b + in go 0 + where sza = sizeofArray a; szb = sizeofArray b instance Alternative Array where empty = emptyArray a1 <|> a2 = createArray (sza1 + sza2) (die "<|>" "impossible") $ \ma -> copyArray ma 0 a1 0 sza1 >> copyArray ma sza1 a2 0 sza2 - where sza1 = sizeofArray a1 ; sza2 = sizeofArray a2 + where sza1 = sizeofArray a1; sza2 = sizeofArray a2 some a | sizeofArray a == 0 = emptyArray | otherwise = die "some" "infinite arrays are not well defined" many a | sizeofArray a == 0 = pure [] @@ -682,26 +672,26 @@ instance Monad Array where return = pure (>>) = (*>) - ary >>= f = collect 0 EmptyStack (la-1) + ary >>= f = collect 0 EmptyStack (la - 1) where - la = sizeofArray ary - collect sz stk i - | i < 0 = createArray sz (die ">>=" "impossible") $ fill 0 stk - | (# x #) <- indexArray## ary i - , let sb = f x - lsb = sizeofArray sb - -- If we don't perform this check, we could end up allocating - -- a stack full of empty arrays if someone is filtering most - -- things out. So we refrain from pushing empty arrays. - = if lsb == 0 - then collect sz stk (i - 1) - else collect (sz + lsb) (PushArray sb stk) (i-1) - - fill _ EmptyStack _ = return () - fill off (PushArray sb sbs) smb - | let lsb = sizeofArray sb - = copyArray smb off sb 0 (lsb) - *> fill (off + lsb) sbs smb + la = sizeofArray ary + collect sz stk i + | i < 0 = createArray sz (die ">>=" "impossible") $ fill 0 stk + | (# x #) <- indexArray## ary i + , let sb = f x + lsb = sizeofArray sb + -- If we don't perform this check, we could end up allocating + -- a stack full of empty arrays if someone is filtering most + -- things out. So we refrain from pushing empty arrays. + = if lsb == 0 + then collect sz stk (i - 1) + else collect (sz + lsb) (PushArray sb stk) (i - 1) + + fill _ EmptyStack _ = return () + fill off (PushArray sb sbs) smb + | let lsb = sizeofArray sb + = copyArray smb off sb 0 lsb + *> fill (off + lsb) sbs smb #if !(MIN_VERSION_base(4,13,0)) fail = Fail.fail @@ -721,13 +711,12 @@ zipW s f aa ab = createArray mn (die s "impossible") $ \mc -> x <- indexArrayM aa i y <- indexArrayM ab i writeArray mc i (f x y) - go (i+1) + go (i + 1) | otherwise = return () in go 0 where mn = sizeofArray aa `min` sizeofArray ab {-# INLINE zipW #-} -#if MIN_VERSION_base(4,4,0) instance MonadZip Array where mzip aa ab = zipW "mzip" (,) aa ab mzipWith f aa ab = zipW "mzipWith" f aa ab @@ -739,11 +728,10 @@ instance MonadZip Array where (a, b) <- indexArrayM aab i writeArray ma i a writeArray mb i b - go (i+1) + go (i + 1) go _ = return () go 0 (,) <$> unsafeFreezeArray ma <*> unsafeFreezeArray mb -#endif instance MonadFix Array where mfix f = createArray (sizeofArray (f err)) @@ -755,17 +743,26 @@ instance MonadFix Array where sz = sizeofArray (f err) err = error "mfix for Data.Primitive.Array applied to strict function." -#if MIN_VERSION_base(4,9,0) -- | @since 0.6.3.0 instance Semigroup (Array a) where (<>) = (<|>) sconcat = mconcat . F.toList -#endif + stimes n arr = case compare n 0 of + LT -> die "stimes" "negative multiplier" + EQ -> empty + GT -> createArray (n' * sizeofArray arr) (die "stimes" "impossible") $ \ma -> + let go i = if i < n' + then do + copyArray ma (i * sizeofArray arr) arr 0 (sizeofArray arr) + go (i + 1) + else return () + in go 0 + where n' = fromIntegral n :: Int instance Monoid (Array a) where mempty = empty #if !(MIN_VERSION_base(4,11,0)) - mappend = (<|>) + mappend = (<>) #endif mconcat l = createArray sz (die "mconcat" "impossible") $ \ma -> let go !_ [ ] = return () @@ -786,29 +783,19 @@ listLiftShowsPrec _ sl _ = sl instance Show a => Show (Array a) where showsPrec p a = arrayLiftShowsPrec showsPrec showList p a -#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,4,0) -- | @since 0.6.4.0 instance Show1 Array where -#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,5,0) liftShowsPrec = arrayLiftShowsPrec -#else - showsPrec1 = arrayLiftShowsPrec showsPrec showList -#endif -#endif instance Read a => Read (Array a) where readPrec = arrayLiftReadPrec readPrec readListPrec -#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,4,0) -- | @since 0.6.4.0 instance Read1 Array where #if MIN_VERSION_base(4,10,0) liftReadPrec = arrayLiftReadPrec -#elif MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,5,0) - liftReadsPrec = arrayLiftReadsPrec #else - readsPrec1 = arrayLiftReadsPrec readsPrec readList -#endif + liftReadsPrec = arrayLiftReadsPrec #endif -- We're really forgiving here. We accept diff --git a/examples/primitive/Data/Primitive/ByteArray.hs b/examples/primitive/Data/Primitive/ByteArray.hs index e99abe419..c019ad0a6 100644 --- a/examples/primitive/Data/Primitive/ByteArray.hs +++ b/examples/primitive/Data/Primitive/ByteArray.hs @@ -1,6 +1,8 @@ {-# LANGUAGE BangPatterns, CPP, MagicHash, UnboxedTuples, UnliftedFFITypes, DeriveDataTypeable #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE TemplateHaskellQuotes #-} -- | -- Module : Data.Primitive.ByteArray @@ -10,8 +12,11 @@ -- Maintainer : Roman Leshchinskiy -- Portability : non-portable -- --- Primitive operations on ByteArrays --- +-- Primitive operations on byte arrays. Most functions in this module include +-- an element type in their type signature and interpret the unit for offsets +-- and lengths as that element. A few functions (e.g. 'copyByteArray', +-- 'freezeByteArray') do not include an element type. Such functions +-- interpret offsets and lengths as units of 8-bit words. module Data.Primitive.ByteArray ( -- * Types @@ -20,26 +25,36 @@ module Data.Primitive.ByteArray ( -- * Allocation newByteArray, newPinnedByteArray, newAlignedPinnedByteArray, resizeMutableByteArray, + shrinkMutableByteArray, -- * Element access readByteArray, writeByteArray, indexByteArray, + -- * Char Element Access + -- $charElementAccess + readCharArray, writeCharArray, indexCharArray, -- * Constructing + emptyByteArray, byteArrayFromList, byteArrayFromListN, -- * Folding foldrByteArray, + -- * Comparing + compareByteArrays, + -- * Freezing and thawing + freezeByteArray, thawByteArray, runByteArray, unsafeFreezeByteArray, unsafeThawByteArray, -- * Block operations copyByteArray, copyMutableByteArray, -#if __GLASGOW_HASKELL__ >= 708 + copyByteArrayToPtr, copyMutableByteArrayToPtr, copyByteArrayToAddr, copyMutableByteArrayToAddr, -#endif + copyPtrToMutableByteArray, moveByteArray, setByteArray, fillByteArray, + cloneByteArray, cloneMutableByteArray, -- * Information sizeofByteArray, @@ -55,49 +70,26 @@ import Control.Monad.Primitive import Control.Monad.ST import Data.Primitive.Types -import Foreign.C.Types -import Data.Word ( Word8 ) -import GHC.Base ( Int(..) ) -#if __GLASGOW_HASKELL__ >= 708 -import qualified GHC.Exts as Exts ( IsList(..) ) -#endif -import GHC.Exts -#if __GLASGOW_HASKELL__ >= 706 - hiding (setByteArray#) -#endif - -import Data.Typeable ( Typeable ) -import Data.Data ( Data(..) ) -import Data.Primitive.Internal.Compat ( isTrue#, mkNoRepType ) -import Numeric - -#if MIN_VERSION_base(4,9,0) -import qualified Data.Semigroup as SG -import qualified Data.Foldable as F -#endif - -#if !(MIN_VERSION_base(4,8,0)) -import Data.Monoid (Monoid(..)) +#if MIN_VERSION_base(4,10,0) +import qualified GHC.ST as GHCST #endif +import Foreign.C.Types +import Data.Word ( Word8 ) #if __GLASGOW_HASKELL__ >= 802 -import GHC.Exts as Exts (isByteArrayPinned#,isMutableByteArrayPinned#) +import qualified GHC.Exts as Exts #endif +import GHC.Exts hiding (setByteArray#) -#if __GLASGOW_HASKELL__ >= 804 -import GHC.Exts (compareByteArrays#) -#else +#if __GLASGOW_HASKELL__ < 804 import System.IO.Unsafe (unsafeDupablePerformIO) #endif --- | Byte arrays -data ByteArray = ByteArray ByteArray# deriving ( Typeable ) - --- | Mutable byte arrays associated with a primitive state token -data MutableByteArray s = MutableByteArray (MutableByteArray# s) - deriving( Typeable ) +import Data.Array.Byte (ByteArray(..), MutableByteArray(..)) -- | Create a new mutable byte array of the specified size in bytes. +-- +-- /Note:/ this function does not check if the input is non-negative. newByteArray :: PrimMonad m => Int -> m (MutableByteArray (PrimState m)) {-# INLINE newByteArray #-} newByteArray (I# n#) @@ -106,6 +98,8 @@ newByteArray (I# n#) -- | Create a /pinned/ byte array of the specified size in bytes. The garbage -- collector is guaranteed not to move it. +-- +-- /Note:/ this function does not check if the input is non-negative. newPinnedByteArray :: PrimMonad m => Int -> m (MutableByteArray (PrimState m)) {-# INLINE newPinnedByteArray #-} newPinnedByteArray (I# n#) @@ -114,6 +108,8 @@ newPinnedByteArray (I# n#) -- | Create a /pinned/ byte array of the specified size in bytes and with the -- given alignment. The garbage collector is guaranteed not to move it. +-- +-- /Note:/ this function does not check if the input is non-negative. newAlignedPinnedByteArray :: PrimMonad m => Int -- ^ size @@ -161,16 +157,9 @@ resizeMutableByteArray :: PrimMonad m => MutableByteArray (PrimState m) -> Int -> m (MutableByteArray (PrimState m)) {-# INLINE resizeMutableByteArray #-} -#if __GLASGOW_HASKELL__ >= 710 resizeMutableByteArray (MutableByteArray arr#) (I# n#) = primitive (\s# -> case resizeMutableByteArray# arr# n# s# of (# s'#, arr'# #) -> (# s'#, MutableByteArray arr'# #)) -#else -resizeMutableByteArray arr n - = do arr' <- newByteArray n - copyMutableByteArray arr' 0 arr 0 (min (sizeofMutableByteArray arr) n) - return arr' -#endif -- | Get the size of a byte array in bytes. Unlike 'sizeofMutableByteArray', -- this function ensures sequencing in the presence of resizing. @@ -186,6 +175,48 @@ getSizeofMutableByteArray arr = return (sizeofMutableByteArray arr) #endif +-- | Create an immutable copy of a slice of a byte array. The offset and +-- length are given in bytes. +-- +-- This operation makes a copy of the specified section, so it is safe to +-- continue using the mutable array afterward. +-- +-- /Note:/ The provided array should contain the full subrange +-- specified by the two Ints, but this is not checked. +freezeByteArray + :: PrimMonad m + => MutableByteArray (PrimState m) -- ^ source + -> Int -- ^ offset in bytes + -> Int -- ^ length in bytes + -> m ByteArray +{-# INLINE freezeByteArray #-} +freezeByteArray !src !off !len = do + dst <- newByteArray len + copyMutableByteArray dst 0 src off len + unsafeFreezeByteArray dst + +-- | Create a mutable byte array from a slice of an immutable byte array. +-- The offset and length are given in bytes. +-- +-- This operation makes a copy of the specified slice, so it is safe to +-- use the immutable array afterward. +-- +-- /Note:/ The provided array should contain the full subrange +-- specified by the two Ints, but this is not checked. +-- +-- @since 0.7.2.0 +thawByteArray + :: PrimMonad m + => ByteArray -- ^ source + -> Int -- ^ offset in bytes + -> Int -- ^ length in bytes + -> m (MutableByteArray (PrimState m)) +{-# INLINE thawByteArray #-} +thawByteArray !src !off !len = do + dst <- newByteArray len + copyByteArray dst 0 src off len + return dst + -- | Convert a mutable byte array to an immutable one without copying. The -- array should not be modified after the conversion. unsafeFreezeByteArray @@ -217,21 +248,37 @@ sizeofMutableByteArray :: MutableByteArray s -> Int {-# INLINE sizeofMutableByteArray #-} sizeofMutableByteArray (MutableByteArray arr#) = I# (sizeofMutableByteArray# arr#) +-- | Shrink a mutable byte array. The new size is given in bytes. +-- It must be smaller than the old size. The array will be resized in place. +-- +-- @since 0.7.1.0 +shrinkMutableByteArray :: PrimMonad m + => MutableByteArray (PrimState m) + -> Int -- ^ new size + -> m () +{-# INLINE shrinkMutableByteArray #-} +shrinkMutableByteArray (MutableByteArray arr#) (I# n#) + = primitive_ (shrinkMutableByteArray# arr# n#) + #if __GLASGOW_HASKELL__ >= 802 -- | Check whether or not the byte array is pinned. Pinned byte arrays cannot --- be moved by the garbage collector. It is safe to use 'byteArrayContents' --- on such byte arrays. This function is only available when compiling with --- GHC 8.2 or newer. +-- be moved by the garbage collector. It is safe to use 'byteArrayContents' on +-- such byte arrays. +-- +-- Caution: This function is only available when compiling with GHC 8.2 or +-- newer. -- --- @since 0.6.4.0 +-- @since 0.6.4.0 isByteArrayPinned :: ByteArray -> Bool {-# INLINE isByteArrayPinned #-} isByteArrayPinned (ByteArray arr#) = isTrue# (Exts.isByteArrayPinned# arr#) --- | Check whether or not the mutable byte array is pinned. This function is --- only available when compiling with GHC 8.2 or newer. +-- | Check whether or not the mutable byte array is pinned. +-- +-- Caution: This function is only available when compiling with GHC 8.2 or +-- newer. -- --- @since 0.6.4.0 +-- @since 0.6.4.0 isMutableByteArrayPinned :: MutableByteArray s -> Bool {-# INLINE isMutableByteArrayPinned #-} isMutableByteArrayPinned (MutableByteArray marr#) = isTrue# (Exts.isMutableByteArrayPinned# marr#) @@ -239,12 +286,16 @@ isMutableByteArrayPinned (MutableByteArray marr#) = isTrue# (Exts.isMutableByteA -- | Read a primitive value from the byte array. The offset is given in -- elements of type @a@ rather than in bytes. +-- +-- /Note:/ this function does not do bounds checking. indexByteArray :: Prim a => ByteArray -> Int -> a {-# INLINE indexByteArray #-} indexByteArray (ByteArray arr#) (I# i#) = indexByteArray# arr# i# -- | Read a primitive value from the byte array. The offset is given in -- elements of type @a@ rather than in bytes. +-- +-- /Note:/ this function does not do bounds checking. readByteArray :: (Prim a, PrimMonad m) => MutableByteArray (PrimState m) -> Int -> m a {-# INLINE readByteArray #-} @@ -253,6 +304,8 @@ readByteArray (MutableByteArray arr#) (I# i#) -- | Write a primitive value to the byte array. The offset is given in -- elements of type @a@ rather than in bytes. +-- +-- /Note:/ this function does not do bounds checking. writeByteArray :: (Prim a, PrimMonad m) => MutableByteArray (PrimState m) -> Int -> a -> m () {-# INLINE writeByteArray #-} @@ -265,13 +318,18 @@ foldrByteArray :: forall a b. (Prim a) => (a -> b -> b) -> b -> ByteArray -> b foldrByteArray f z arr = go 0 where go i - | i < maxI = f (indexByteArray arr i) (go (i+1)) + | i < maxI = f (indexByteArray arr i) (go (i + 1)) | otherwise = z maxI = sizeofByteArray arr `quot` sizeOf (undefined :: a) +-- | Create a 'ByteArray' from a list. +-- +-- @byteArrayFromList xs = `byteArrayFromListN` (length xs) xs@ byteArrayFromList :: Prim a => [a] -> ByteArray byteArrayFromList xs = byteArrayFromListN (length xs) xs +-- | Create a 'ByteArray' from a list of a known length. If the length +-- of the list does not match the given length, this throws an exception. byteArrayFromListN :: Prim a => Int -> [a] -> ByteArray byteArrayFromListN n ys = runST $ do marr <- newByteArray (n * sizeOf (head ys)) @@ -290,40 +348,103 @@ unI# :: Int -> Int# unI# (I# n#) = n# -- | Copy a slice of an immutable byte array to a mutable byte array. +-- +-- /Note:/ this function does not do bounds or overlap checking. copyByteArray - :: PrimMonad m => MutableByteArray (PrimState m) - -- ^ destination array - -> Int -- ^ offset into destination array - -> ByteArray -- ^ source array - -> Int -- ^ offset into source array - -> Int -- ^ number of bytes to copy - -> m () + :: PrimMonad m + => MutableByteArray (PrimState m) -- ^ destination array + -> Int -- ^ offset into destination array + -> ByteArray -- ^ source array + -> Int -- ^ offset into source array + -> Int -- ^ number of bytes to copy + -> m () {-# INLINE copyByteArray #-} copyByteArray (MutableByteArray dst#) doff (ByteArray src#) soff sz = primitive_ (copyByteArray# src# (unI# soff) dst# (unI# doff) (unI# sz)) -- | Copy a slice of a mutable byte array into another array. The two slices -- may not overlap. +-- +-- /Note:/ this function does not do bounds or overlap checking. copyMutableByteArray - :: PrimMonad m => MutableByteArray (PrimState m) - -- ^ destination array - -> Int -- ^ offset into destination array - -> MutableByteArray (PrimState m) - -- ^ source array - -> Int -- ^ offset into source array - -> Int -- ^ number of bytes to copy - -> m () + :: PrimMonad m + => MutableByteArray (PrimState m) -- ^ destination array + -> Int -- ^ offset into destination array + -> MutableByteArray (PrimState m) -- ^ source array + -> Int -- ^ offset into source array + -> Int -- ^ number of bytes to copy + -> m () {-# INLINE copyMutableByteArray #-} copyMutableByteArray (MutableByteArray dst#) doff (MutableByteArray src#) soff sz = primitive_ (copyMutableByteArray# src# (unI# soff) dst# (unI# doff) (unI# sz)) -#if __GLASGOW_HASKELL__ >= 708 +-- | Copy a slice of a byte array to an unmanaged pointer address. These must not +-- overlap. The offset and length are given in elements, not in bytes. +-- +-- /Note:/ this function does not do bounds or overlap checking. +-- +-- @since 0.7.1.0 +copyByteArrayToPtr + :: forall m a. (PrimMonad m, Prim a) + => Ptr a -- ^ destination + -> ByteArray -- ^ source array + -> Int -- ^ offset into source array, interpreted as elements of type @a@ + -> Int -- ^ number of elements to copy + -> m () +{-# INLINE copyByteArrayToPtr #-} +copyByteArrayToPtr (Ptr dst#) (ByteArray src#) soff sz + = primitive_ (copyByteArrayToAddr# src# (unI# soff *# siz#) dst# (unI# sz *# siz#)) + where + siz# = sizeOf# (undefined :: a) + +-- | Copy from an unmanaged pointer address to a byte array. These must not +-- overlap. The offset and length are given in elements, not in bytes. +-- +-- /Note:/ this function does not do bounds or overlap checking. +copyPtrToMutableByteArray :: forall m a. (PrimMonad m, Prim a) + => MutableByteArray (PrimState m) -- ^ destination array + -> Int -- ^ destination offset given in elements of type @a@ + -> Ptr a -- ^ source pointer + -> Int -- ^ number of elements + -> m () +{-# INLINE copyPtrToMutableByteArray #-} +copyPtrToMutableByteArray (MutableByteArray ba#) (I# doff#) (Ptr addr#) (I# n#) = + primitive_ (copyAddrToByteArray# addr# ba# (doff# *# siz#) (n# *# siz#)) + where + siz# = sizeOf# (undefined :: a) + + +-- | Copy a slice of a mutable byte array to an unmanaged pointer address. +-- These must not overlap. The offset and length are given in elements, not +-- in bytes. +-- +-- /Note:/ this function does not do bounds or overlap checking. +-- +-- @since 0.7.1.0 +copyMutableByteArrayToPtr + :: forall m a. (PrimMonad m, Prim a) + => Ptr a -- ^ destination + -> MutableByteArray (PrimState m) -- ^ source array + -> Int -- ^ offset into source array, interpreted as elements of type @a@ + -> Int -- ^ number of elements to copy + -> m () +{-# INLINE copyMutableByteArrayToPtr #-} +copyMutableByteArrayToPtr (Ptr dst#) (MutableByteArray src#) soff sz + = primitive_ (copyMutableByteArrayToAddr# src# (unI# soff *# siz#) dst# (unI# sz *# siz#)) + where + siz# = sizeOf# (undefined :: a) + +------ +--- These latter two should be DEPRECATED +----- + -- | Copy a slice of a byte array to an unmanaged address. These must not --- overlap. This function is only available when compiling with GHC 7.8 --- or newer. +-- overlap. +-- +-- Note: This function is just 'copyByteArrayToPtr' where @a@ is 'Word8'. -- --- @since 0.6.4.0 +-- @since 0.6.4.0 copyByteArrayToAddr :: PrimMonad m => Ptr Word8 -- ^ destination @@ -336,10 +457,11 @@ copyByteArrayToAddr (Ptr dst#) (ByteArray src#) soff sz = primitive_ (copyByteArrayToAddr# src# (unI# soff) dst# (unI# sz)) -- | Copy a slice of a mutable byte array to an unmanaged address. These must --- not overlap. This function is only available when compiling with GHC 7.8 --- or newer. +-- not overlap. +-- +-- Note: This function is just 'copyMutableByteArrayToPtr' where @a@ is 'Word8'. -- --- @since 0.6.4.0 +-- @since 0.6.4.0 copyMutableByteArrayToAddr :: PrimMonad m => Ptr Word8 -- ^ destination @@ -350,19 +472,17 @@ copyMutableByteArrayToAddr {-# INLINE copyMutableByteArrayToAddr #-} copyMutableByteArrayToAddr (Ptr dst#) (MutableByteArray src#) soff sz = primitive_ (copyMutableByteArrayToAddr# src# (unI# soff) dst# (unI# sz)) -#endif -- | Copy a slice of a mutable byte array into another, potentially -- overlapping array. moveByteArray - :: PrimMonad m => MutableByteArray (PrimState m) - -- ^ destination array - -> Int -- ^ offset into destination array - -> MutableByteArray (PrimState m) - -- ^ source array - -> Int -- ^ offset into source array - -> Int -- ^ number of bytes to copy - -> m () + :: PrimMonad m + => MutableByteArray (PrimState m) -- ^ destination array + -> Int -- ^ offset into destination array + -> MutableByteArray (PrimState m) -- ^ source array + -> Int -- ^ offset into source array + -> Int -- ^ number of bytes to copy + -> m () {-# INLINE moveByteArray #-} moveByteArray (MutableByteArray dst#) doff (MutableByteArray src#) soff sz @@ -372,179 +492,154 @@ moveByteArray (MutableByteArray dst#) doff -- | Fill a slice of a mutable byte array with a value. The offset and length -- are given in elements of type @a@ rather than in bytes. +-- +-- /Note:/ this function does not do bounds checking. setByteArray - :: (Prim a, PrimMonad m) => MutableByteArray (PrimState m) -- ^ array to fill - -> Int -- ^ offset into array - -> Int -- ^ number of values to fill - -> a -- ^ value to fill with - -> m () + :: (Prim a, PrimMonad m) + => MutableByteArray (PrimState m) -- ^ array to fill + -> Int -- ^ offset into array + -> Int -- ^ number of values to fill + -> a -- ^ value to fill with + -> m () {-# INLINE setByteArray #-} setByteArray (MutableByteArray dst#) (I# doff#) (I# sz#) x = primitive_ (setByteArray# dst# doff# sz# x) -- | Fill a slice of a mutable byte array with a byte. +-- +-- /Note:/ this function does not do bounds checking. fillByteArray - :: PrimMonad m => MutableByteArray (PrimState m) - -- ^ array to fill - -> Int -- ^ offset into array - -> Int -- ^ number of bytes to fill - -> Word8 -- ^ byte to fill with - -> m () + :: PrimMonad m + => MutableByteArray (PrimState m) -- ^ array to fill + -> Int -- ^ offset into array + -> Int -- ^ number of bytes to fill + -> Word8 -- ^ byte to fill with + -> m () {-# INLINE fillByteArray #-} fillByteArray = setByteArray foreign import ccall unsafe "primitive-memops.h hsprimitive_memmove" - memmove_mba :: MutableByteArray# s -> CInt - -> MutableByteArray# s -> CInt + memmove_mba :: MutableByteArray# s -> CPtrdiff + -> MutableByteArray# s -> CPtrdiff -> CSize -> IO () -instance Data ByteArray where - toConstr _ = error "toConstr" - gunfold _ _ = error "gunfold" - dataTypeOf _ = mkNoRepType "Data.Primitive.ByteArray.ByteArray" - -instance Typeable s => Data (MutableByteArray s) where - toConstr _ = error "toConstr" - gunfold _ _ = error "gunfold" - dataTypeOf _ = mkNoRepType "Data.Primitive.ByteArray.MutableByteArray" - --- | @since 0.6.3.0 -instance Show ByteArray where - showsPrec _ ba = - showString "[" . go 0 - where - go i - | i < sizeofByteArray ba = comma . showString "0x" . showHex (indexByteArray ba i :: Word8) . go (i+1) - | otherwise = showChar ']' - where - comma | i == 0 = id - | otherwise = showString ", " - - -compareByteArrays :: ByteArray -> ByteArray -> Int -> Ordering +-- | Lexicographic comparison of equal-length slices into two byte arrays. +-- This wraps the @compareByteArrays#@ primop, which wraps @memcmp@. +compareByteArrays + :: ByteArray -- ^ array A + -> Int -- ^ offset A, given in bytes + -> ByteArray -- ^ array B + -> Int -- ^ offset B, given in bytes + -> Int -- ^ length of the slice, given in bytes + -> Ordering {-# INLINE compareByteArrays #-} #if __GLASGOW_HASKELL__ >= 804 -compareByteArrays (ByteArray ba1#) (ByteArray ba2#) (I# n#) = - compare (I# (compareByteArrays# ba1# 0# ba2# 0# n#)) 0 +compareByteArrays (ByteArray ba1#) (I# off1#) (ByteArray ba2#) (I# off2#) (I# n#) + = compare (I# (compareByteArrays# ba1# off1# ba2# off2# n#)) 0 #else -- Emulate GHC 8.4's 'GHC.Prim.compareByteArrays#' -compareByteArrays (ByteArray ba1#) (ByteArray ba2#) (I# n#) - = compare (fromCInt (unsafeDupablePerformIO (memcmp_ba ba1# ba2# n))) 0 +compareByteArrays (ByteArray ba1#) (I# off1#) (ByteArray ba2#) (I# off2#) (I# n#) + = compare (fromCInt (unsafeDupablePerformIO (memcmp_ba_offs ba1# off1# ba2# off2# n))) 0 where n = fromIntegral (I# n#) :: CSize fromCInt = fromIntegral :: CInt -> Int -foreign import ccall unsafe "primitive-memops.h hsprimitive_memcmp" - memcmp_ba :: ByteArray# -> ByteArray# -> CSize -> IO CInt +foreign import ccall unsafe "primitive-memops.h hsprimitive_memcmp_offset" + memcmp_ba_offs :: ByteArray# -> Int# -> ByteArray# -> Int# -> CSize -> IO CInt #endif - -sameByteArray :: ByteArray# -> ByteArray# -> Bool -sameByteArray ba1 ba2 = - case reallyUnsafePtrEquality# (unsafeCoerce# ba1 :: ()) (unsafeCoerce# ba2 :: ()) of -#if __GLASGOW_HASKELL__ >= 708 - r -> isTrue# r -#else - 1# -> True - 0# -> False -#endif - --- | @since 0.6.3.0 -instance Eq ByteArray where - ba1@(ByteArray ba1#) == ba2@(ByteArray ba2#) - | sameByteArray ba1# ba2# = True - | n1 /= n2 = False - | otherwise = compareByteArrays ba1 ba2 n1 == EQ - where - n1 = sizeofByteArray ba1 - n2 = sizeofByteArray ba2 - --- | Non-lexicographic ordering. This compares the lengths of --- the byte arrays first and uses a lexicographic ordering if --- the lengths are equal. Subject to change between major versions. --- --- @since 0.6.3.0 -instance Ord ByteArray where - ba1@(ByteArray ba1#) `compare` ba2@(ByteArray ba2#) - | sameByteArray ba1# ba2# = EQ - | n1 /= n2 = n1 `compare` n2 - | otherwise = compareByteArrays ba1 ba2 n1 - where - n1 = sizeofByteArray ba1 - n2 = sizeofByteArray ba2 --- Note: On GHC 8.4, the primop compareByteArrays# performs a check for pointer --- equality as a shortcut, so the check here is actually redundant. However, it --- is included here because it is likely better to check for pointer equality --- before checking for length equality. Getting the length requires deferencing --- the pointers, which could cause accesses to memory that is not in the cache. --- By contrast, a pointer equality check is always extremely cheap. - -appendByteArray :: ByteArray -> ByteArray -> ByteArray -appendByteArray a b = runST $ do - marr <- newByteArray (sizeofByteArray a + sizeofByteArray b) - copyByteArray marr 0 a 0 (sizeofByteArray a) - copyByteArray marr (sizeofByteArray a) b 0 (sizeofByteArray b) - unsafeFreezeByteArray marr - -concatByteArray :: [ByteArray] -> ByteArray -concatByteArray arrs = runST $ do - let len = calcLength arrs 0 - marr <- newByteArray len - pasteByteArrays marr 0 arrs - unsafeFreezeByteArray marr - -pasteByteArrays :: MutableByteArray s -> Int -> [ByteArray] -> ST s () -pasteByteArrays !_ !_ [] = return () -pasteByteArrays !marr !ix (x : xs) = do - copyByteArray marr ix x 0 (sizeofByteArray x) - pasteByteArrays marr (ix + sizeofByteArray x) xs - -calcLength :: [ByteArray] -> Int -> Int -calcLength [] !n = n -calcLength (x : xs) !n = calcLength xs (sizeofByteArray x + n) - +-- | The empty 'ByteArray'. emptyByteArray :: ByteArray +{-# NOINLINE emptyByteArray #-} emptyByteArray = runST (newByteArray 0 >>= unsafeFreezeByteArray) -replicateByteArray :: Int -> ByteArray -> ByteArray -replicateByteArray n arr = runST $ do - marr <- newByteArray (n * sizeofByteArray arr) - let go i = if i < n - then do - copyByteArray marr (i * sizeofByteArray arr) arr 0 (sizeofByteArray arr) - go (i + 1) - else return () - go 0 - unsafeFreezeByteArray marr - -#if MIN_VERSION_base(4,9,0) -instance SG.Semigroup ByteArray where - (<>) = appendByteArray - sconcat = mconcat . F.toList - stimes i arr - | itgr < 1 = emptyByteArray - | itgr <= (fromIntegral (maxBound :: Int)) = replicateByteArray (fromIntegral itgr) arr - | otherwise = error "Data.Primitive.ByteArray#stimes: cannot allocate the requested amount of memory" - where itgr = toInteger i :: Integer -#endif - -instance Monoid ByteArray where - mempty = emptyByteArray -#if !(MIN_VERSION_base(4,11,0)) - mappend = appendByteArray -#endif - mconcat = concatByteArray +die :: String -> String -> a +die fun problem = error $ "Data.Primitive.ByteArray." ++ fun ++ ": " ++ problem -#if __GLASGOW_HASKELL__ >= 708 --- | @since 0.6.3.0 -instance Exts.IsList ByteArray where - type Item ByteArray = Word8 +-- | Return a newly allocated array with the specified subrange of the +-- provided array. The provided array should contain the full subrange +-- specified by the two Ints, but this is not checked. +cloneByteArray + :: ByteArray -- ^ source array + -> Int -- ^ offset into destination array + -> Int -- ^ number of bytes to copy + -> ByteArray +{-# INLINE cloneByteArray #-} +cloneByteArray src off n = runByteArray $ do + dst <- newByteArray n + copyByteArray dst 0 src off n + return dst + +-- | Return a newly allocated mutable array with the specified subrange of +-- the provided mutable array. The provided mutable array should contain the +-- full subrange specified by the two Ints, but this is not checked. +cloneMutableByteArray :: PrimMonad m + => MutableByteArray (PrimState m) -- ^ source array + -> Int -- ^ offset into destination array + -> Int -- ^ number of bytes to copy + -> m (MutableByteArray (PrimState m)) +{-# INLINE cloneMutableByteArray #-} +cloneMutableByteArray src off n = do + dst <- newByteArray n + copyMutableByteArray dst 0 src off n + return dst - toList = foldrByteArray (:) [] - fromList xs = byteArrayFromListN (length xs) xs - fromListN = byteArrayFromListN +-- | Execute the monadic action and freeze the resulting array. +-- +-- > runByteArray m = runST $ m >>= unsafeFreezeByteArray +runByteArray + :: (forall s. ST s (MutableByteArray s)) + -> ByteArray +#if MIN_VERSION_base(4,10,0) /* In new GHCs, runRW# is available. */ +runByteArray m = ByteArray (runByteArray# m) + +runByteArray# + :: (forall s. ST s (MutableByteArray s)) + -> ByteArray# +runByteArray# m = case runRW# $ \s -> + case unST m s of { (# s', MutableByteArray mary# #) -> + unsafeFreezeByteArray# mary# s'} of (# _, ary# #) -> ary# + +unST :: ST s a -> State# s -> (# State# s, a #) +unST (GHCST.ST f) = f +#else /* In older GHCs, runRW# is not available. */ +runByteArray m = runST $ m >>= unsafeFreezeByteArray #endif -die :: String -> String -> a -die fun problem = error $ "Data.Primitive.ByteArray." ++ fun ++ ": " ++ problem +{- $charElementAccess +GHC provides two sets of element accessors for 'Char'. One set faithfully +represents 'Char' as 32-bit words using UTF-32. The other set represents +'Char' as 8-bit words using Latin-1 (ISO-8859-1), and the write operation +has undefined behavior for codepoints outside of the ASCII and Latin-1 +blocks. The 'Prim' instance for 'Char' uses the UTF-32 set of operators. +-} +-- | Read an 8-bit element from the byte array, interpreting it as a +-- Latin-1-encoded character. The offset is given in bytes. +-- +-- /Note:/ this function does not do bounds checking. +readCharArray :: PrimMonad m => MutableByteArray (PrimState m) -> Int -> m Char +{-# INLINE readCharArray #-} +readCharArray (MutableByteArray arr#) (I# i#) = primitive + (\s0 -> case readCharArray# arr# i# s0 of + (# s1, c #) -> (# s1, C# c #) + ) + +-- | Write a character to the byte array, encoding it with Latin-1 as +-- a single byte. Behavior is undefined for codepoints outside of the +-- ASCII and Latin-1 blocks. The offset is given in bytes. +-- +-- /Note:/ this function does not do bounds checking. +writeCharArray + :: PrimMonad m => MutableByteArray (PrimState m) -> Int -> Char -> m () +{-# INLINE writeCharArray #-} +writeCharArray (MutableByteArray arr#) (I# i#) (C# c) + = primitive_ (writeCharArray# arr# i# c) + +-- | Read an 8-bit element from the byte array, interpreting it as a +-- Latin-1-encoded character. The offset is given in bytes. +-- +-- /Note:/ this function does not do bounds checking. +indexCharArray :: ByteArray -> Int -> Char +{-# INLINE indexCharArray #-} +indexCharArray (ByteArray arr#) (I# i#) = C# (indexCharArray# arr# i#) diff --git a/examples/primitive/Data/Primitive/Internal/Operations.hs b/examples/primitive/Data/Primitive/Internal/Operations.hs index 20a7cd99c..9630a4025 100644 --- a/examples/primitive/Data/Primitive/Internal/Operations.hs +++ b/examples/primitive/Data/Primitive/Internal/Operations.hs @@ -1,4 +1,4 @@ -{-# LANGUAGE MagicHash, UnliftedFFITypes #-} +{-# LANGUAGE CPP, MagicHash, UnliftedFFITypes #-} -- | -- Module : Data.Primitive.Internal.Operations @@ -8,9 +8,7 @@ -- Maintainer : Roman Leshchinskiy -- Portability : non-portable -- --- Internal operations --- - +-- Internal operations. module Data.Primitive.Internal.Operations ( setWord8Array#, setWord16Array#, setWord32Array#, @@ -32,26 +30,49 @@ import Data.Primitive.MachDeps (Word64_#, Int64_#) import Foreign.C.Types import GHC.Exts + +#if __GLASGOW_HASKELL__ >= 902 foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word8" setWord8Array# :: MutableByteArray# s -> CPtrdiff -> CSize -> Word8# -> IO () foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word16" setWord16Array# :: MutableByteArray# s -> CPtrdiff -> CSize -> Word16# -> IO () foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word32" setWord32Array# :: MutableByteArray# s -> CPtrdiff -> CSize -> Word32# -> IO () +#else +foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word8" + setWord8Array# :: MutableByteArray# s -> CPtrdiff -> CSize -> Word# -> IO () +foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word16" + setWord16Array# :: MutableByteArray# s -> CPtrdiff -> CSize -> Word# -> IO () +foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word32" + setWord32Array# :: MutableByteArray# s -> CPtrdiff -> CSize -> Word# -> IO () +#endif + foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word64" setWord64Array# :: MutableByteArray# s -> CPtrdiff -> CSize -> Word64_# -> IO () foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word" setWordArray# :: MutableByteArray# s -> CPtrdiff -> CSize -> Word# -> IO () + +#if __GLASGOW_HASKELL__ >= 902 foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word8" setInt8Array# :: MutableByteArray# s -> CPtrdiff -> CSize -> Int8# -> IO () foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word16" setInt16Array# :: MutableByteArray# s -> CPtrdiff -> CSize -> Int16# -> IO () foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word32" setInt32Array# :: MutableByteArray# s -> CPtrdiff -> CSize -> Int32# -> IO () +#else +foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word8" + setInt8Array# :: MutableByteArray# s -> CPtrdiff -> CSize -> Int# -> IO () +foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word16" + setInt16Array# :: MutableByteArray# s -> CPtrdiff -> CSize -> Int# -> IO () +foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word32" + setInt32Array# :: MutableByteArray# s -> CPtrdiff -> CSize -> Int# -> IO () +#endif + foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word64" setInt64Array# :: MutableByteArray# s -> CPtrdiff -> CSize -> Int64_# -> IO () foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word" setIntArray# :: MutableByteArray# s -> CPtrdiff -> CSize -> Int# -> IO () + foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Ptr" setAddrArray# :: MutableByteArray# s -> CPtrdiff -> CSize -> Addr# -> IO () foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Ptr" @@ -63,26 +84,48 @@ foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Double" foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Char" setWideCharArray# :: MutableByteArray# s -> CPtrdiff -> CSize -> Char# -> IO () +#if __GLASGOW_HASKELL__ >= 902 foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word8" setWord8OffAddr# :: Addr# -> CPtrdiff -> CSize -> Word8# -> IO () foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word16" setWord16OffAddr# :: Addr# -> CPtrdiff -> CSize -> Word16# -> IO () foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word32" setWord32OffAddr# :: Addr# -> CPtrdiff -> CSize -> Word32# -> IO () +#else +foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word8" + setWord8OffAddr# :: Addr# -> CPtrdiff -> CSize -> Word# -> IO () +foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word16" + setWord16OffAddr# :: Addr# -> CPtrdiff -> CSize -> Word# -> IO () +foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word32" + setWord32OffAddr# :: Addr# -> CPtrdiff -> CSize -> Word# -> IO () +#endif + foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word64" setWord64OffAddr# :: Addr# -> CPtrdiff -> CSize -> Word64_# -> IO () foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word" setWordOffAddr# :: Addr# -> CPtrdiff -> CSize -> Word# -> IO () + +#if __GLASGOW_HASKELL__ >= 902 foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word8" setInt8OffAddr# :: Addr# -> CPtrdiff -> CSize -> Int8# -> IO () foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word16" setInt16OffAddr# :: Addr# -> CPtrdiff -> CSize -> Int16# -> IO () foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word32" setInt32OffAddr# :: Addr# -> CPtrdiff -> CSize -> Int32# -> IO () +#else +foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word8" + setInt8OffAddr# :: Addr# -> CPtrdiff -> CSize -> Int# -> IO () +foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word16" + setInt16OffAddr# :: Addr# -> CPtrdiff -> CSize -> Int# -> IO () +foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word32" + setInt32OffAddr# :: Addr# -> CPtrdiff -> CSize -> Int# -> IO () +#endif + foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word64" setInt64OffAddr# :: Addr# -> CPtrdiff -> CSize -> Int64_# -> IO () foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word" setIntOffAddr# :: Addr# -> CPtrdiff -> CSize -> Int# -> IO () + foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Ptr" setAddrOffAddr# :: Addr# -> CPtrdiff -> CSize -> Addr# -> IO () foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Ptr" diff --git a/examples/primitive/Data/Primitive/MVar.hs b/examples/primitive/Data/Primitive/MVar.hs index 3c7bfd1fa..62b2aa1c5 100644 --- a/examples/primitive/Data/Primitive/MVar.hs +++ b/examples/primitive/Data/Primitive/MVar.hs @@ -8,14 +8,17 @@ -- License : BSD2 -- Portability : non-portable -- --- Primitive operations on @MVar@. This module provides a similar interface +-- Primitive operations on 'MVar'. This module provides a similar interface -- to "Control.Concurrent.MVar". However, the functions are generalized to -- work in any 'PrimMonad' instead of only working in 'IO'. Note that all -- of the functions here are completely deterministic. Users of 'MVar' are -- responsible for designing abstractions that guarantee determinism in -- the presence of multi-threading. -- +-- For a more detailed explanation, see "Control.Concurrent.MVar". +-- -- @since 0.6.4.0 + module Data.Primitive.MVar ( MVar(..) , newMVar @@ -30,14 +33,12 @@ module Data.Primitive.MVar ) where import Control.Monad.Primitive -import Data.Primitive.Internal.Compat (isTrue#) -import GHC.Exts (MVar#,newMVar#,takeMVar#,sameMVar#,putMVar#,tryTakeMVar#, - isEmptyMVar#,tryPutMVar#,(/=#)) - -#if __GLASGOW_HASKELL__ >= 708 -import GHC.Exts (readMVar#,tryReadMVar#) -#endif +import GHC.Exts + ( MVar#, newMVar#, takeMVar#, sameMVar#, putMVar#, tryTakeMVar#, isEmptyMVar#, tryPutMVar#, (/=#) + , readMVar#, tryReadMVar#, isTrue# ) +-- | A synchronizing variable, used for communication between concurrent threads. +-- It can be thought of as a box, which may be empty or full. data MVar s a = MVar (MVar# s a) instance Eq (MVar s a) where @@ -49,54 +50,62 @@ newEmptyMVar = primitive $ \ s# -> case newMVar# s# of (# s2#, svar# #) -> (# s2#, MVar svar# #) - -- | Create a new 'MVar' that holds the supplied argument. newMVar :: PrimMonad m => a -> m (MVar (PrimState m) a) -newMVar value = - newEmptyMVar >>= \ mvar -> - putMVar mvar value >> +newMVar value = do + mvar <- newEmptyMVar + putMVar mvar value return mvar --- | Return the contents of the 'MVar'. If the 'MVar' is currently --- empty, 'takeMVar' will wait until it is full. After a 'takeMVar', +-- | Return the contents of the 'MVar'. If the 'MVar' is currently +-- empty, 'takeMVar' will wait until it is full. After a 'takeMVar', -- the 'MVar' is left empty. +-- +-- There are two further important properties of 'takeMVar': +-- +-- * 'takeMVar' is single-wakeup. That is, if there are multiple +-- threads blocked in 'takeMVar', and the 'MVar' becomes full, +-- only one thread will be woken up. The runtime guarantees that +-- the woken thread completes its 'takeMVar' operation. +-- * When multiple threads are blocked on an 'MVar', they are +-- woken up in FIFO order. This is useful for providing +-- fairness properties of abstractions built using 'MVar's. takeMVar :: PrimMonad m => MVar (PrimState m) a -> m a takeMVar (MVar mvar#) = primitive $ \ s# -> takeMVar# mvar# s# --- | Atomically read the contents of an 'MVar'. If the 'MVar' is +-- | Atomically read the contents of an 'MVar'. If the 'MVar' is -- currently empty, 'readMVar' will wait until it is full. -- 'readMVar' is guaranteed to receive the next 'putMVar'. -- -- /Multiple Wakeup:/ 'readMVar' is multiple-wakeup, so when multiple readers -- are blocked on an 'MVar', all of them are woken up at the same time. -- --- /Compatibility note:/ On GHCs prior to 7.8, 'readMVar' is a combination --- of 'takeMVar' and 'putMVar'. Consequently, its behavior differs in the --- following ways: --- -- * It is single-wakeup instead of multiple-wakeup. -- * It might not receive the value from the next call to 'putMVar' if -- there is already a pending thread blocked on 'takeMVar'. -- * If another thread puts a value in the 'MVar' in between the -- calls to 'takeMVar' and 'putMVar', that value may be overridden. readMVar :: PrimMonad m => MVar (PrimState m) a -> m a -#if __GLASGOW_HASKELL__ >= 708 readMVar (MVar mvar#) = primitive $ \ s# -> readMVar# mvar# s# -#else -readMVar mv = do - a <- takeMVar mv - putMVar mv a - return a -#endif --- |Put a value into an 'MVar'. If the 'MVar' is currently full, +-- | Put a value into an 'MVar'. If the 'MVar' is currently full, -- 'putMVar' will wait until it becomes empty. +-- +-- There are two further important properties of 'putMVar': +-- +-- * 'putMVar' is single-wakeup. That is, if there are multiple +-- threads blocked in 'putMVar', and the 'MVar' becomes empty, +-- only one thread will be woken up. The runtime guarantees that +-- the woken thread completes its 'putMVar' operation. +-- * When multiple threads are blocked on an 'MVar', they are +-- woken up in FIFO order. This is useful for providing +-- fairness properties of abstractions built using 'MVar's. putMVar :: PrimMonad m => MVar (PrimState m) a -> a -> m () putMVar (MVar mvar#) x = primitive_ (putMVar# mvar# x) --- |A non-blocking version of 'takeMVar'. The 'tryTakeMVar' function +-- | A non-blocking version of 'takeMVar'. The 'tryTakeMVar' function -- returns immediately, with 'Nothing' if the 'MVar' was empty, or --- @'Just' a@ if the 'MVar' was full with contents @a@. After 'tryTakeMVar', +-- @'Just' a@ if the 'MVar' was full with contents @a@. After 'tryTakeMVar', -- the 'MVar' is left empty. tryTakeMVar :: PrimMonad m => MVar (PrimState m) a -> m (Maybe a) tryTakeMVar (MVar m) = primitive $ \ s -> @@ -104,8 +113,7 @@ tryTakeMVar (MVar m) = primitive $ \ s -> (# s', 0#, _ #) -> (# s', Nothing #) -- MVar is empty (# s', _, a #) -> (# s', Just a #) -- MVar is full - --- |A non-blocking version of 'putMVar'. The 'tryPutMVar' function +-- | A non-blocking version of 'putMVar'. The 'tryPutMVar' function -- attempts to put the value @a@ into the 'MVar', returning 'True' if -- it was successful, or 'False' otherwise. tryPutMVar :: PrimMonad m => MVar (PrimState m) a -> a -> m Bool @@ -114,41 +122,27 @@ tryPutMVar (MVar mvar#) x = primitive $ \ s# -> (# s, 0# #) -> (# s, False #) (# s, _ #) -> (# s, True #) --- | A non-blocking version of 'readMVar'. The 'tryReadMVar' function +-- | A non-blocking version of 'readMVar'. The 'tryReadMVar' function -- returns immediately, with 'Nothing' if the 'MVar' was empty, or -- @'Just' a@ if the 'MVar' was full with contents @a@. -- --- /Compatibility note:/ On GHCs prior to 7.8, 'tryReadMVar' is a combination --- of 'tryTakeMVar' and 'putMVar'. Consequently, its behavior differs in the --- following ways: --- -- * It is single-wakeup instead of multiple-wakeup. -- * In the presence of other threads calling 'putMVar', 'tryReadMVar' -- may block. -- * If another thread puts a value in the 'MVar' in between the -- calls to 'tryTakeMVar' and 'putMVar', that value may be overridden. tryReadMVar :: PrimMonad m => MVar (PrimState m) a -> m (Maybe a) -#if __GLASGOW_HASKELL__ >= 708 tryReadMVar (MVar m) = primitive $ \ s -> case tryReadMVar# m s of (# s', 0#, _ #) -> (# s', Nothing #) -- MVar is empty (# s', _, a #) -> (# s', Just a #) -- MVar is full -#else -tryReadMVar mv = do - ma <- tryTakeMVar mv - case ma of - Just a -> do - putMVar mv a - return (Just a) - Nothing -> return Nothing -#endif -- | Check whether a given 'MVar' is empty. -- --- Notice that the boolean value returned is just a snapshot of --- the state of the MVar. By the time you get to react on its result, --- the MVar may have been filled (or emptied) - so be extremely --- careful when using this operation. Use 'tryTakeMVar' instead if possible. +-- Notice that the boolean value returned is just a snapshot of +-- the state of the 'MVar'. By the time you get to react on its result, +-- the 'MVar' may have been filled (or emptied) - so be extremely +-- careful when using this operation. Use 'tryTakeMVar' instead if possible. isEmptyMVar :: PrimMonad m => MVar (PrimState m) a -> m Bool isEmptyMVar (MVar mv#) = primitive $ \ s# -> case isEmptyMVar# mv# s# of diff --git a/examples/primitive/Data/Primitive/MachDeps.hs b/examples/primitive/Data/Primitive/MachDeps.hs index bdf857bda..21d3db40a 100644 --- a/examples/primitive/Data/Primitive/MachDeps.hs +++ b/examples/primitive/Data/Primitive/MachDeps.hs @@ -1,4 +1,5 @@ {-# LANGUAGE CPP, MagicHash #-} + -- | -- Module : Data.Primitive.MachDeps -- Copyright : (c) Roman Leshchinskiy 2009-2012 @@ -7,8 +8,7 @@ -- Maintainer : Roman Leshchinskiy -- Portability : non-portable -- --- Machine-dependent constants --- +-- Machine-dependent constants. module Data.Primitive.MachDeps where @@ -113,11 +113,10 @@ aLIGNMENT_INT64 = ALIGNMENT_INT64 sIZEOF_WORD64 = SIZEOF_WORD64 aLIGNMENT_WORD64 = ALIGNMENT_WORD64 -#if WORD_SIZE_IN_BITS == 32 +#if WORD_SIZE_IN_BITS == 32 || __GLASGOW_HASKELL__ >= 903 type Word64_# = Word64# type Int64_# = Int64# #else type Word64_# = Word# type Int64_# = Int# #endif - diff --git a/examples/primitive/Data/Primitive/MutVar.hs b/examples/primitive/Data/Primitive/MutVar.hs index 85e728323..2578bc6d1 100644 --- a/examples/primitive/Data/Primitive/MutVar.hs +++ b/examples/primitive/Data/Primitive/MutVar.hs @@ -8,8 +8,9 @@ -- Maintainer : Roman Leshchinskiy -- Portability : non-portable -- --- Primitive boxed mutable variables --- +-- Primitive boxed mutable variables. This is a generalization of +-- "Data.IORef", "Data.STRef" and "Data.STRef.Lazy" to work in +-- any 'PrimMonad'. module Data.Primitive.MutVar ( MutVar(..), @@ -25,9 +26,9 @@ module Data.Primitive.MutVar ( ) where import Control.Monad.Primitive ( PrimMonad(..), primitive_ ) -import GHC.Exts ( MutVar#, sameMutVar#, newMutVar#, - readMutVar#, writeMutVar#, atomicModifyMutVar# ) -import Data.Primitive.Internal.Compat ( isTrue# ) +import GHC.Exts ( MutVar#, sameMutVar#, newMutVar# + , readMutVar#, writeMutVar#, atomicModifyMutVar# + , isTrue# ) import Data.Typeable ( Typeable ) -- | A 'MutVar' behaves like a single-element mutable array associated @@ -38,25 +39,38 @@ data MutVar s a = MutVar (MutVar# s a) instance Eq (MutVar s a) where MutVar mva# == MutVar mvb# = isTrue# (sameMutVar# mva# mvb#) --- | Create a new 'MutVar' with the specified initial value +-- | Create a new 'MutVar' with the specified initial value. newMutVar :: PrimMonad m => a -> m (MutVar (PrimState m) a) {-# INLINE newMutVar #-} newMutVar initialValue = primitive $ \s# -> case newMutVar# initialValue s# of (# s'#, mv# #) -> (# s'#, MutVar mv# #) --- | Read the value of a 'MutVar' +-- | Read the value of a 'MutVar'. readMutVar :: PrimMonad m => MutVar (PrimState m) a -> m a {-# INLINE readMutVar #-} readMutVar (MutVar mv#) = primitive (readMutVar# mv#) --- | Write a new value into a 'MutVar' +-- | Write a new value into a 'MutVar'. writeMutVar :: PrimMonad m => MutVar (PrimState m) a -> a -> m () {-# INLINE writeMutVar #-} writeMutVar (MutVar mv#) newValue = primitive_ (writeMutVar# mv# newValue) --- | Atomically mutate the contents of a 'MutVar' -atomicModifyMutVar :: PrimMonad m => MutVar (PrimState m) a -> (a -> (a,b)) -> m b +-- | Atomically mutate the contents of a 'MutVar'. +-- +-- This function is useful for using 'MutVar' in a safe way in a multithreaded program. +-- If you only have one 'MutVar', then using 'atomicModifyMutVar' to access and modify +-- it will prevent race conditions. +-- +-- Extending the atomicity to multiple 'MutVar's is problematic, +-- so if you need to do anything more complicated, +-- using 'Data.Primitive.MVar.MVar' instead is a good idea. +-- +-- 'atomicModifyMutVar' does not apply the function strictly. This means if a program +-- calls 'atomicModifyMutVar' many times, but seldom uses the value, thunks will pile up +-- in memory resulting in a space leak. +-- To avoid this problem, use 'atomicModifyMutVar'' instead. +atomicModifyMutVar :: PrimMonad m => MutVar (PrimState m) a -> (a -> (a, b)) -> m b {-# INLINE atomicModifyMutVar #-} atomicModifyMutVar (MutVar mv#) f = primitive $ atomicModifyMutVar# mv# f @@ -69,16 +83,21 @@ atomicModifyMutVar' mv f = do b `seq` return b where force x = case f x of - v@(x',_) -> x' `seq` v + v@(x', _) -> x' `seq` v --- | Mutate the contents of a 'MutVar' +-- | Mutate the contents of a 'MutVar'. +-- +-- 'modifyMutVar' does not apply the function strictly. This means if a program +-- calls 'modifyMutVar' many times, but seldom uses the value, thunks will pile up +-- in memory resulting in a space leak. +-- To avoid this problem, use 'modifyMutVar'' instead. modifyMutVar :: PrimMonad m => MutVar (PrimState m) a -> (a -> a) -> m () {-# INLINE modifyMutVar #-} modifyMutVar (MutVar mv#) g = primitive_ $ \s# -> case readMutVar# mv# s# of (# s'#, a #) -> writeMutVar# mv# (g a) s'# --- | Strict version of 'modifyMutVar' +-- | Strict version of 'modifyMutVar'. modifyMutVar' :: PrimMonad m => MutVar (PrimState m) a -> (a -> a) -> m () {-# INLINE modifyMutVar' #-} modifyMutVar' (MutVar mv#) g = primitive_ $ \s# -> diff --git a/examples/primitive/Data/Primitive/PrimArray.hs b/examples/primitive/Data/Primitive/PrimArray.hs index a99d605b4..ca8c3eb45 100644 --- a/examples/primitive/Data/Primitive/PrimArray.hs +++ b/examples/primitive/Data/Primitive/PrimArray.hs @@ -5,7 +5,8 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UnboxedTuples #-} - +{-# LANGUAGE TemplateHaskellQuotes #-} +{-# LANGUAGE RoleAnnotations #-} -- | -- Module : Data.Primitive.PrimArray @@ -15,46 +16,57 @@ -- Maintainer : Roman Leshchinskiy -- Portability : non-portable -- --- Arrays of unboxed primitive types. The function provided by this module --- match the behavior of those provided by @Data.Primitive.ByteArray@, and +-- Arrays of unboxed primitive types. The functions provided by this module +-- match the behavior of those provided by "Data.Primitive.ByteArray", and -- the underlying types and primops that back them are the same. -- However, the type constructors 'PrimArray' and 'MutablePrimArray' take one additional --- argument than their respective counterparts 'ByteArray' and 'MutableByteArray'. +-- argument compared to their respective counterparts 'ByteArray' and 'Data.Primitive.ByteArray.MutableByteArray'. -- This argument is used to designate the type of element in the array. --- Consequently, all function this modules accepts length and incides in +-- Consequently, all functions in this module accept length and indices in -- terms of elements, not bytes. -- -- @since 0.6.4.0 + module Data.Primitive.PrimArray ( -- * Types PrimArray(..) , MutablePrimArray(..) -- * Allocation , newPrimArray + , newPinnedPrimArray + , newAlignedPinnedPrimArray , resizeMutablePrimArray -#if __GLASGOW_HASKELL__ >= 710 , shrinkMutablePrimArray -#endif -- * Element Access , readPrimArray , writePrimArray , indexPrimArray -- * Freezing and Thawing + , freezePrimArray + , thawPrimArray + , runPrimArray , unsafeFreezePrimArray , unsafeThawPrimArray -- * Block Operations , copyPrimArray , copyMutablePrimArray -#if __GLASGOW_HASKELL__ >= 708 , copyPrimArrayToPtr , copyMutablePrimArrayToPtr -#endif + , copyPtrToMutablePrimArray + , clonePrimArray + , cloneMutablePrimArray , setPrimArray -- * Information , sameMutablePrimArray , getSizeofMutablePrimArray , sizeofMutablePrimArray , sizeofPrimArray + , primArrayContents + , mutablePrimArrayContents +#if __GLASGOW_HASKELL__ >= 802 + , isPrimArrayPinned + , isMutablePrimArrayPinned +#endif -- * List Conversion , primArrayToList , primArrayFromList @@ -69,6 +81,7 @@ module Data.Primitive.PrimArray , traversePrimArray_ , itraversePrimArray_ -- * Map/Create + , emptyPrimArray , mapPrimArray , imapPrimArray , generatePrimArray @@ -77,6 +90,7 @@ module Data.Primitive.PrimArray , mapMaybePrimArray -- * Effectful Map/Create -- $effectfulMapCreate + -- ** Lazy Applicative , traversePrimArray , itraversePrimArray @@ -94,52 +108,74 @@ module Data.Primitive.PrimArray ) where import GHC.Exts -import GHC.Base ( Int(..) ) -import Data.Primitive.Internal.Compat (isTrue#) import Data.Primitive.Types import Data.Primitive.ByteArray (ByteArray(..)) -import Data.Monoid (Monoid(..),(<>)) -import Control.Applicative +#if !MIN_VERSION_base(4,11,0) +import Data.Monoid ((<>)) +#endif +#if !MIN_VERSION_base(4,18,0) +import Control.Applicative (liftA2) +#endif +import Control.DeepSeq import Control.Monad.Primitive import Control.Monad.ST import qualified Data.List as L import qualified Data.Primitive.ByteArray as PB import qualified Data.Primitive.Types as PT - -#if MIN_VERSION_base(4,7,0) -import GHC.Exts (IsList(..)) +#if MIN_VERSION_base(4,10,0) +import qualified GHC.ST as GHCST #endif +import Language.Haskell.TH.Syntax (Lift (..)) -#if MIN_VERSION_base(4,9,0) +#if !MIN_VERSION_base(4,11,0) import Data.Semigroup (Semigroup) +#endif import qualified Data.Semigroup as SG + +#if __GLASGOW_HASKELL__ >= 802 +import qualified GHC.Exts as Exts #endif -- | Arrays of unboxed elements. This accepts types like 'Double', 'Char', --- 'Int', and 'Word', as well as their fixed-length variants ('Word8', +-- 'Int' and 'Word', as well as their fixed-length variants ('Word8', -- 'Word16', etc.). Since the elements are unboxed, a 'PrimArray' is strict --- in its elements. This differs from the behavior of 'Array', which is lazy --- in its elements. +-- in its elements. This differs from the behavior of 'Data.Primitive.Array.Array', +-- which is lazy in its elements. data PrimArray a = PrimArray ByteArray# +type role PrimArray nominal + +instance Lift (PrimArray a) where +#if MIN_VERSION_template_haskell(2,16,0) + liftTyped ary = [|| byteArrayToPrimArray ba ||] +#else + lift ary = [| byteArrayToPrimArray ba |] +#endif + where + ba = primArrayToByteArray ary + +instance NFData (PrimArray a) where + rnf (PrimArray _) = () + -- | Mutable primitive arrays associated with a primitive state token. -- These can be written to and read from in a monadic context that supports --- sequencing such as 'IO' or 'ST'. Typically, a mutable primitive array will --- be built and then convert to an immutable primitive array using +-- sequencing, such as 'IO' or 'ST'. Typically, a mutable primitive array will +-- be built and then converted to an immutable primitive array using -- 'unsafeFreezePrimArray'. However, it is also acceptable to simply discard -- a mutable primitive array since it lives in managed memory and will be -- garbage collected when no longer referenced. data MutablePrimArray s a = MutablePrimArray (MutableByteArray# s) +instance Eq (MutablePrimArray s a) where + (==) = sameMutablePrimArray + +instance NFData (MutablePrimArray s a) where + rnf (MutablePrimArray _) = () + sameByteArray :: ByteArray# -> ByteArray# -> Bool sameByteArray ba1 ba2 = case reallyUnsafePtrEquality# (unsafeCoerce# ba1 :: ()) (unsafeCoerce# ba2 :: ()) of -#if __GLASGOW_HASKELL__ >= 708 r -> isTrue# r -#else - 1# -> True - _ -> False -#endif -- | @since 0.6.4.0 instance (Eq a, Prim a) => Eq (PrimArray a) where @@ -155,12 +191,12 @@ instance (Eq a, Prim a) => Eq (PrimArray a) where sz2 = PB.sizeofByteArray (ByteArray ba2#) loop !i | i < 0 = True - | otherwise = indexPrimArray a1 i == indexPrimArray a2 i && loop (i-1) + | otherwise = indexPrimArray a1 i == indexPrimArray a2 i && loop (i - 1) {-# INLINE (==) #-} -- | Lexicographic ordering. Subject to change between major versions. -- --- @since 0.6.4.0 +-- @since 0.6.4.0 instance (Ord a, Prim a) => Ord (PrimArray a) where compare a1@(PrimArray ba1#) a2@(PrimArray ba2#) | sameByteArray ba1# ba2# = EQ @@ -170,18 +206,16 @@ instance (Ord a, Prim a) => Ord (PrimArray a) where sz2 = PB.sizeofByteArray (ByteArray ba2#) sz = quot (min sz1 sz2) (sizeOf (undefined :: a)) loop !i - | i < sz = compare (indexPrimArray a1 i) (indexPrimArray a2 i) <> loop (i+1) + | i < sz = compare (indexPrimArray a1 i) (indexPrimArray a2 i) <> loop (i + 1) | otherwise = compare sz1 sz2 {-# INLINE compare #-} -#if MIN_VERSION_base(4,7,0) -- | @since 0.6.4.0 instance Prim a => IsList (PrimArray a) where type Item (PrimArray a) = a fromList = primArrayFromList fromListN = primArrayFromListN toList = primArrayToList -#endif -- | @since 0.6.4.0 instance (Show a, Prim a) => Show (PrimArray a) where @@ -192,9 +226,14 @@ instance (Show a, Prim a) => Show (PrimArray a) where die :: String -> String -> a die fun problem = error $ "Data.Primitive.PrimArray." ++ fun ++ ": " ++ problem +-- | Create a 'PrimArray' from a list. +-- +-- @primArrayFromList vs = `primArrayFromListN` (length vs) vs@ primArrayFromList :: Prim a => [a] -> PrimArray a primArrayFromList vs = primArrayFromListN (L.length vs) vs +-- | Create a 'PrimArray' from a list of a known length. If the length +-- of the list does not match the given length, this throws an exception. primArrayFromListN :: forall a. Prim a => Int -> [a] -> PrimArray a primArrayFromListN len vs = runST run where run :: forall s. ST s (PrimArray a) @@ -212,7 +251,7 @@ primArrayFromListN len vs = runST run where go vs 0 unsafeFreezePrimArray arr --- | Convert the primitive array to a list. +-- | Convert a 'PrimArray' to a list. {-# INLINE primArrayToList #-} primArrayToList :: forall a. Prim a => PrimArray a -> [a] primArrayToList xs = build (\c n -> foldrPrimArray c n xs) @@ -223,13 +262,11 @@ primArrayToByteArray (PrimArray x) = PB.ByteArray x byteArrayToPrimArray :: ByteArray -> PrimArray a byteArrayToPrimArray (PB.ByteArray x) = PrimArray x -#if MIN_VERSION_base(4,9,0) -- | @since 0.6.4.0 instance Semigroup (PrimArray a) where x <> y = byteArrayToPrimArray (primArrayToByteArray x SG.<> primArrayToByteArray y) sconcat = byteArrayToPrimArray . SG.sconcat . fmap primArrayToByteArray stimes i arr = byteArrayToPrimArray (SG.stimes i (primArrayToByteArray arr)) -#endif -- | @since 0.6.4.0 instance Monoid (PrimArray a) where @@ -239,7 +276,7 @@ instance Monoid (PrimArray a) where #endif mconcat = byteArrayToPrimArray . mconcat . map primArrayToByteArray --- | The empty primitive array. +-- | The empty 'PrimArray'. emptyPrimArray :: PrimArray a {-# NOINLINE emptyPrimArray #-} emptyPrimArray = runST $ primitive $ \s0# -> case newByteArray# 0# s0# of @@ -248,6 +285,8 @@ emptyPrimArray = runST $ primitive $ \s0# -> case newByteArray# 0# s0# of -- | Create a new mutable primitive array of the given length. The -- underlying memory is left uninitialized. +-- +-- /Note:/ this function does not check if the input is non-negative. newPrimArray :: forall m a. (PrimMonad m, Prim a) => Int -> m (MutablePrimArray (PrimState m) a) {-# INLINE newPrimArray #-} newPrimArray (I# n#) @@ -271,23 +310,12 @@ resizeMutablePrimArray :: forall m a. (PrimMonad m, Prim a) -> Int -- ^ new size -> m (MutablePrimArray (PrimState m) a) {-# INLINE resizeMutablePrimArray #-} -#if __GLASGOW_HASKELL__ >= 710 resizeMutablePrimArray (MutablePrimArray arr#) (I# n#) = primitive (\s# -> case resizeMutableByteArray# arr# (n# *# sizeOf# (undefined :: a)) s# of (# s'#, arr'# #) -> (# s'#, MutablePrimArray arr'# #)) -#else -resizeMutablePrimArray arr n - = do arr' <- newPrimArray n - copyMutablePrimArray arr' 0 arr 0 (min (sizeofMutablePrimArray arr) n) - return arr' -#endif --- Although it is possible to shim resizeMutableByteArray for old GHCs, this --- is not the case with shrinkMutablePrimArray. -#if __GLASGOW_HASKELL__ >= 710 -- | Shrink a mutable primitive array. The new size is given in elements. -- It must be smaller than the old size. The array will be resized in place. --- This function is only available when compiling with GHC 7.10 or newer. shrinkMutablePrimArray :: forall m a. (PrimMonad m, Prim a) => MutablePrimArray (PrimState m) a -> Int -- ^ new size @@ -295,16 +323,20 @@ shrinkMutablePrimArray :: forall m a. (PrimMonad m, Prim a) {-# INLINE shrinkMutablePrimArray #-} shrinkMutablePrimArray (MutablePrimArray arr#) (I# n#) = primitive_ (shrinkMutableByteArray# arr# (n# *# sizeOf# (undefined :: a))) -#endif +-- | Read a value from the array at the given index. +-- +-- /Note:/ this function does not do bounds checking. readPrimArray :: (Prim a, PrimMonad m) => MutablePrimArray (PrimState m) a -> Int -> m a {-# INLINE readPrimArray #-} readPrimArray (MutablePrimArray arr#) (I# i#) = primitive (readByteArray# arr# i#) -- | Write an element to the given index. -writePrimArray :: - (Prim a, PrimMonad m) +-- +-- /Note:/ this function does not do bounds checking. +writePrimArray + :: (Prim a, PrimMonad m) => MutablePrimArray (PrimState m) a -- ^ array -> Int -- ^ index -> a -- ^ element @@ -314,8 +346,10 @@ writePrimArray (MutablePrimArray arr#) (I# i#) x = primitive_ (writeByteArray# arr# i# x) -- | Copy part of a mutable array into another mutable array. --- In the case that the destination and --- source arrays are the same, the regions may overlap. +-- In the case that the destination and +-- source arrays are the same, the regions may overlap. +-- +-- /Note:/ this function does not do bounds or overlap checking. copyMutablePrimArray :: forall m a. (PrimMonad m, Prim a) => MutablePrimArray (PrimState m) a -- ^ destination array @@ -328,13 +362,15 @@ copyMutablePrimArray :: forall m a. copyMutablePrimArray (MutablePrimArray dst#) (I# doff#) (MutablePrimArray src#) (I# soff#) (I# n#) = primitive_ (copyMutableByteArray# src# - (soff# *# (sizeOf# (undefined :: a))) + (soff# *# sizeOf# (undefined :: a)) dst# - (doff# *# (sizeOf# (undefined :: a))) - (n# *# (sizeOf# (undefined :: a))) + (doff# *# sizeOf# (undefined :: a)) + (n# *# sizeOf# (undefined :: a)) ) -- | Copy part of an array into another mutable array. +-- +-- /Note:/ this function does not do bounds or overlap checking. copyPrimArray :: forall m a. (PrimMonad m, Prim a) => MutablePrimArray (PrimState m) a -- ^ destination array @@ -347,23 +383,23 @@ copyPrimArray :: forall m a. copyPrimArray (MutablePrimArray dst#) (I# doff#) (PrimArray src#) (I# soff#) (I# n#) = primitive_ (copyByteArray# src# - (soff# *# (sizeOf# (undefined :: a))) + (soff# *# sizeOf# (undefined :: a)) dst# - (doff# *# (sizeOf# (undefined :: a))) - (n# *# (sizeOf# (undefined :: a))) + (doff# *# sizeOf# (undefined :: a)) + (n# *# sizeOf# (undefined :: a)) ) -#if __GLASGOW_HASKELL__ >= 708 --- | Copy a slice of an immutable primitive array to an address. --- The offset and length are given in elements of type @a@. --- This function assumes that the 'Prim' instance of @a@ --- agrees with the 'Storable' instance. This function is only --- available when building with GHC 7.8 or newer. +-- | Copy a slice of an immutable primitive array to a pointer. +-- The offset and length are given in elements of type @a@. +-- This function assumes that the 'Prim' instance of @a@ +-- agrees with the 'Storable' instance. +-- +-- /Note:/ this function does not do bounds or overlap checking. copyPrimArrayToPtr :: forall m a. (PrimMonad m, Prim a) => Ptr a -- ^ destination pointer -> PrimArray a -- ^ source array -> Int -- ^ offset into source array - -> Int -- ^ number of prims to copy + -> Int -- ^ number of elements to copy -> m () {-# INLINE copyPrimArrayToPtr #-} copyPrimArrayToPtr (Ptr addr#) (PrimArray ba#) (I# soff#) (I# n#) = @@ -372,16 +408,17 @@ copyPrimArrayToPtr (Ptr addr#) (PrimArray ba#) (I# soff#) (I# n#) = in (# s'#, () #)) where siz# = sizeOf# (undefined :: a) --- | Copy a slice of an immutable primitive array to an address. --- The offset and length are given in elements of type @a@. --- This function assumes that the 'Prim' instance of @a@ --- agrees with the 'Storable' instance. This function is only --- available when building with GHC 7.8 or newer. +-- | Copy a slice of a mutable primitive array to a pointer. +-- The offset and length are given in elements of type @a@. +-- This function assumes that the 'Prim' instance of @a@ +-- agrees with the 'Storable' instance. +-- +-- /Note:/ this function does not do bounds or overlap checking. copyMutablePrimArrayToPtr :: forall m a. (PrimMonad m, Prim a) => Ptr a -- ^ destination pointer -> MutablePrimArray (PrimState m) a -- ^ source array -> Int -- ^ offset into source array - -> Int -- ^ number of prims to copy + -> Int -- ^ number of elements to copy -> m () {-# INLINE copyMutablePrimArrayToPtr #-} copyMutablePrimArrayToPtr (Ptr addr#) (MutablePrimArray mba#) (I# soff#) (I# n#) = @@ -389,9 +426,28 @@ copyMutablePrimArrayToPtr (Ptr addr#) (MutablePrimArray mba#) (I# soff#) (I# n#) let s'# = copyMutableByteArrayToAddr# mba# (soff# *# siz#) addr# (n# *# siz#) s# in (# s'#, () #)) where siz# = sizeOf# (undefined :: a) -#endif + +-- | Copy from a pointer to a mutable primitive array. +-- The offset and length are given in elements of type @a@. +-- This function assumes that the 'Prim' instance of @a@ +-- agrees with the 'Storable' instance. +-- +-- /Note:/ this function does not do bounds or overlap checking. +copyPtrToMutablePrimArray :: forall m a. (PrimMonad m, Prim a) + => MutablePrimArray (PrimState m) a -- ^ destination array + -> Int -- ^ destination offset + -> Ptr a -- ^ source pointer + -> Int -- ^ number of elements + -> m () +{-# INLINE copyPtrToMutablePrimArray #-} +copyPtrToMutablePrimArray (MutablePrimArray ba#) (I# doff#) (Ptr addr#) (I# n#) = + primitive_ (copyAddrToByteArray# addr# ba# (doff# *# siz#) (n# *# siz#)) + where + siz# = sizeOf# (undefined :: a) -- | Fill a slice of a mutable primitive array with a value. +-- +-- /Note:/ this function does not do bounds checking. setPrimArray :: (Prim a, PrimMonad m) => MutablePrimArray (PrimState m) a -- ^ array to fill @@ -424,8 +480,8 @@ getSizeofMutablePrimArray arr #endif -- | Size of the mutable primitive array in elements. This function shall not --- be used on primitive arrays that are an argument to or a result of --- 'resizeMutablePrimArray' or 'shrinkMutablePrimArray'. +-- be used on primitive arrays that are an argument to or a result of +-- 'resizeMutablePrimArray' or 'shrinkMutablePrimArray'. sizeofMutablePrimArray :: forall s a. Prim a => MutablePrimArray s a -> Int {-# INLINE sizeofMutablePrimArray #-} sizeofMutablePrimArray (MutablePrimArray arr#) = @@ -437,7 +493,49 @@ sameMutablePrimArray :: MutablePrimArray s a -> MutablePrimArray s a -> Bool sameMutablePrimArray (MutablePrimArray arr#) (MutablePrimArray brr#) = isTrue# (sameMutableByteArray# arr# brr#) --- | Convert a mutable byte array to an immutable one without copying. The +-- | Create an immutable copy of a slice of a primitive array. The offset and +-- length are given in elements. +-- +-- This operation makes a copy of the specified section, so it is safe to +-- continue using the mutable array afterward. +-- +-- /Note:/ The provided array should contain the full subrange +-- specified by the two Ints, but this is not checked. +freezePrimArray + :: (PrimMonad m, Prim a) + => MutablePrimArray (PrimState m) a -- ^ source + -> Int -- ^ offset in elements + -> Int -- ^ length in elements + -> m (PrimArray a) +{-# INLINE freezePrimArray #-} +freezePrimArray !src !off !len = do + dst <- newPrimArray len + copyMutablePrimArray dst 0 src off len + unsafeFreezePrimArray dst + +-- | Create a mutable primitive array from a slice of an immutable primitive array. +-- The offset and length are given in elements. +-- +-- This operation makes a copy of the specified slice, so it is safe to +-- use the immutable array afterward. +-- +-- /Note:/ The provided array should contain the full subrange +-- specified by the two Ints, but this is not checked. +-- +-- @since 0.7.2.0 +thawPrimArray + :: (PrimMonad m, Prim a) + => PrimArray a -- ^ source + -> Int -- ^ offset in elements + -> Int -- ^ length in elements + -> m (MutablePrimArray (PrimState m) a) +{-# INLINE thawPrimArray #-} +thawPrimArray !src !off !len = do + dst <- newPrimArray len + copyPrimArray dst 0 src off len + return dst + +-- | Convert a mutable primitive array to an immutable one without copying. The -- array should not be modified after the conversion. unsafeFreezePrimArray :: PrimMonad m => MutablePrimArray (PrimState m) a -> m (PrimArray a) @@ -455,6 +553,8 @@ unsafeThawPrimArray (PrimArray arr#) = primitive (\s# -> (# s#, MutablePrimArray (unsafeCoerce# arr#) #)) -- | Read a primitive value from the primitive array. +-- +-- /Note:/ this function does not do bounds checking. indexPrimArray :: forall a. Prim a => PrimArray a -> Int -> a {-# INLINE indexPrimArray #-} indexPrimArray (PrimArray arr#) (I# i#) = indexByteArray# arr# i# @@ -464,6 +564,26 @@ sizeofPrimArray :: forall a. Prim a => PrimArray a -> Int {-# INLINE sizeofPrimArray #-} sizeofPrimArray (PrimArray arr#) = I# (quotInt# (sizeofByteArray# arr#) (sizeOf# (undefined :: a))) +#if __GLASGOW_HASKELL__ >= 802 +-- | Check whether or not the primitive array is pinned. Pinned primitive arrays cannot +-- be moved by the garbage collector. It is safe to use 'primArrayContents' +-- on such arrays. This function is only available when compiling with +-- GHC 8.2 or newer. +-- +-- @since 0.7.1.0 +isPrimArrayPinned :: PrimArray a -> Bool +{-# INLINE isPrimArrayPinned #-} +isPrimArrayPinned (PrimArray arr#) = isTrue# (Exts.isByteArrayPinned# arr#) + +-- | Check whether or not the mutable primitive array is pinned. This function is +-- only available when compiling with GHC 8.2 or newer. +-- +-- @since 0.7.1.0 +isMutablePrimArrayPinned :: MutablePrimArray s a -> Bool +{-# INLINE isMutablePrimArrayPinned #-} +isMutablePrimArrayPinned (MutablePrimArray marr#) = isTrue# (Exts.isMutableByteArrayPinned# marr#) +#endif + -- | Lazy right-associated fold over the elements of a 'PrimArray'. {-# INLINE foldrPrimArray #-} foldrPrimArray :: forall a b. Prim a => (a -> b -> b) -> b -> PrimArray a -> b @@ -471,7 +591,7 @@ foldrPrimArray f z arr = go 0 where !sz = sizeofPrimArray arr go !i - | sz > i = f (indexPrimArray arr i) (go (i+1)) + | i < sz = f (indexPrimArray arr i) (go (i + 1)) | otherwise = z -- | Strict right-associated fold over the elements of a 'PrimArray'. @@ -559,7 +679,7 @@ traversePrimArrayP f arr = do unsafeFreezePrimArray marr -- | Filter the primitive array, keeping the elements for which the monadic --- predicate evaluates true. +-- predicate evaluates to true. {-# INLINE filterPrimArrayP #-} filterPrimArrayP :: (PrimMonad m, Prim a) => (a -> m Bool) @@ -642,7 +762,6 @@ replicatePrimArrayP sz f = do go 0 unsafeFreezePrimArray marr - -- | Map over the elements of a primitive array. {-# INLINE mapPrimArray #-} mapPrimArray :: (Prim a, Prim b) @@ -703,8 +822,8 @@ filterPrimArray p arr = runST $ do -- | Filter the primitive array, keeping the elements for which the monadic -- predicate evaluates true. -filterPrimArrayA :: - (Applicative f, Prim a) +filterPrimArrayA + :: (Applicative f, Prim a) => (a -> f Bool) -- ^ mapping function -> PrimArray a -- ^ primitive array -> f (PrimArray a) @@ -727,8 +846,8 @@ filterPrimArrayA f = \ !ary -> -- | Map over the primitive array, keeping the elements for which the applicative -- predicate provides a 'Just'. -mapMaybePrimArrayA :: - (Applicative f, Prim a, Prim b) +mapMaybePrimArrayA + :: (Applicative f, Prim a, Prim b) => (a -> f (Maybe b)) -- ^ mapping function -> PrimArray a -- ^ primitive array -> f (PrimArray b) @@ -772,7 +891,6 @@ mapMaybePrimArray p arr = runST $ do marr' <- resizeMutablePrimArray marr dstLen unsafeFreezePrimArray marr' - -- | Traverse a primitive array. The traversal performs all of the applicative -- effects /before/ forcing the resulting values and writing them to the new -- primitive array. Consequently: @@ -786,8 +904,8 @@ mapMaybePrimArray p arr = runST $ do -- The function 'traversePrimArrayP' always outperforms this function, but it -- requires a 'PrimMonad' constraint, and it forces the values as -- it performs the effects. -traversePrimArray :: - (Applicative f, Prim a, Prim b) +traversePrimArray + :: (Applicative f, Prim a, Prim b) => (a -> f b) -- ^ mapping function -> PrimArray a -- ^ primitive array -> f (PrimArray b) @@ -805,8 +923,8 @@ traversePrimArray f = \ !ary -> else runSTA len <$> go 0 -- | Traverse a primitive array with the index of each element. -itraversePrimArray :: - (Applicative f, Prim a, Prim b) +itraversePrimArray + :: (Applicative f, Prim a, Prim b) => (Int -> a -> f b) -> PrimArray a -> f (PrimArray b) @@ -873,8 +991,8 @@ replicatePrimArray len a = runST $ do -- | Generate a primitive array by evaluating the applicative generator -- function at each index. {-# INLINE generatePrimArrayA #-} -generatePrimArrayA :: - (Applicative f, Prim a) +generatePrimArrayA + :: (Applicative f, Prim a) => Int -- ^ length -> (Int -> f a) -- ^ element from index -> f (PrimArray a) @@ -891,10 +1009,10 @@ generatePrimArrayA len f = else runSTA len <$> go 0 -- | Execute the applicative action the given number of times and store the --- results in a vector. +-- results in a 'PrimArray'. {-# INLINE replicatePrimArrayA #-} -replicatePrimArrayA :: - (Applicative f, Prim a) +replicatePrimArrayA + :: (Applicative f, Prim a) => Int -- ^ length -> f a -- ^ applicative element producer -> f (PrimArray a) @@ -911,10 +1029,10 @@ replicatePrimArrayA len f = else runSTA len <$> go 0 -- | Traverse the primitive array, discarding the results. There --- is no 'PrimMonad' variant of this function since it would not provide +-- is no 'PrimMonad' variant of this function, since it would not provide -- any performance benefit. -traversePrimArray_ :: - (Applicative f, Prim a) +traversePrimArray_ + :: (Applicative f, Prim a) => (a -> f b) -> PrimArray a -> f () @@ -925,10 +1043,10 @@ traversePrimArray_ f a = go 0 where else pure () -- | Traverse the primitive array with the indices, discarding the results. --- There is no 'PrimMonad' variant of this function since it would not +-- There is no 'PrimMonad' variant of this function, since it would not -- provide any performance benefit. -itraversePrimArray_ :: - (Applicative f, Prim a) +itraversePrimArray_ + :: (Applicative f, Prim a) => (Int -> a -> f b) -> PrimArray a -> f () @@ -965,4 +1083,94 @@ The naming conventions adopted in this section are explained in the documentation of the @Data.Primitive@ module. -} +-- | Create a /pinned/ primitive array of the specified size (in elements). The garbage +-- collector is guaranteed not to move it. +-- +-- @since 0.7.1.0 +newPinnedPrimArray :: forall m a. (PrimMonad m, Prim a) + => Int -> m (MutablePrimArray (PrimState m) a) +{-# INLINE newPinnedPrimArray #-} +newPinnedPrimArray (I# n#) + = primitive (\s# -> case newPinnedByteArray# (n# *# sizeOf# (undefined :: a)) s# of + (# s'#, arr# #) -> (# s'#, MutablePrimArray arr# #)) + +-- | Create a /pinned/ primitive array of the specified size (in elements) and +-- with the alignment given by its 'Prim' instance. The garbage collector is +-- guaranteed not to move it. +-- +-- @since 0.7.0.0 +newAlignedPinnedPrimArray :: forall m a. (PrimMonad m, Prim a) + => Int -> m (MutablePrimArray (PrimState m) a) +{-# INLINE newAlignedPinnedPrimArray #-} +newAlignedPinnedPrimArray (I# n#) + = primitive (\s# -> case newAlignedPinnedByteArray# (n# *# sizeOf# (undefined :: a)) (alignment# (undefined :: a)) s# of + (# s'#, arr# #) -> (# s'#, MutablePrimArray arr# #)) + +-- | Yield a pointer to the array's data. This operation is only safe on +-- /pinned/ prim arrays allocated by 'newPinnedByteArray' or +-- 'newAlignedPinnedByteArray'. +-- +-- @since 0.7.1.0 +primArrayContents :: PrimArray a -> Ptr a +{-# INLINE primArrayContents #-} +primArrayContents (PrimArray arr#) = Ptr (byteArrayContents# arr#) + +-- | Yield a pointer to the array's data. This operation is only safe on +-- /pinned/ byte arrays allocated by 'newPinnedByteArray' or +-- 'newAlignedPinnedByteArray'. +-- +-- @since 0.7.1.0 +mutablePrimArrayContents :: MutablePrimArray s a -> Ptr a +{-# INLINE mutablePrimArrayContents #-} +mutablePrimArrayContents (MutablePrimArray arr#) + = Ptr (byteArrayContents# (unsafeCoerce# arr#)) + +-- | Return a newly allocated array with the specified subrange of the +-- provided array. The provided array should contain the full subrange +-- specified by the two Ints, but this is not checked. +clonePrimArray :: Prim a + => PrimArray a -- ^ source array + -> Int -- ^ offset into destination array + -> Int -- ^ number of elements to copy + -> PrimArray a +{-# INLINE clonePrimArray #-} +clonePrimArray src off n = runPrimArray $ do + dst <- newPrimArray n + copyPrimArray dst 0 src off n + return dst + +-- | Return a newly allocated mutable array with the specified subrange of +-- the provided mutable array. The provided mutable array should contain the +-- full subrange specified by the two Ints, but this is not checked. +cloneMutablePrimArray :: (PrimMonad m, Prim a) + => MutablePrimArray (PrimState m) a -- ^ source array + -> Int -- ^ offset into destination array + -> Int -- ^ number of elements to copy + -> m (MutablePrimArray (PrimState m) a) +{-# INLINE cloneMutablePrimArray #-} +cloneMutablePrimArray src off n = do + dst <- newPrimArray n + copyMutablePrimArray dst 0 src off n + return dst +-- | Execute the monadic action and freeze the resulting array. +-- +-- > runPrimArray m = runST $ m >>= unsafeFreezePrimArray +runPrimArray + :: (forall s. ST s (MutablePrimArray s a)) + -> PrimArray a +#if MIN_VERSION_base(4,10,0) /* In new GHCs, runRW# is available. */ +runPrimArray m = PrimArray (runPrimArray# m) + +runPrimArray# + :: (forall s. ST s (MutablePrimArray s a)) + -> ByteArray# +runPrimArray# m = case runRW# $ \s -> + case unST m s of { (# s', MutablePrimArray mary# #) -> + unsafeFreezeByteArray# mary# s'} of (# _, ary# #) -> ary# + +unST :: ST s a -> State# s -> (# State# s, a #) +unST (GHCST.ST f) = f +#else /* In older GHCs, runRW# is not available. */ +runPrimArray m = runST $ m >>= unsafeFreezePrimArray +#endif diff --git a/examples/primitive/Data/Primitive/PrimVar.hs b/examples/primitive/Data/Primitive/PrimVar.hs new file mode 100644 index 000000000..f2924a67f --- /dev/null +++ b/examples/primitive/Data/Primitive/PrimVar.hs @@ -0,0 +1,167 @@ +{-# LANGUAGE CPP #-} +{-# LANGUAGE MagicHash #-} +{-# LANGUAGE RoleAnnotations #-} +{-# LANGUAGE UnboxedTuples #-} +{-# LANGUAGE Unsafe #-} + +-- | Variant of @MutVar@ that has one less indirection for primitive types. +-- The difference is illustrated by comparing @MutVar Int@ and @PrimVar Int@: +-- +-- * @MutVar Int@: @MutVar# --> I#@ +-- * @PrimVar Int@: @MutableByteArray#@ +-- +-- This module is adapted from a module in Edward Kmett\'s @prim-ref@ library. +module Data.Primitive.PrimVar + ( + -- * Primitive References + PrimVar(..) + , newPrimVar + , newPinnedPrimVar + , newAlignedPinnedPrimVar + , readPrimVar + , writePrimVar + , modifyPrimVar + , primVarContents + , primVarToMutablePrimArray + -- * Atomic Operations + -- $atomic + , casInt + , fetchAddInt + , fetchSubInt + , fetchAndInt + , fetchNandInt + , fetchOrInt + , fetchXorInt + , atomicReadInt + , atomicWriteInt + ) where + +import Control.Monad.Primitive +import Data.Primitive +import GHC.Exts +import GHC.Ptr (castPtr) + +-------------------------------------------------------------------------------- +-- * Primitive References +-------------------------------------------------------------------------------- + +-- | A 'PrimVar' behaves like a single-element mutable primitive array. +newtype PrimVar s a = PrimVar (MutablePrimArray s a) + +type role PrimVar nominal nominal + +-- | Create a primitive reference. +newPrimVar :: (PrimMonad m, Prim a) => a -> m (PrimVar (PrimState m) a) +newPrimVar a = do + m <- newPrimArray 1 + writePrimArray m 0 a + return (PrimVar m) +{-# INLINE newPrimVar #-} + +-- | Create a pinned primitive reference. +newPinnedPrimVar :: (PrimMonad m, Prim a) => a -> m (PrimVar (PrimState m) a) +newPinnedPrimVar a = do + m <- newPinnedPrimArray 1 + writePrimArray m 0 a + return (PrimVar m) +{-# INLINE newPinnedPrimVar #-} + +-- | Create a pinned primitive reference with the appropriate alignment for its contents. +newAlignedPinnedPrimVar :: (PrimMonad m, Prim a) => a -> m (PrimVar (PrimState m) a) +newAlignedPinnedPrimVar a = do + m <- newAlignedPinnedPrimArray 1 + writePrimArray m 0 a + return (PrimVar m) +{-# INLINE newAlignedPinnedPrimVar #-} + +-- | Read a value from the 'PrimVar'. +readPrimVar :: (PrimMonad m, Prim a) => PrimVar (PrimState m) a -> m a +readPrimVar (PrimVar m) = readPrimArray m 0 +{-# INLINE readPrimVar #-} + +-- | Write a value to the 'PrimVar'. +writePrimVar :: (PrimMonad m, Prim a) => PrimVar (PrimState m) a -> a -> m () +writePrimVar (PrimVar m) a = writePrimArray m 0 a +{-# INLINE writePrimVar #-} + +-- | Mutate the contents of a 'PrimVar'. +modifyPrimVar :: (PrimMonad m, Prim a) => PrimVar (PrimState m) a -> (a -> a) -> m () +modifyPrimVar pv f = do + x <- readPrimVar pv + writePrimVar pv (f x) +{-# INLINE modifyPrimVar #-} + +instance Eq (PrimVar s a) where + PrimVar m == PrimVar n = sameMutablePrimArray m n + {-# INLINE (==) #-} + +-- | Yield a pointer to the data of a 'PrimVar'. This operation is only safe on pinned byte arrays allocated by +-- 'newPinnedPrimVar' or 'newAlignedPinnedPrimVar'. +primVarContents :: PrimVar s a -> Ptr a +primVarContents (PrimVar m) = castPtr $ mutablePrimArrayContents m +{-# INLINE primVarContents #-} + +-- | Convert a 'PrimVar' to a one-elment 'MutablePrimArray'. +primVarToMutablePrimArray :: PrimVar s a -> MutablePrimArray s a +primVarToMutablePrimArray (PrimVar m) = m +{-# INLINE primVarToMutablePrimArray #-} + +-------------------------------------------------------------------------------- +-- * Atomic Operations +-------------------------------------------------------------------------------- + +-- $atomic +-- Atomic operations on `PrimVar s Int`. All atomic operations imply a full memory barrier. + +-- | Given a primitive reference, the expected old value, and the new value, perform an atomic compare and swap i.e. write the new value if the current value matches the provided old value. Returns the value of the element before the operation. +casInt :: PrimMonad m => PrimVar (PrimState m) Int -> Int -> Int -> m Int +casInt (PrimVar (MutablePrimArray m)) (I# old) (I# new) = primitive $ \s -> case casIntArray# m 0# old new s of + (# s', result #) -> (# s', I# result #) +{-# INLINE casInt #-} + +-- | Given a reference, and a value to add, atomically add the value to the element. Returns the value of the element before the operation. +fetchAddInt :: PrimMonad m => PrimVar (PrimState m) Int -> Int -> m Int +fetchAddInt (PrimVar (MutablePrimArray m)) (I# x) = primitive $ \s -> case fetchAddIntArray# m 0# x s of + (# s', result #) -> (# s', I# result #) +{-# INLINE fetchAddInt #-} + +-- | Given a reference, and a value to subtract, atomically subtract the value from the element. Returns the value of the element before the operation. +fetchSubInt :: PrimMonad m => PrimVar (PrimState m) Int -> Int -> m Int +fetchSubInt (PrimVar (MutablePrimArray m)) (I# x) = primitive $ \s -> case fetchSubIntArray# m 0# x s of + (# s', result #) -> (# s', I# result #) +{-# INLINE fetchSubInt #-} + +-- | Given a reference, and a value to bitwise and, atomically and the value with the element. Returns the value of the element before the operation. +fetchAndInt :: PrimMonad m => PrimVar (PrimState m) Int -> Int -> m Int +fetchAndInt (PrimVar (MutablePrimArray m)) (I# x) = primitive $ \s -> case fetchAndIntArray# m 0# x s of + (# s', result #) -> (# s', I# result #) +{-# INLINE fetchAndInt #-} + +-- | Given a reference, and a value to bitwise nand, atomically nand the value with the element. Returns the value of the element before the operation. +fetchNandInt :: PrimMonad m => PrimVar (PrimState m) Int -> Int -> m Int +fetchNandInt (PrimVar (MutablePrimArray m)) (I# x) = primitive $ \s -> case fetchNandIntArray# m 0# x s of + (# s', result #) -> (# s', I# result #) +{-# INLINE fetchNandInt #-} + +-- | Given a reference, and a value to bitwise or, atomically or the value with the element. Returns the value of the element before the operation. +fetchOrInt :: PrimMonad m => PrimVar (PrimState m) Int -> Int -> m Int +fetchOrInt (PrimVar (MutablePrimArray m)) (I# x) = primitive $ \s -> case fetchOrIntArray# m 0# x s of + (# s', result #) -> (# s', I# result #) +{-# INLINE fetchOrInt #-} + +-- | Given a reference, and a value to bitwise xor, atomically xor the value with the element. Returns the value of the element before the operation. +fetchXorInt :: PrimMonad m => PrimVar (PrimState m) Int -> Int -> m Int +fetchXorInt (PrimVar (MutablePrimArray m)) (I# x) = primitive $ \s -> case fetchXorIntArray# m 0# x s of + (# s', result #) -> (# s', I# result #) +{-# INLINE fetchXorInt #-} + +-- | Given a reference, atomically read an element. +atomicReadInt :: PrimMonad m => PrimVar (PrimState m) Int -> m Int +atomicReadInt (PrimVar (MutablePrimArray m)) = primitive $ \s -> case atomicReadIntArray# m 0# s of + (# s', result #) -> (# s', I# result #) +{-# INLINE atomicReadInt #-} + +-- | Given a reference, atomically write an element. +atomicWriteInt :: PrimMonad m => PrimVar (PrimState m) Int -> Int -> m () +atomicWriteInt (PrimVar (MutablePrimArray m)) (I# x) = primitive_ $ \s -> atomicWriteIntArray# m 0# x s +{-# INLINE atomicWriteInt #-} diff --git a/examples/primitive/Data/Primitive/Ptr.hs b/examples/primitive/Data/Primitive/Ptr.hs index bb3aeef6e..07616e972 100644 --- a/examples/primitive/Data/Primitive/Ptr.hs +++ b/examples/primitive/Data/Primitive/Ptr.hs @@ -11,7 +11,7 @@ -- Maintainer : Roman Leshchinskiy -- Portability : non-portable -- --- Primitive operations on machine addresses +-- Primitive operations on machine addresses. -- -- @since 0.6.4.0 @@ -28,20 +28,16 @@ module Data.Primitive.Ptr ( -- * Block operations copyPtr, movePtr, setPtr -#if __GLASGOW_HASKELL__ >= 708 , copyPtrToMutablePrimArray -#endif + , copyPtrToMutableByteArray ) where import Control.Monad.Primitive import Data.Primitive.Types -#if __GLASGOW_HASKELL__ >= 708 -import Data.Primitive.PrimArray (MutablePrimArray(..)) -#endif +import Data.Primitive.PrimArray (copyPtrToMutablePrimArray) +import Data.Primitive.ByteArray (copyPtrToMutableByteArray) -import GHC.Base ( Int(..) ) import GHC.Exts - import GHC.Ptr import Foreign.Marshal.Utils @@ -52,8 +48,8 @@ advancePtr :: forall a. Prim a => Ptr a -> Int -> Ptr a advancePtr (Ptr a#) (I# i#) = Ptr (plusAddr# a# (i# *# sizeOf# (undefined :: a))) -- | Subtract a pointer from another pointer. The result represents --- the number of elements of type @a@ that fit in the contiguous --- memory range bounded by these two pointers. +-- the number of elements of type @a@ that fit in the contiguous +-- memory range bounded by these two pointers. subtractPtr :: forall a. Prim a => Ptr a -> Ptr a -> Int {-# INLINE subtractPtr #-} subtractPtr (Ptr a#) (Ptr b#) = I# (quotInt# (minusAddr# a# b#) (sizeOf# (undefined :: a))) @@ -91,8 +87,8 @@ copyPtr (Ptr dst#) (Ptr src#) n -- | Copy the given number of elements from the second 'Ptr' to the first. The -- areas may overlap. movePtr :: forall m a. (PrimMonad m, Prim a) - => Ptr a -- ^ destination address - -> Ptr a -- ^ source address + => Ptr a -- ^ destination pointer + -> Ptr a -- ^ source pointer -> Int -- ^ number of elements -> m () {-# INLINE movePtr #-} @@ -104,22 +100,3 @@ movePtr (Ptr dst#) (Ptr src#) n setPtr :: (Prim a, PrimMonad m) => Ptr a -> Int -> a -> m () {-# INLINE setPtr #-} setPtr (Ptr addr#) (I# n#) x = primitive_ (setOffAddr# addr# 0# n# x) - - -#if __GLASGOW_HASKELL__ >= 708 --- | Copy from a pointer to a mutable primitive array. --- The offset and length are given in elements of type @a@. --- This function is only available when building with GHC 7.8 --- or newer. -copyPtrToMutablePrimArray :: forall m a. (PrimMonad m, Prim a) - => MutablePrimArray (PrimState m) a -- ^ destination array - -> Int -- ^ destination offset - -> Ptr a -- ^ source pointer - -> Int -- ^ number of elements - -> m () -{-# INLINE copyPtrToMutablePrimArray #-} -copyPtrToMutablePrimArray (MutablePrimArray ba#) (I# doff#) (Ptr addr#) (I# n#) = - primitive_ (copyAddrToByteArray# addr# ba# (doff# *# siz#) (n# *# siz#)) - where - siz# = sizeOf# (undefined :: a) -#endif diff --git a/examples/primitive/Data/Primitive/SmallArray.hs b/examples/primitive/Data/Primitive/SmallArray.hs index 7e0eb413d..a4e9e4ec1 100644 --- a/examples/primitive/Data/Primitive/SmallArray.hs +++ b/examples/primitive/Data/Primitive/SmallArray.hs @@ -7,6 +7,7 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE BangPatterns #-} +{-# LANGUAGE TemplateHaskellQuotes #-} -- | -- Module : Data.Primitive.SmallArray @@ -18,7 +19,7 @@ -- -- Small arrays are boxed (im)mutable arrays. -- --- The underlying structure of the 'Array' type contains a card table, allowing +-- The underlying structure of the 'Data.Primitive.Array.Array' type contains a card table, allowing -- segments of the array to be marked as having been mutated. This allows the -- garbage collector to only re-traverse segments of the array that have been -- marked during certain phases, rather than having to traverse the entire @@ -30,11 +31,8 @@ -- entire array. These advantages make them suitable for use as arrays that are -- known to be small. -- --- The card size is 128, so for uses much larger than that, 'Array' would likely --- be superior. --- --- The underlying type, 'SmallArray#', was introduced in GHC 7.10, so prior to --- that version, this module simply implements small arrays as 'Array'. +-- The card size is 128, so for uses much larger than that, +-- 'Data.Primitive.Array.Array' would likely be superior. module Data.Primitive.SmallArray ( SmallArray(..) @@ -52,27 +50,27 @@ module Data.Primitive.SmallArray , freezeSmallArray , unsafeFreezeSmallArray , thawSmallArray - , runSmallArray , unsafeThawSmallArray + , runSmallArray + , createSmallArray , sizeofSmallArray , sizeofSmallMutableArray +#if MIN_VERSION_base(4,14,0) + , shrinkSmallMutableArray + , resizeSmallMutableArray +#endif + , emptySmallArray , smallArrayFromList , smallArrayFromListN , mapSmallArray' , traverseSmallArrayP ) where - -#if (__GLASGOW_HASKELL__ >= 710) -#define HAVE_SMALL_ARRAY 1 -#endif - -#if MIN_VERSION_base(4,7,0) import GHC.Exts hiding (toList) import qualified GHC.Exts -#endif import Control.Applicative +import Control.DeepSeq import Control.Monad import qualified Control.Monad.Fail as Fail import Control.Monad.Fix @@ -82,117 +80,96 @@ import Control.Monad.Zip import Data.Data import Data.Foldable as Foldable import Data.Functor.Identity -#if !(MIN_VERSION_base(4,10,0)) -import Data.Monoid -#endif -#if MIN_VERSION_base(4,9,0) import qualified GHC.ST as GHCST import qualified Data.Semigroup as Sem -#endif import Text.ParserCombinators.ReadP -#if MIN_VERSION_base(4,10,0) -import GHC.Exts (runRW#) -#elif MIN_VERSION_base(4,9,0) +#if !MIN_VERSION_base(4,10,0) import GHC.Base (runRW#) #endif -#if !(HAVE_SMALL_ARRAY) -import Data.Primitive.Array -import Data.Traversable -import qualified Data.Primitive.Array as Array -#endif +import Data.Functor.Classes (Eq1(..), Ord1(..), Show1(..), Read1(..)) +import Language.Haskell.TH.Syntax (Lift(..)) -#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,4,0) -import Data.Functor.Classes (Eq1(..),Ord1(..),Show1(..),Read1(..)) -#endif - -#if HAVE_SMALL_ARRAY data SmallArray a = SmallArray (SmallArray# a) deriving Typeable -#else -newtype SmallArray a = SmallArray (Array a) deriving - ( Eq - , Ord - , Show - , Read - , Foldable - , Traversable - , Functor - , Applicative - , Alternative - , Monad - , MonadPlus - , MonadZip - , MonadFix - , Monoid - , Typeable -#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,4,0) - , Eq1 - , Ord1 - , Show1 - , Read1 -#endif - ) -#if MIN_VERSION_base(4,7,0) -instance IsList (SmallArray a) where - type Item (SmallArray a) = a - fromListN n l = SmallArray (fromListN n l) - fromList l = SmallArray (fromList l) - toList a = Foldable.toList a -#endif +#if MIN_VERSION_deepseq(1,4,3) +instance NFData1 SmallArray where + liftRnf r = foldl' (\_ -> r) () #endif -#if HAVE_SMALL_ARRAY +instance NFData a => NFData (SmallArray a) where + rnf = foldl' (\_ -> rnf) () + data SmallMutableArray s a = SmallMutableArray (SmallMutableArray# s a) deriving Typeable + +instance Lift a => Lift (SmallArray a) where +#if MIN_VERSION_template_haskell(2,16,0) + liftTyped ary = case lst of + [] -> [|| SmallArray (emptySmallArray# (##)) ||] + [x] -> [|| pure $! x ||] + x : xs -> [|| unsafeSmallArrayFromListN' len x xs ||] #else -newtype SmallMutableArray s a = SmallMutableArray (MutableArray s a) - deriving (Eq, Typeable) + lift ary = case lst of + [] -> [| SmallArray (emptySmallArray# (##)) |] + [x] -> [| pure $! x |] + x : xs -> [| unsafeSmallArrayFromListN' len x xs |] #endif + where + len = length ary + lst = toList ary + +-- | Strictly create an array from a nonempty list (represented as +-- a first element and a list of the rest) of a known length. If the length +-- of the list does not match the given length, this makes demons fly +-- out of your nose. We use it in the 'Lift' instance. If you edit the +-- splice and break it, you get to keep both pieces. +unsafeSmallArrayFromListN' :: Int -> a -> [a] -> SmallArray a +unsafeSmallArrayFromListN' n y ys = + createSmallArray n y $ \sma -> + let go !_ix [] = return () + go !ix (!x : xs) = do + writeSmallArray sma ix x + go (ix+1) xs + in go 1 ys -- | Create a new small mutable array. +-- +-- /Note:/ this function does not check if the input is non-negative. newSmallArray :: PrimMonad m => Int -- ^ size -> a -- ^ initial contents -> m (SmallMutableArray (PrimState m) a) -#if HAVE_SMALL_ARRAY newSmallArray (I# i#) x = primitive $ \s -> case newSmallArray# i# x s of (# s', sma# #) -> (# s', SmallMutableArray sma# #) -#else -newSmallArray n e = SmallMutableArray `liftM` newArray n e -#endif {-# INLINE newSmallArray #-} -- | Read the element at a given index in a mutable array. +-- +-- /Note:/ this function does not do bounds checking. readSmallArray :: PrimMonad m => SmallMutableArray (PrimState m) a -- ^ array -> Int -- ^ index -> m a -#if HAVE_SMALL_ARRAY readSmallArray (SmallMutableArray sma#) (I# i#) = primitive $ readSmallArray# sma# i# -#else -readSmallArray (SmallMutableArray a) = readArray a -#endif {-# INLINE readSmallArray #-} -- | Write an element at the given idex in a mutable array. +-- +-- /Note:/ this function does not do bounds checking. writeSmallArray :: PrimMonad m => SmallMutableArray (PrimState m) a -- ^ array -> Int -- ^ index -> a -- ^ new element -> m () -#if HAVE_SMALL_ARRAY writeSmallArray (SmallMutableArray sma#) (I# i#) x = primitive_ $ writeSmallArray# sma# i# x -#else -writeSmallArray (SmallMutableArray a) = writeArray a -#endif {-# INLINE writeSmallArray #-} -- | Look up an element in an immutable array. @@ -214,95 +191,84 @@ writeSmallArray (SmallMutableArray a) = writeArray a -- -- > let x = indexSmallArray sa 0 -- --- And does not prevent 'sa' from being garbage collected. +-- It also does not prevent 'sa' from being garbage collected. -- -- Note that 'Identity' is not adequate for this use, as it is a newtype, and -- cannot be evaluated without evaluating the element. +-- +-- /Note:/ this function does not do bounds checking. indexSmallArrayM :: Monad m => SmallArray a -- ^ array -> Int -- ^ index -> m a -#if HAVE_SMALL_ARRAY indexSmallArrayM (SmallArray sa#) (I# i#) = case indexSmallArray# sa# i# of (# x #) -> pure x -#else -indexSmallArrayM (SmallArray a) = indexArrayM a -#endif {-# INLINE indexSmallArrayM #-} -- | Look up an element in an immutable array. +-- +-- /Note:/ this function does not do bounds checking. indexSmallArray :: SmallArray a -- ^ array -> Int -- ^ index -> a -#if HAVE_SMALL_ARRAY indexSmallArray sa i = runIdentity $ indexSmallArrayM sa i -#else -indexSmallArray (SmallArray a) = indexArray a -#endif {-# INLINE indexSmallArray #-} -- | Read a value from the immutable array at the given index, returning -- the result in an unboxed unary tuple. This is currently used to implement -- folds. +-- +-- /Note:/ this function does not do bounds checking. indexSmallArray## :: SmallArray a -> Int -> (# a #) -#if HAVE_SMALL_ARRAY indexSmallArray## (SmallArray ary) (I# i) = indexSmallArray# ary i -#else -indexSmallArray## (SmallArray a) = indexArray## a -#endif {-# INLINE indexSmallArray## #-} -- | Create a copy of a slice of an immutable array. +-- +-- /Note:/ The provided array should contain the full subrange +-- specified by the two Ints, but this is not checked. cloneSmallArray :: SmallArray a -- ^ source -> Int -- ^ offset -> Int -- ^ length -> SmallArray a -#if HAVE_SMALL_ARRAY cloneSmallArray (SmallArray sa#) (I# i#) (I# j#) = SmallArray (cloneSmallArray# sa# i# j#) -#else -cloneSmallArray (SmallArray a) i j = SmallArray $ cloneArray a i j -#endif {-# INLINE cloneSmallArray #-} -- | Create a copy of a slice of a mutable array. +-- +-- /Note:/ The provided array should contain the full subrange +-- specified by the two Ints, but this is not checked. cloneSmallMutableArray :: PrimMonad m => SmallMutableArray (PrimState m) a -- ^ source -> Int -- ^ offset -> Int -- ^ length -> m (SmallMutableArray (PrimState m) a) -#if HAVE_SMALL_ARRAY cloneSmallMutableArray (SmallMutableArray sma#) (I# o#) (I# l#) = primitive $ \s -> case cloneSmallMutableArray# sma# o# l# s of (# s', smb# #) -> (# s', SmallMutableArray smb# #) -#else -cloneSmallMutableArray (SmallMutableArray ma) i j = - SmallMutableArray `liftM` cloneMutableArray ma i j -#endif {-# INLINE cloneSmallMutableArray #-} -- | Create an immutable array corresponding to a slice of a mutable array. -- -- This operation copies the portion of the array to be frozen. +-- +-- /Note:/ The provided array should contain the full subrange +-- specified by the two Ints, but this is not checked. freezeSmallArray :: PrimMonad m => SmallMutableArray (PrimState m) a -- ^ source -> Int -- ^ offset -> Int -- ^ length -> m (SmallArray a) -#if HAVE_SMALL_ARRAY freezeSmallArray (SmallMutableArray sma#) (I# i#) (I# j#) = primitive $ \s -> case freezeSmallArray# sma# i# j# s of (# s', sa# #) -> (# s', SmallArray sa# #) -#else -freezeSmallArray (SmallMutableArray ma) i j = - SmallArray `liftM` freezeArray ma i j -#endif {-# INLINE freezeSmallArray #-} -- | Render a mutable array immutable. @@ -311,33 +277,26 @@ freezeSmallArray (SmallMutableArray ma) i j = -- input array after freezing. unsafeFreezeSmallArray :: PrimMonad m => SmallMutableArray (PrimState m) a -> m (SmallArray a) -#if HAVE_SMALL_ARRAY unsafeFreezeSmallArray (SmallMutableArray sma#) = primitive $ \s -> case unsafeFreezeSmallArray# sma# s of (# s', sa# #) -> (# s', SmallArray sa# #) -#else -unsafeFreezeSmallArray (SmallMutableArray ma) = - SmallArray `liftM` unsafeFreezeArray ma -#endif {-# INLINE unsafeFreezeSmallArray #-} -- | Create a mutable array corresponding to a slice of an immutable array. -- -- This operation copies the portion of the array to be thawed. +-- +-- /Note:/ The provided array should contain the full subrange +-- specified by the two Ints, but this is not checked. thawSmallArray :: PrimMonad m => SmallArray a -- ^ source -> Int -- ^ offset -> Int -- ^ length -> m (SmallMutableArray (PrimState m) a) -#if HAVE_SMALL_ARRAY thawSmallArray (SmallArray sa#) (I# o#) (I# l#) = primitive $ \s -> case thawSmallArray# sa# o# l# s of (# s', sma# #) -> (# s', SmallMutableArray sma# #) -#else -thawSmallArray (SmallArray a) off len = - SmallMutableArray `liftM` thawArray a off len -#endif {-# INLINE thawSmallArray #-} -- | Render an immutable array mutable. @@ -345,16 +304,14 @@ thawSmallArray (SmallArray a) off len = -- This operation performs no copying, so care must be taken with its use. unsafeThawSmallArray :: PrimMonad m => SmallArray a -> m (SmallMutableArray (PrimState m) a) -#if HAVE_SMALL_ARRAY unsafeThawSmallArray (SmallArray sa#) = primitive $ \s -> case unsafeThawSmallArray# sa# s of (# s', sma# #) -> (# s', SmallMutableArray sma# #) -#else -unsafeThawSmallArray (SmallArray a) = SmallMutableArray `liftM` unsafeThawArray a -#endif {-# INLINE unsafeThawSmallArray #-} -- | Copy a slice of an immutable array into a mutable array. +-- +-- /Note:/ this function does not do bounds or overlap checking. copySmallArray :: PrimMonad m => SmallMutableArray (PrimState m) a -- ^ destination @@ -363,16 +320,14 @@ copySmallArray -> Int -- ^ source offset -> Int -- ^ length -> m () -#if HAVE_SMALL_ARRAY copySmallArray (SmallMutableArray dst#) (I# do#) (SmallArray src#) (I# so#) (I# l#) = primitive_ $ copySmallArray# src# so# dst# do# l# -#else -copySmallArray (SmallMutableArray dst) i (SmallArray src) = copyArray dst i src -#endif {-# INLINE copySmallArray #-} -- | Copy a slice of one mutable array into another. +-- +-- /Note:/ this function does not do bounds or overlap checking. copySmallMutableArray :: PrimMonad m => SmallMutableArray (PrimState m) a -- ^ destination @@ -381,46 +336,34 @@ copySmallMutableArray -> Int -- ^ source offset -> Int -- ^ length -> m () -#if HAVE_SMALL_ARRAY copySmallMutableArray (SmallMutableArray dst#) (I# do#) (SmallMutableArray src#) (I# so#) (I# l#) = primitive_ $ copySmallMutableArray# src# so# dst# do# l# -#else -copySmallMutableArray (SmallMutableArray dst) i (SmallMutableArray src) = - copyMutableArray dst i src -#endif {-# INLINE copySmallMutableArray #-} +-- | The number of elements in an immutable array. sizeofSmallArray :: SmallArray a -> Int -#if HAVE_SMALL_ARRAY sizeofSmallArray (SmallArray sa#) = I# (sizeofSmallArray# sa#) -#else -sizeofSmallArray (SmallArray a) = sizeofArray a -#endif {-# INLINE sizeofSmallArray #-} +-- | The number of elements in a mutable array. sizeofSmallMutableArray :: SmallMutableArray s a -> Int -#if HAVE_SMALL_ARRAY sizeofSmallMutableArray (SmallMutableArray sa#) = I# (sizeofSmallMutableArray# sa#) -#else -sizeofSmallMutableArray (SmallMutableArray ma) = sizeofMutableArray ma -#endif {-# INLINE sizeofSmallMutableArray #-} -- | This is the fastest, most straightforward way to traverse -- an array, but it only works correctly with a sufficiently -- "affine" 'PrimMonad' instance. In particular, it must only produce --- *one* result array. 'Control.Monad.Trans.List.ListT'-transformed +-- /one/ result array. 'Control.Monad.Trans.List.ListT'-transformed -- monads, for example, will not work right at all. traverseSmallArrayP :: PrimMonad m => (a -> m b) -> SmallArray a -> m (SmallArray b) -#if HAVE_SMALL_ARRAY traverseSmallArrayP f = \ !ary -> let !sz = sizeofSmallArray ary @@ -436,39 +379,24 @@ traverseSmallArrayP f = \ !ary -> in do mary <- newSmallArray sz badTraverseValue go 0 mary -#else -traverseSmallArrayP f (SmallArray ar) = SmallArray `liftM` traverseArrayP f ar -#endif {-# INLINE traverseSmallArrayP #-} -- | Strict map over the elements of the array. mapSmallArray' :: (a -> b) -> SmallArray a -> SmallArray b -#if HAVE_SMALL_ARRAY mapSmallArray' f sa = createSmallArray (length sa) (die "mapSmallArray'" "impossible") $ \smb -> fix ? 0 $ \go i -> when (i < length sa) $ do x <- indexSmallArrayM sa i let !y = f x - writeSmallArray smb i y *> go (i+1) -#else -mapSmallArray' f (SmallArray ar) = SmallArray (mapArray' f ar) -#endif + writeSmallArray smb i y *> go (i + 1) {-# INLINE mapSmallArray' #-} -#ifndef HAVE_SMALL_ARRAY -runSmallArray - :: (forall s. ST s (SmallMutableArray s a)) - -> SmallArray a -runSmallArray m = SmallArray $ runArray $ - m >>= \(SmallMutableArray mary) -> return mary - -#elif !MIN_VERSION_base(4,9,0) +-- | Execute the monadic action and freeze the resulting array. +-- +-- > runSmallArray m = runST $ m >>= unsafeFreezeSmallArray runSmallArray :: (forall s. ST s (SmallMutableArray s a)) -> SmallArray a -runSmallArray m = runST $ m >>= unsafeFreezeSmallArray - -#else -- This low-level business is designed to work with GHC's worker-wrapper -- transformation. A lot of the time, we don't actually need an Array -- constructor. By putting it on the outside, and being careful about @@ -476,9 +404,6 @@ runSmallArray m = runST $ m >>= unsafeFreezeSmallArray -- The only downside is that separately created 0-length arrays won't share -- their Array constructors, although they'll share their underlying -- Array#s. -runSmallArray - :: (forall s. ST s (SmallMutableArray s a)) - -> SmallArray a runSmallArray m = SmallArray (runSmallArray# m) runSmallArray# @@ -491,15 +416,21 @@ runSmallArray# m = case runRW# $ \s -> unST :: ST s a -> State# s -> (# State# s, a #) unST (GHCST.ST f) = f -#endif - -#if HAVE_SMALL_ARRAY --- See the comment on runSmallArray for why we use emptySmallArray#. +-- | Create an array of the given size with a default value, +-- apply the monadic function and freeze the result. If the +-- size is 0, return 'emptySmallArray' (rather than a new copy thereof). +-- +-- > createSmallArray 0 _ _ = emptySmallArray +-- > createSmallArray n x f = runSmallArray $ do +-- > mary <- newSmallArray n x +-- > f mary +-- > pure mary createSmallArray :: Int -> a -> (forall s. SmallMutableArray s a -> ST s ()) -> SmallArray a +-- See the comment on runSmallArray for why we use emptySmallArray#. createSmallArray 0 _ _ = SmallArray (emptySmallArray# (# #)) createSmallArray n x f = runSmallArray $ do mary <- newSmallArray n x @@ -513,6 +444,7 @@ emptySmallArray# _ = case emptySmallArray of SmallArray ar -> ar die :: String -> String -> a die fun problem = error $ "Data.Primitive.SmallArray." ++ fun ++ ": " ++ problem +-- | The empty 'SmallArray'. emptySmallArray :: SmallArray a emptySmallArray = runST $ newSmallArray 0 (die "emptySmallArray" "impossible") @@ -536,17 +468,11 @@ smallArrayLiftEq p sa1 sa2 = length sa1 == length sa2 && loop (length sa1 - 1) = True | (# x #) <- indexSmallArray## sa1 i , (# y #) <- indexSmallArray## sa2 i - = p x y && loop (i-1) + = p x y && loop (i - 1) -#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,4,0) -- | @since 0.6.4.0 instance Eq1 SmallArray where -#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,5,0) liftEq = smallArrayLiftEq -#else - eq1 = smallArrayLiftEq (==) -#endif -#endif instance Eq a => Eq (SmallArray a) where sa1 == sa2 = smallArrayLiftEq (==) sa1 sa2 @@ -563,18 +489,12 @@ smallArrayLiftCompare elemCompare a1 a2 = loop 0 | i < mn , (# x1 #) <- indexSmallArray## a1 i , (# x2 #) <- indexSmallArray## a2 i - = elemCompare x1 x2 `mappend` loop (i+1) + = elemCompare x1 x2 `mappend` loop (i + 1) | otherwise = compare (length a1) (length a2) -#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,4,0) -- | @since 0.6.4.0 instance Ord1 SmallArray where -#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,5,0) liftCompare = smallArrayLiftCompare -#else - compare1 = smallArrayLiftCompare compare -#endif -#endif -- | Lexicographic ordering. Subject to change between major versions. instance Ord a => Ord (SmallArray a) where @@ -590,7 +510,7 @@ instance Foldable SmallArray where go i | i == sz = z | (# x #) <- indexSmallArray## ary i - = f x (go (i+1)) + = f x (go (i + 1)) in go 0 {-# INLINE foldr #-} foldl f = \z !ary -> @@ -598,7 +518,7 @@ instance Foldable SmallArray where go i | i < 0 = z | (# x #) <- indexSmallArray## ary i - = f (go (i-1)) x + = f (go (i - 1)) x in go (sizeofSmallArray ary - 1) {-# INLINE foldl #-} foldr1 f = \ !ary -> @@ -607,7 +527,7 @@ instance Foldable SmallArray where go i = case indexSmallArray## ary i of (# x #) | i == sz -> x - | otherwise -> f x (go (i+1)) + | otherwise -> f x (go (i + 1)) in if sz < 0 then die "foldr1" "Empty SmallArray" else go 0 @@ -628,7 +548,7 @@ instance Foldable SmallArray where go i !acc | i == -1 = acc | (# x #) <- indexSmallArray## ary i - = go (i-1) (f x acc) + = go (i - 1) (f x acc) in go (sizeofSmallArray ary - 1) z {-# INLINE foldr' #-} foldl' f = \z !ary -> @@ -637,7 +557,7 @@ instance Foldable SmallArray where go i !acc | i == sz = acc | (# x #) <- indexSmallArray## ary i - = go (i+1) (f acc x) + = go (i + 1) (f acc x) in go 0 z {-# INLINE foldl' #-} null a = sizeofSmallArray a == 0 @@ -652,7 +572,7 @@ instance Foldable SmallArray where go i !e | i == sz = e | (# x #) <- indexSmallArray## ary i - = go (i+1) (max e x) + = go (i + 1) (max e x) {-# INLINE maximum #-} minimum ary | sz == 0 = die "minimum" "Empty SmallArray" | (# frst #) <- indexSmallArray## ary 0 @@ -661,14 +581,14 @@ instance Foldable SmallArray where go i !e | i == sz = e | (# x #) <- indexSmallArray## ary i - = go (i+1) (min e x) + = go (i + 1) (min e x) {-# INLINE minimum #-} sum = foldl' (+) 0 {-# INLINE sum #-} product = foldl' (*) 1 {-# INLINE product #-} -newtype STA a = STA {_runSTA :: forall s. SmallMutableArray# s a -> ST s (SmallArray a)} +newtype STA a = STA { _runSTA :: forall s. SmallMutableArray# s a -> ST s (SmallArray a) } runSTA :: Int -> STA a -> SmallArray a runSTA !sz = \ (STA m) -> runST $ newSmallArray_ sz >>= @@ -700,8 +620,8 @@ traverseSmallArray f = \ !ary -> writeSmallArray (SmallMutableArray mary) i b >> m mary) (f x) (go (i + 1)) in if len == 0 - then pure emptySmallArray - else runSTA len <$> go 0 + then pure emptySmallArray + else runSTA len <$> go 0 {-# INLINE [1] traverseSmallArray #-} {-# RULES @@ -718,7 +638,7 @@ instance Functor SmallArray where fix ? 0 $ \go i -> when (i < length sa) $ do x <- indexSmallArrayM sa i - writeSmallArray smb i (f x) *> go (i+1) + writeSmallArray smb i (f x) *> go (i + 1) {-# INLINE fmap #-} x <$ sa = createSmallArray (length sa) x noOp @@ -726,36 +646,36 @@ instance Functor SmallArray where instance Applicative SmallArray where pure x = createSmallArray 1 x noOp - sa *> sb = createSmallArray (la*lb) (die "*>" "impossible") $ \smb -> + sa *> sb = createSmallArray (la * lb) (die "*>" "impossible") $ \smb -> fix ? 0 $ \go i -> when (i < la) $ - copySmallArray smb 0 sb 0 lb *> go (i+1) + copySmallArray smb (i * lb) sb 0 lb *> go (i + 1) where - la = length sa ; lb = length sb + la = length sa; lb = length sb - a <* b = createSmallArray (sza*szb) (die "<*" "impossible") $ \ma -> + a <* b = createSmallArray (sza * szb) (die "<*" "impossible") $ \ma -> let fill off i e = when (i < szb) $ - writeSmallArray ma (off+i) e >> fill off (i+1) e + writeSmallArray ma (off + i) e >> fill off (i + 1) e go i = when (i < sza) $ do x <- indexSmallArrayM a i - fill (i*szb) 0 x - go (i+1) + fill (i * szb) 0 x + go (i + 1) in go 0 - where sza = sizeofSmallArray a ; szb = sizeofSmallArray b + where sza = sizeofSmallArray a; szb = sizeofSmallArray b - ab <*> a = createSmallArray (szab*sza) (die "<*>" "impossible") $ \mb -> + ab <*> a = createSmallArray (szab * sza) (die "<*>" "impossible") $ \mb -> let go1 i = when (i < szab) $ do f <- indexSmallArrayM ab i - go2 (i*sza) f 0 - go1 (i+1) + go2 (i * sza) f 0 + go1 (i + 1) go2 off f j = when (j < sza) $ do x <- indexSmallArrayM a j writeSmallArray mb (off + j) (f x) go2 off f (j + 1) in go1 0 - where szab = sizeofSmallArray ab ; sza = sizeofSmallArray a + where szab = sizeofSmallArray ab; sza = sizeofSmallArray a instance Alternative SmallArray where empty = emptySmallArray @@ -789,25 +709,25 @@ instance Monad SmallArray where return = pure (>>) = (*>) - sa >>= f = collect 0 EmptyStack (la-1) + sa >>= f = collect 0 EmptyStack (la - 1) where - la = length sa - collect sz stk i - | i < 0 = createSmallArray sz (die ">>=" "impossible") $ fill 0 stk - | (# x #) <- indexSmallArray## sa i - , let sb = f x - lsb = length sb - -- If we don't perform this check, we could end up allocating - -- a stack full of empty arrays if someone is filtering most - -- things out. So we refrain from pushing empty arrays. - = if lsb == 0 - then collect sz stk (i-1) - else collect (sz + lsb) (PushArray sb stk) (i-1) - - fill _ EmptyStack _ = return () - fill off (PushArray sb sbs) smb = - copySmallArray smb off sb 0 (length sb) - *> fill (off + length sb) sbs smb + la = length sa + collect sz stk i + | i < 0 = createSmallArray sz (die ">>=" "impossible") $ fill 0 stk + | (# x #) <- indexSmallArray## sa i + , let sb = f x + lsb = length sb + -- If we don't perform this check, we could end up allocating + -- a stack full of empty arrays if someone is filtering most + -- things out. So we refrain from pushing empty arrays. + = if lsb == 0 + then collect sz stk (i - 1) + else collect (sz + lsb) (PushArray sb stk) (i - 1) + + fill _ EmptyStack _ = return () + fill off (PushArray sb sbs) smb = + copySmallArray smb off sb 0 (length sb) + *> fill (off + length sb) sbs smb #if !(MIN_VERSION_base(4,13,0)) fail = Fail.fail @@ -827,7 +747,7 @@ zipW nm = \f sa sb -> let mn = length sa `min` length sb in x <- indexSmallArrayM sa i y <- indexSmallArrayM sb i writeSmallArray mc i (f x y) - go (i+1) + go (i + 1) {-# INLINE zipW #-} instance MonadZip SmallArray where @@ -842,13 +762,13 @@ instance MonadZip SmallArray where when (i < sz) $ case indexSmallArray sab i of (x, y) -> do writeSmallArray sma i x writeSmallArray smb i y - go $ i+1 + go (i + 1) (,) <$> unsafeFreezeSmallArray sma <*> unsafeFreezeSmallArray smb instance MonadFix SmallArray where mfix f = createSmallArray (sizeofSmallArray (f err)) - (die "mfix" "impossible") $ flip fix 0 $ + (die "mfix" "impossible") $ fix ? 0 $ \r !i !mary -> when (i < sz) $ do writeSmallArray mary i (fix (\xi -> f xi `indexSmallArray` i)) r (i + 1) mary @@ -856,24 +776,33 @@ instance MonadFix SmallArray where sz = sizeofSmallArray (f err) err = error "mfix for Data.Primitive.SmallArray applied to strict function." -#if MIN_VERSION_base(4,9,0) -- | @since 0.6.3.0 instance Sem.Semigroup (SmallArray a) where (<>) = (<|>) sconcat = mconcat . toList -#endif + stimes n arr = case compare n 0 of + LT -> die "stimes" "negative multiplier" + EQ -> empty + GT -> createSmallArray (n' * sizeofSmallArray arr) (die "stimes" "impossible") $ \sma -> + let go i = if i < n' + then do + copySmallArray sma (i * sizeofSmallArray arr) arr 0 (sizeofSmallArray arr) + go (i + 1) + else return () + in go 0 + where n' = fromIntegral n :: Int instance Monoid (SmallArray a) where mempty = empty #if !(MIN_VERSION_base(4,11,0)) - mappend = (<|>) + mappend = (Sem.<>) #endif mconcat l = createSmallArray n (die "mconcat" "impossible") $ \ma -> let go !_ [ ] = return () go off (a:as) = copySmallArray ma off a 0 (sizeofSmallArray a) >> go (off + sizeofSmallArray a) as in go 0 l - where n = sum . fmap length $ l + where n = sum (fmap length l) instance IsList (SmallArray a) where type Item (SmallArray a) = a @@ -893,15 +822,9 @@ listLiftShowsPrec _ sl _ = sl instance Show a => Show (SmallArray a) where showsPrec p sa = smallArrayLiftShowsPrec showsPrec showList p sa -#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,4,0) -- | @since 0.6.4.0 instance Show1 SmallArray where -#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,5,0) liftShowsPrec = smallArrayLiftShowsPrec -#else - showsPrec1 = smallArrayLiftShowsPrec showsPrec showList -#endif -#endif smallArrayLiftReadsPrec :: (Int -> ReadS a) -> ReadS [a] -> Int -> ReadS (SmallArray a) smallArrayLiftReadsPrec _ listReadsPrec p = readParen (p > 10) . readP_to_S $ do @@ -915,15 +838,9 @@ smallArrayLiftReadsPrec _ listReadsPrec p = readParen (p > 10) . readP_to_S $ do instance Read a => Read (SmallArray a) where readsPrec = smallArrayLiftReadsPrec readsPrec readList -#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,4,0) -- | @since 0.6.4.0 instance Read1 SmallArray where -#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,5,0) liftReadsPrec = smallArrayLiftReadsPrec -#else - readsPrec1 = smallArrayLiftReadsPrec readsPrec readList -#endif -#endif @@ -946,12 +863,10 @@ instance (Typeable s, Typeable a) => Data (SmallMutableArray s a) where toConstr _ = die "toConstr" "SmallMutableArray" gunfold _ _ = die "gunfold" "SmallMutableArray" dataTypeOf _ = mkNoRepType "Data.Primitive.SmallArray.SmallMutableArray" -#endif -- | Create a 'SmallArray' from a list of a known length. If the length --- of the list does not match the given length, this throws an exception. +-- of the list does not match the given length, this throws an exception. smallArrayFromListN :: Int -> [a] -> SmallArray a -#if HAVE_SMALL_ARRAY smallArrayFromListN n l = createSmallArray n (die "smallArrayFromListN" "uninitialized element") $ \sma -> @@ -961,13 +876,46 @@ smallArrayFromListN n l = go !ix (x : xs) = if ix < n then do writeSmallArray sma ix x - go (ix+1) xs + go (ix + 1) xs else die "smallArrayFromListN" "list length greater than specified size" in go 0 l -#else -smallArrayFromListN n l = SmallArray (Array.fromListN n l) -#endif -- | Create a 'SmallArray' from a list. smallArrayFromList :: [a] -> SmallArray a smallArrayFromList l = smallArrayFromListN (length l) l + +#if MIN_VERSION_base(4,14,0) +-- | Shrink the mutable array in place. The size given must be equal to +-- or less than the current size of the array. This is not checked. +shrinkSmallMutableArray :: PrimMonad m + => SmallMutableArray (PrimState m) a + -> Int + -> m () +{-# inline shrinkSmallMutableArray #-} +shrinkSmallMutableArray (SmallMutableArray x) (I# n) = primitive + (\s0 -> case GHC.Exts.shrinkSmallMutableArray# x n s0 of + s1 -> (# s1, () #) + ) + +-- | Resize a mutable array to new specified size. The returned +-- 'SmallMutableArray' is either the original 'SmallMutableArray' +-- resized in-place or, if not possible, a newly allocated +-- 'SmallMutableArray' with the original content copied over. +-- +-- To avoid undefined behaviour, the original 'SmallMutableArray' +-- shall not be accessed anymore after a 'resizeSmallMutableArray' has +-- been performed. Moreover, no reference to the old one should be +-- kept in order to allow garbage collection of the original +-- 'SmallMutableArray' in case a new 'SmallMutableArray' had to be +-- allocated. +resizeSmallMutableArray :: PrimMonad m + => SmallMutableArray (PrimState m) a + -> Int -- ^ New size + -> a -- ^ Newly created slots initialized to this element. Only used when array is grown. + -> m (SmallMutableArray (PrimState m) a) +resizeSmallMutableArray (SmallMutableArray arr) (I# n) x = primitive + (\s0 -> case GHC.Exts.resizeSmallMutableArray# arr n x s0 of + (# s1, arr' #) -> (# s1, SmallMutableArray arr' #) + ) +{-# INLINE resizeSmallMutableArray #-} +#endif diff --git a/examples/primitive/Data/Primitive/Types.hs b/examples/primitive/Data/Primitive/Types.hs index 969e6e582..44c9a4999 100644 --- a/examples/primitive/Data/Primitive/Types.hs +++ b/examples/primitive/Data/Primitive/Types.hs @@ -1,9 +1,16 @@ -{-# LANGUAGE CPP, UnboxedTuples, MagicHash, DeriveDataTypeable #-} -{-# LANGUAGE GeneralizedNewtypeDeriving, StandaloneDeriving #-} +{-# LANGUAGE CPP #-} +{-# LANGUAGE UnboxedTuples #-} +{-# LANGUAGE MagicHash #-} +{-# LANGUAGE DeriveDataTypeable #-} +{-# LANGUAGE GeneralizedNewtypeDeriving #-} +{-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE ScopedTypeVariables #-} -#if __GLASGOW_HASKELL__ >= 800 -{-# LANGUAGE TypeInType #-} {-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE PolyKinds #-} + +#if __GLASGOW_HASKELL__ < 906 +{-# LANGUAGE TypeInType #-} #endif #include "HsBaseConfig.h" @@ -16,66 +23,45 @@ -- Maintainer : Roman Leshchinskiy -- Portability : non-portable -- --- Basic types and classes for primitive array operations --- +-- Basic types and classes for primitive array operations. -module Data.Primitive.Types ( - Prim(..) - ,sizeOf, alignment, defaultSetByteArray#, defaultSetOffAddr# - ,PrimStorable(..) - ,Ptr(..) -) where +module Data.Primitive.Types + ( Prim(..) + , sizeOf, alignment, defaultSetByteArray#, defaultSetOffAddr# + , PrimStorable(..) + , Ptr(..) + ) where import Control.Monad.Primitive import Data.Primitive.MachDeps import Data.Primitive.Internal.Operations +import Foreign.Ptr (IntPtr, intPtrToPtr, ptrToIntPtr, WordPtr, wordPtrToPtr, ptrToWordPtr) import Foreign.C.Types import System.Posix.Types -import GHC.Base ( - Int(..), Char(..), - ) -import GHC.Float ( - Float(..), Double(..) - ) -import GHC.Word ( - Word(..), Word8(..), Word16(..), Word32(..), Word64(..) - ) -import GHC.Int ( - Int8(..), Int16(..), Int32(..), Int64(..) - ) - -import GHC.Ptr ( - Ptr(..), FunPtr(..) - ) -import GHC.Stable ( - StablePtr(..) - ) - -import GHC.Exts -#if __GLASGOW_HASKELL__ >= 706 - hiding (setByteArray#) -#endif +import GHC.Word (Word8(..), Word16(..), Word32(..), Word64(..)) +import GHC.Int (Int8(..), Int16(..), Int32(..), Int64(..)) + +import GHC.Stable (StablePtr(..)) +import GHC.Exts hiding (setByteArray#) -import Data.Primitive.Internal.Compat ( isTrue# ) import Foreign.Storable (Storable) import qualified Foreign.Storable as FS +import GHC.IO (IO(..)) +import qualified GHC.Exts + + import Control.Applicative (Const(..)) -#if MIN_VERSION_base(4,8,0) import Data.Functor.Identity (Identity(..)) import qualified Data.Monoid as Monoid -#endif -#if MIN_VERSION_base(4,6,0) -import Data.Ord (Down(..)) -#else -import GHC.Exts (Down(..)) -#endif -#if MIN_VERSION_base(4,9,0) import qualified Data.Semigroup as Semigroup + +#if !MIN_VERSION_base(4,13,0) +import Data.Ord (Down(..)) #endif -- | Class of types supporting primitive array operations. This includes @@ -83,9 +69,8 @@ import qualified Data.Semigroup as Semigroup -- and interfacing with unmanaged memory (functions suffixed with @Addr#@). -- Endianness is platform-dependent. class Prim a where - -- | Size of values of type @a@. The argument is not used. - sizeOf# :: a -> Int# + sizeOf# :: a -> Int# -- | Alignment of values of type @a@. The argument is not used. alignment# :: a -> Int# @@ -104,7 +89,13 @@ class Prim a where -- | Fill a slice of the mutable array with a value. The offset and length -- of the chunk are in elements of type @a@ rather than in bytes. - setByteArray# :: MutableByteArray# s -> Int# -> Int# -> a -> State# s -> State# s + setByteArray# + :: MutableByteArray# s + -> Int# -- ^ offset + -> Int# -- ^ length + -> a + -> State# s + -> State# s -- | Read a value from a memory position given by an address and an offset. -- The memory block the address refers to must be immutable. The offset is in @@ -121,25 +112,31 @@ class Prim a where -- | Fill a memory block given by an address, an offset and a length. -- The offset and length are in elements of type @a@ rather than in bytes. - setOffAddr# :: Addr# -> Int# -> Int# -> a -> State# s -> State# s + setOffAddr# + :: Addr# + -> Int# -- ^ offset + -> Int# -- ^ length + -> a + -> State# s + -> State# s -- | Size of values of type @a@. The argument is not used. -- -- This function has existed since 0.1, but was moved from 'Data.Primitive' --- to 'Data.Primitive.Types' in version 0.6.3.0 +-- to 'Data.Primitive.Types' in version 0.6.3.0. sizeOf :: Prim a => a -> Int sizeOf x = I# (sizeOf# x) -- | Alignment of values of type @a@. The argument is not used. -- -- This function has existed since 0.1, but was moved from 'Data.Primitive' --- to 'Data.Primitive.Types' in version 0.6.3.0 +-- to 'Data.Primitive.Types' in version 0.6.3.0. alignment :: Prim a => a -> Int alignment x = I# (alignment# x) -- | An implementation of 'setByteArray#' that calls 'writeByteArray#' -- to set each element. This is helpful when writing a 'Prim' instance --- for a multi-word data type for which there is no cpu-accelerated way +-- for a multi-word data type for which there is no CPU-accelerated way -- to broadcast a value to contiguous memory. It is typically used -- alongside 'defaultSetOffAddr#'. For example: -- @@ -206,42 +203,58 @@ instance Prim a => Storable (PrimStorable a) where writeOffAddr# addr# i# a s# #define derivePrim(ty, ctr, sz, align, idx_arr, rd_arr, wr_arr, set_arr, idx_addr, rd_addr, wr_addr, set_addr) \ -instance Prim (ty) where { \ - sizeOf# _ = unI# sz \ -; alignment# _ = unI# align \ -; indexByteArray# arr# i# = ctr (idx_arr arr# i#) \ -; readByteArray# arr# i# s# = case rd_arr arr# i# s# of \ - { (# s1#, x# #) -> (# s1#, ctr x# #) } \ -; writeByteArray# arr# i# (ctr x#) s# = wr_arr arr# i# x# s# \ -; setByteArray# arr# i# n# (ctr x#) s# \ - = let { i = fromIntegral (I# i#) \ - ; n = fromIntegral (I# n#) \ - } in \ - case unsafeCoerce# (internal (set_arr arr# i n x#)) s# of \ - { (# s1#, _ #) -> s1# } \ - \ -; indexOffAddr# addr# i# = ctr (idx_addr addr# i#) \ -; readOffAddr# addr# i# s# = case rd_addr addr# i# s# of \ - { (# s1#, x# #) -> (# s1#, ctr x# #) } \ -; writeOffAddr# addr# i# (ctr x#) s# = wr_addr addr# i# x# s# \ -; setOffAddr# addr# i# n# (ctr x#) s# \ - = let { i = fromIntegral (I# i#) \ - ; n = fromIntegral (I# n#) \ - } in \ +instance Prim (ty) where { \ + sizeOf# _ = unI# sz \ +; alignment# _ = unI# align \ +; indexByteArray# arr# i# = ctr (idx_arr arr# i#) \ +; readByteArray# arr# i# s# = case rd_arr arr# i# s# of \ + { (# s1#, x# #) -> (# s1#, ctr x# #) } \ +; writeByteArray# arr# i# (ctr x#) s# = wr_arr arr# i# x# s# \ +; setByteArray# arr# i# n# (ctr x#) s# \ + = let { i = fromIntegral (I# i#) \ + ; n = fromIntegral (I# n#) \ + } in \ + case unsafeCoerce# (internal (set_arr arr# i n x#)) s# of \ + { (# s1#, _ #) -> s1# } \ + \ +; indexOffAddr# addr# i# = ctr (idx_addr addr# i#) \ +; readOffAddr# addr# i# s# = case rd_addr addr# i# s# of \ + { (# s1#, x# #) -> (# s1#, ctr x# #) } \ +; writeOffAddr# addr# i# (ctr x#) s# = wr_addr addr# i# x# s# \ +; setOffAddr# addr# i# n# (ctr x#) s# \ + = let { i = fromIntegral (I# i#) \ + ; n = fromIntegral (I# n#) \ + } in \ case unsafeCoerce# (internal (set_addr addr# i n x#)) s# of \ - { (# s1#, _ #) -> s1# } \ -; {-# INLINE sizeOf# #-} \ -; {-# INLINE alignment# #-} \ -; {-# INLINE indexByteArray# #-} \ -; {-# INLINE readByteArray# #-} \ -; {-# INLINE writeByteArray# #-} \ -; {-# INLINE setByteArray# #-} \ -; {-# INLINE indexOffAddr# #-} \ -; {-# INLINE readOffAddr# #-} \ -; {-# INLINE writeOffAddr# #-} \ -; {-# INLINE setOffAddr# #-} \ + { (# s1#, _ #) -> s1# } \ +; {-# INLINE sizeOf# #-} \ +; {-# INLINE alignment# #-} \ +; {-# INLINE indexByteArray# #-} \ +; {-# INLINE readByteArray# #-} \ +; {-# INLINE writeByteArray# #-} \ +; {-# INLINE setByteArray# #-} \ +; {-# INLINE indexOffAddr# #-} \ +; {-# INLINE readOffAddr# #-} \ +; {-# INLINE writeOffAddr# #-} \ +; {-# INLINE setOffAddr# #-} \ } +#if __GLASGOW_HASKELL__ >= 902 +liberate# :: State# s -> State# r +liberate# = unsafeCoerce# +shimmedSetWord8Array# :: MutableByteArray# s -> Int -> Int -> Word8# -> IO () +shimmedSetWord8Array# m (I# off) (I# len) w = IO (\s -> (# liberate# (GHC.Exts.setByteArray# m off len (GHC.Exts.word2Int# (GHC.Exts.word8ToWord# w)) (liberate# s)), () #)) +shimmedSetInt8Array# :: MutableByteArray# s -> Int -> Int -> Int8# -> IO () +shimmedSetInt8Array# m (I# off) (I# len) i = IO (\s -> (# liberate# (GHC.Exts.setByteArray# m off len (GHC.Exts.int8ToInt# i) (liberate# s)), () #)) +#else +liberate# :: State# s -> State# r +liberate# = unsafeCoerce# +shimmedSetWord8Array# :: MutableByteArray# s -> Int -> Int -> Word# -> IO () +shimmedSetWord8Array# m (I# off) (I# len) w = IO (\s -> (# liberate# (GHC.Exts.setByteArray# m off len (GHC.Exts.word2Int# w) (liberate# s)), () #)) +shimmedSetInt8Array# :: MutableByteArray# s -> Int -> Int -> Int# -> IO () +shimmedSetInt8Array# m (I# off) (I# len) i = IO (\s -> (# liberate# (GHC.Exts.setByteArray# m off len i (liberate# s)), () #)) +#endif + unI# :: Int -> Int# unI# (I# n#) = n# @@ -249,7 +262,7 @@ derivePrim(Word, W#, sIZEOF_WORD, aLIGNMENT_WORD, indexWordArray#, readWordArray#, writeWordArray#, setWordArray#, indexWordOffAddr#, readWordOffAddr#, writeWordOffAddr#, setWordOffAddr#) derivePrim(Word8, W8#, sIZEOF_WORD8, aLIGNMENT_WORD8, - indexWord8Array#, readWord8Array#, writeWord8Array#, setWord8Array#, + indexWord8Array#, readWord8Array#, writeWord8Array#, shimmedSetWord8Array#, indexWord8OffAddr#, readWord8OffAddr#, writeWord8OffAddr#, setWord8OffAddr#) derivePrim(Word16, W16#, sIZEOF_WORD16, aLIGNMENT_WORD16, indexWord16Array#, readWord16Array#, writeWord16Array#, setWord16Array#, @@ -264,7 +277,7 @@ derivePrim(Int, I#, sIZEOF_INT, aLIGNMENT_INT, indexIntArray#, readIntArray#, writeIntArray#, setIntArray#, indexIntOffAddr#, readIntOffAddr#, writeIntOffAddr#, setIntOffAddr#) derivePrim(Int8, I8#, sIZEOF_INT8, aLIGNMENT_INT8, - indexInt8Array#, readInt8Array#, writeInt8Array#, setInt8Array#, + indexInt8Array#, readInt8Array#, writeInt8Array#, shimmedSetInt8Array#, indexInt8OffAddr#, readInt8OffAddr#, writeInt8OffAddr#, setInt8OffAddr#) derivePrim(Int16, I16#, sIZEOF_INT16, aLIGNMENT_INT16, indexInt16Array#, readInt16Array#, writeInt16Array#, setInt16Array#, @@ -390,11 +403,47 @@ deriving instance Prim CTimer #endif deriving instance Prim Fd +-- Andrew Martin: The instances for WordPtr and IntPtr are written out by +-- hand in a tedious way. We cannot use GND because the data constructors for +-- these types were not available before GHC 8.2. The CPP for generating code +-- for the Int and Word types does not work here. There is a way to clean this +-- up a little with CPP, and if anyone wants to do that, go for it. In the +-- meantime, I am going to ship this with the instances written out by hand. + +-- | @since 0.7.1.0 +instance Prim WordPtr where + sizeOf# _ = sizeOf# (undefined :: Ptr ()) + alignment# _ = alignment# (undefined :: Ptr ()) + indexByteArray# a i = ptrToWordPtr (indexByteArray# a i) + readByteArray# a i s0 = case readByteArray# a i s0 of + (# s1, p #) -> (# s1, ptrToWordPtr p #) + writeByteArray# a i wp = writeByteArray# a i (wordPtrToPtr wp) + setByteArray# a i n wp = setByteArray# a i n (wordPtrToPtr wp) + indexOffAddr# a i = ptrToWordPtr (indexOffAddr# a i) + readOffAddr# a i s0 = case readOffAddr# a i s0 of + (# s1, p #) -> (# s1, ptrToWordPtr p #) + writeOffAddr# a i wp = writeOffAddr# a i (wordPtrToPtr wp) + setOffAddr# a i n wp = setOffAddr# a i n (wordPtrToPtr wp) + +-- | @since 0.7.1.0 +instance Prim IntPtr where + sizeOf# _ = sizeOf# (undefined :: Ptr ()) + alignment# _ = alignment# (undefined :: Ptr ()) + indexByteArray# a i = ptrToIntPtr (indexByteArray# a i) + readByteArray# a i s0 = case readByteArray# a i s0 of + (# s1, p #) -> (# s1, ptrToIntPtr p #) + writeByteArray# a i wp = writeByteArray# a i (intPtrToPtr wp) + setByteArray# a i n wp = setByteArray# a i n (intPtrToPtr wp) + indexOffAddr# a i = ptrToIntPtr (indexOffAddr# a i) + readOffAddr# a i s0 = case readOffAddr# a i s0 of + (# s1, p #) -> (# s1, ptrToIntPtr p #) + writeOffAddr# a i wp = writeOffAddr# a i (intPtrToPtr wp) + setOffAddr# a i n wp = setOffAddr# a i n (intPtrToPtr wp) + -- | @since 0.6.5.0 deriving instance Prim a => Prim (Const a b) -- | @since 0.6.5.0 deriving instance Prim a => Prim (Down a) -#if MIN_VERSION_base(4,8,0) -- | @since 0.6.5.0 deriving instance Prim a => Prim (Identity a) -- | @since 0.6.5.0 @@ -403,8 +452,6 @@ deriving instance Prim a => Prim (Monoid.Dual a) deriving instance Prim a => Prim (Monoid.Sum a) -- | @since 0.6.5.0 deriving instance Prim a => Prim (Monoid.Product a) -#endif -#if MIN_VERSION_base(4,9,0) -- | @since 0.6.5.0 deriving instance Prim a => Prim (Semigroup.First a) -- | @since 0.6.5.0 @@ -413,4 +460,3 @@ deriving instance Prim a => Prim (Semigroup.Last a) deriving instance Prim a => Prim (Semigroup.Min a) -- | @since 0.6.5.0 deriving instance Prim a => Prim (Semigroup.Max a) -#endif diff --git a/examples/primitive/cbits/primitive-memops.c b/examples/primitive/cbits/primitive-memops.c index 81b1d6f57..680273e19 100644 --- a/examples/primitive/cbits/primitive-memops.c +++ b/examples/primitive/cbits/primitive-memops.c @@ -40,14 +40,19 @@ int hsprimitive_memcmp( HsWord8 *s1, HsWord8 *s2, size_t n ) return memcmp( s1, s2, n ); } -void hsprimitive_memset_Word8 (HsWord8 *p, ptrdiff_t off, size_t n, HsWord x) +int hsprimitive_memcmp_offset( HsWord8 *s1, HsInt off1, HsWord8 *s2, HsInt off2, size_t n ) +{ + return memcmp( s1 + off1, s2 + off2, n ); +} + +void hsprimitive_memset_Word8 (HsWord8 *p, ptrdiff_t off, size_t n, HsWord8 x) { memset( (char *)(p+off), x, n ); } /* MEMSET(HsWord8, HsWord) */ -MEMSET(Word16, HsWord) -MEMSET(Word32, HsWord) +MEMSET(Word16, HsWord16) +MEMSET(Word32, HsWord32) MEMSET(Word64, HsWord64) MEMSET(Word, HsWord) MEMSET(Ptr, HsPtr) diff --git a/examples/primitive/cbits/primitive-memops.h b/examples/primitive/cbits/primitive-memops.h index d7c3396f8..10c0931c5 100644 --- a/examples/primitive/cbits/primitive-memops.h +++ b/examples/primitive/cbits/primitive-memops.h @@ -1,23 +1,25 @@ #ifndef haskell_primitive_memops_h #define haskell_primitive_memops_h +// N.B. GHC RTS headers want to come first, lest things break on Windows. +#include + #include #include -#include -void hsprimitive_memcpy( void *dst, ptrdiff_t doff, void *src, ptrdiff_t soff, size_t len ); -void hsprimitive_memmove( void *dst, ptrdiff_t doff, void *src, ptrdiff_t soff, size_t len ); -int hsprimitive_memcmp( HsWord8 *s1, HsWord8 *s2, size_t n ); +void hsprimitive_memcpy(void *dst, ptrdiff_t doff, void *src, ptrdiff_t soff, size_t len); +void hsprimitive_memmove(void *dst, ptrdiff_t doff, void *src, ptrdiff_t soff, size_t len); +int hsprimitive_memcmp(HsWord8 *s1, HsWord8 *s2, size_t n); +int hsprimitive_memcmp_offset(HsWord8 *s1, HsInt off1, HsWord8 *s2, HsInt off2, size_t n); -void hsprimitive_memset_Word8 (HsWord8 *, ptrdiff_t, size_t, HsWord); -void hsprimitive_memset_Word16 (HsWord16 *, ptrdiff_t, size_t, HsWord); -void hsprimitive_memset_Word32 (HsWord32 *, ptrdiff_t, size_t, HsWord); -void hsprimitive_memset_Word64 (HsWord64 *, ptrdiff_t, size_t, HsWord64); -void hsprimitive_memset_Word (HsWord *, ptrdiff_t, size_t, HsWord); -void hsprimitive_memset_Ptr (HsPtr *, ptrdiff_t, size_t, HsPtr); -void hsprimitive_memset_Float (HsFloat *, ptrdiff_t, size_t, HsFloat); -void hsprimitive_memset_Double (HsDouble *, ptrdiff_t, size_t, HsDouble); -void hsprimitive_memset_Char (HsChar *, ptrdiff_t, size_t, HsChar); +void hsprimitive_memset_Word8(HsWord8 *, ptrdiff_t, size_t, HsWord8); +void hsprimitive_memset_Word16(HsWord16 *, ptrdiff_t, size_t, HsWord16); +void hsprimitive_memset_Word32(HsWord32 *, ptrdiff_t, size_t, HsWord32); +void hsprimitive_memset_Word64(HsWord64 *, ptrdiff_t, size_t, HsWord64); +void hsprimitive_memset_Word(HsWord *, ptrdiff_t, size_t, HsWord); +void hsprimitive_memset_Ptr(HsPtr *, ptrdiff_t, size_t, HsPtr); +void hsprimitive_memset_Float(HsFloat *, ptrdiff_t, size_t, HsFloat); +void hsprimitive_memset_Double(HsDouble *, ptrdiff_t, size_t, HsDouble); +void hsprimitive_memset_Char(HsChar *, ptrdiff_t, size_t, HsChar); #endif - diff --git a/examples/primitive/changelog.md b/examples/primitive/changelog.md index 02d72a40f..352eaa29d 100644 --- a/examples/primitive/changelog.md +++ b/examples/primitive/changelog.md @@ -1,3 +1,104 @@ +## Changes in version 0.8.0.0 + + * Add `resizeSmallMutableArray` that wraps `resizeSmallMutableArray#` from + `GHC.Exts`. + + * New module `Data.Primitive.PrimVar`. This is essentially `PrimArray` with + element length 1. For types with `Prim` instances, this is a drop-in + replacement for `MutVar` with fewer indirections. + + * `PrimArray`'s type argument has been given a nominal role instead of a phantom role. + This is a breaking change. + + * Add `readCharArray`, `writeCharArray`, `indexCharArray` for operating on + 8-bit characters in a byte array. + + * When building with `base-4.17` and newer, re-export the `ByteArray` and + `MutableByteArray` types from `base` instead of defining them in this + library. This does not change the user-facing interface of + `Data.Primitive.ByteArray`. + + * Add `keepAlive` that wraps `keepAlive#` for GHC 9.2 and newer. It + falls back to using `touch` for older GHCs. + +## Changes in version 0.7.4.0 + + * Add Lift instances (#332) + + * Expose `copyPtrToMutablePrimArray` + + * Improve definitions for stimes (#326) + + * Support GHC 9.4. Note: GHC 9.4 is not released at the time of + primitive-0.7.4.0's release, so this support might be reverted by + a hackage metadata revision if things change. + + * Drop support for GHC 7.10 + +## Changes in version 0.7.3.0 + + * Correct implementations of `*>` for `Array` and `SmallArray`. + + * Drop support for GHC < 7.10 + + * Export `runByteArray` and `runPrimArray`. + + * Export `createArray` and `createSmallArray`. + + * Export `emptyByteArray`, `emptyPrimArray`, `emptyArray` and `emptySmallArray`. + +## Changes in version 0.7.2.0 + + * Add `thawByteArray` and `thawPrimArray`. + + * Changed the `Show` instance of `ByteArray`, so that all 8-bit words + are rendered as two digits. For example, display `0x0D` instead of `0xD`. + +## Changes in version 0.7.1.0 + + * Introduce convenience class `MonadPrim` and `MonadPrimBase`. + + * Add `PrimMonad` and `PrimBase` instances for `Lazy.ST` (GHC >= 8.2). + thanks to Avi Dessauer (@Avi-D-coder) for this first contribution + + * Add `freezeByteArray` and `freezePrimArray`. + + * Add `compareByteArrays`. + + * Add `shrinkMutableByteArray`. + + * Add `Eq` instances for `MutableByteArray` and `MutablePrimArray`. + by Andrew Martin + + * Add functions for manipulating pinned Prim Arrays + by Andrew Martin + + * Add `copyPtrToMutableByteArray`. + + * Add `NFData` instances for `ByteArray`, `MutableByteArray`, + `PrimArray` and `MutablePrimArray`. + by Callan McGill + + * Add `shrinkSmallMutableArray`. + + * Add `clonePrimArray` and `cloneMutablePrimArray`. + + * Add `cloneMutableByteArray` and `cloneByteArray`. + + * Add `Prim` instances for `WordPtr` and `IntPtr`. + + * Add `NFData` instances for `Array` and `SmallArray`. + by Callan McGill + + * Add `copyByteArrayToPtr` and `copyMutableByteArrayToPtr`. + + * Export `arrayFromList` and `arrayFromListN`. + +## Changes in version 0.7.0.1 + + * Allow building with GHC 8.12. + Thanks Ryan GL Scott for this and every compat patch over time. + ## Changes in version 0.7.0.0 * Remove `Addr` data type, lifted code should use `Ptr a` now diff --git a/examples/primitive/test/main.hs b/examples/primitive/test/main.hs index 1ce98ae8e..689b289e6 100644 --- a/examples/primitive/test/main.hs +++ b/examples/primitive/test/main.hs @@ -26,24 +26,13 @@ import GHC.IO import GHC.Exts import Data.Function (on) import Control.Applicative (Const(..)) -import PrimLawsWIP (primLaws) +import PrimLaws (primLaws) -#if !(MIN_VERSION_base(4,8,0)) -import Data.Monoid (Monoid(..)) -#endif -#if MIN_VERSION_base(4,8,0) import Data.Functor.Identity (Identity(..)) import qualified Data.Monoid as Monoid -#endif -#if MIN_VERSION_base(4,6,0) import Data.Ord (Down(..)) -#else -import GHC.Exts (Down(..)) -#endif -#if MIN_VERSION_base(4,9,0) -import Data.Semigroup (stimes) +import Data.Semigroup (stimes, stimesMonoid) import qualified Data.Semigroup as Semigroup -#endif #if !(MIN_VERSION_base(4,11,0)) import Data.Monoid ((<>)) #endif @@ -53,11 +42,11 @@ import Foreign.Storable (Storable) import Data.Orphans () import Test.Tasty (defaultMain,testGroup,TestTree) -import Test.QuickCheck (Arbitrary,Arbitrary1,Gen,(===),CoArbitrary,Function) +import Test.QuickCheck (Arbitrary,Arbitrary1,Gen,CoArbitrary,Function,(===),(==>)) import qualified Test.Tasty.QuickCheck as TQC import qualified Test.QuickCheck as QC -import qualified Test.QuickCheck.Classes as QCC -import qualified Test.QuickCheck.Classes.IsList as QCCL +import qualified Test.QuickCheck.Classes.Base as QCC +import qualified Test.QuickCheck.Classes.Base.IsList as QCCL import qualified Data.List as L main :: IO () @@ -70,57 +59,69 @@ main = do , lawsToTest (QCC.ordLaws (Proxy :: Proxy (Array Int))) , lawsToTest (QCC.monoidLaws (Proxy :: Proxy (Array Int))) , lawsToTest (QCC.showReadLaws (Proxy :: Proxy (Array Int))) -#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,4,0) , lawsToTest (QCC.functorLaws (Proxy1 :: Proxy1 Array)) , lawsToTest (QCC.applicativeLaws (Proxy1 :: Proxy1 Array)) , lawsToTest (QCC.monadLaws (Proxy1 :: Proxy1 Array)) , lawsToTest (QCC.foldableLaws (Proxy1 :: Proxy1 Array)) , lawsToTest (QCC.traversableLaws (Proxy1 :: Proxy1 Array)) -#endif -#if MIN_VERSION_base(4,7,0) , lawsToTest (QCC.isListLaws (Proxy :: Proxy (Array Int))) , TQC.testProperty "mapArray'" (QCCL.mapProp int16 int32 mapArray') -#endif + , TQC.testProperty "*>" $ \(xs :: Array Int) (ys :: Array Int) -> toList (xs *> ys) === (toList xs *> toList ys) + , TQC.testProperty "<*" $ \(xs :: Array Int) (ys :: Array Int) -> toList (xs <* ys) === (toList xs <* toList ys) + , lawsToTest (QCC.semigroupLaws (Proxy :: Proxy (Array Int))) + , TQC.testProperty "stimes" $ \(QC.NonNegative (n :: Int)) (xs :: Array Int) -> stimes n xs == stimesMonoid n xs ] , testGroup "SmallArray" [ lawsToTest (QCC.eqLaws (Proxy :: Proxy (SmallArray Int))) , lawsToTest (QCC.ordLaws (Proxy :: Proxy (SmallArray Int))) , lawsToTest (QCC.monoidLaws (Proxy :: Proxy (SmallArray Int))) , lawsToTest (QCC.showReadLaws (Proxy :: Proxy (Array Int))) -#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,4,0) , lawsToTest (QCC.functorLaws (Proxy1 :: Proxy1 SmallArray)) , lawsToTest (QCC.applicativeLaws (Proxy1 :: Proxy1 SmallArray)) , lawsToTest (QCC.monadLaws (Proxy1 :: Proxy1 SmallArray)) , lawsToTest (QCC.foldableLaws (Proxy1 :: Proxy1 SmallArray)) , lawsToTest (QCC.traversableLaws (Proxy1 :: Proxy1 SmallArray)) -#endif -#if MIN_VERSION_base(4,7,0) , lawsToTest (QCC.isListLaws (Proxy :: Proxy (SmallArray Int))) , TQC.testProperty "mapSmallArray'" (QCCL.mapProp int16 int32 mapSmallArray') -#endif + , TQC.testProperty "*>" $ \(xs :: SmallArray Int) (ys :: SmallArray Int) -> toList (xs *> ys) === (toList xs *> toList ys) + , TQC.testProperty "<*" $ \(xs :: SmallArray Int) (ys :: SmallArray Int) -> toList (xs <* ys) === (toList xs <* toList ys) + , lawsToTest (QCC.semigroupLaws (Proxy :: Proxy (SmallArray Int))) + , TQC.testProperty "stimes" $ \(QC.NonNegative (n :: Int)) (xs :: SmallArray Int) -> stimes n xs == stimesMonoid n xs ] , testGroup "ByteArray" [ testGroup "Ordering" [ TQC.testProperty "equality" byteArrayEqProp , TQC.testProperty "compare" byteArrayCompareProp + , testGroup "Filling" + [ TQC.testProperty "Int8" (setByteArrayProp (Proxy :: Proxy Int8)) + , TQC.testProperty "Int16" (setByteArrayProp (Proxy :: Proxy Int16)) + , TQC.testProperty "Int32" (setByteArrayProp (Proxy :: Proxy Int32)) + , TQC.testProperty "Int64" (setByteArrayProp (Proxy :: Proxy Int64)) + , TQC.testProperty "Int" (setByteArrayProp (Proxy :: Proxy Int)) + , TQC.testProperty "Word8" (setByteArrayProp (Proxy :: Proxy Word8)) + , TQC.testProperty "Word16" (setByteArrayProp (Proxy :: Proxy Word16)) + , TQC.testProperty "Word32" (setByteArrayProp (Proxy :: Proxy Word32)) + , TQC.testProperty "Word64" (setByteArrayProp (Proxy :: Proxy Word64)) + , TQC.testProperty "Word" (setByteArrayProp (Proxy :: Proxy Word)) ] + ] , testGroup "Resize" [ TQC.testProperty "shrink" byteArrayShrinkProp , TQC.testProperty "grow" byteArrayGrowProp ] , lawsToTest (QCC.eqLaws (Proxy :: Proxy ByteArray)) , lawsToTest (QCC.ordLaws (Proxy :: Proxy ByteArray)) + , lawsToTest (QCC.monoidLaws (Proxy :: Proxy ByteArray)) , lawsToTest (QCC.showReadLaws (Proxy :: Proxy (Array Int))) -#if MIN_VERSION_base(4,7,0) , lawsToTest (QCC.isListLaws (Proxy :: Proxy ByteArray)) , TQC.testProperty "foldrByteArray" (QCCL.foldrProp word8 foldrByteArray) -#endif + , lawsToTest (QCC.semigroupLaws (Proxy :: Proxy ByteArray)) + , TQC.testProperty "stimes" $ \(QC.NonNegative (n :: Int)) (xs :: ByteArray) -> stimes n xs == stimesMonoid n xs ] , testGroup "PrimArray" [ lawsToTest (QCC.eqLaws (Proxy :: Proxy (PrimArray Word16))) , lawsToTest (QCC.ordLaws (Proxy :: Proxy (PrimArray Word16))) , lawsToTest (QCC.monoidLaws (Proxy :: Proxy (PrimArray Word16))) -#if MIN_VERSION_base(4,7,0) , lawsToTest (QCC.isListLaws (Proxy :: Proxy (PrimArray Word16))) , TQC.testProperty "foldrPrimArray" (QCCL.foldrProp int16 foldrPrimArray) , TQC.testProperty "foldrPrimArray'" (QCCL.foldrProp int16 foldrPrimArray') @@ -145,20 +146,18 @@ main = do , TQC.testProperty "mapMaybePrimArray" (QCCL.mapMaybeProp int16 int32 mapMaybePrimArray) , TQC.testProperty "mapMaybePrimArrayA" (QCCL.mapMaybeMProp int16 int32 mapMaybePrimArrayA) , TQC.testProperty "mapMaybePrimArrayP" (QCCL.mapMaybeMProp int16 int32 mapMaybePrimArrayP) -#endif + , lawsToTest (QCC.semigroupLaws (Proxy :: Proxy (PrimArray Word16))) + , TQC.testProperty "stimes" $ \(QC.NonNegative (n :: Int)) (xs :: PrimArray Word16) -> stimes n xs == stimesMonoid n xs ] - - - - ,testGroup "DefaultSetMethod" + , testGroup "DefaultSetMethod" [ lawsToTest (primLaws (Proxy :: Proxy DefaultSetMethod)) ] #if __GLASGOW_HASKELL__ >= 805 - ,testGroup "PrimStorable" + , testGroup "PrimStorable" [ lawsToTest (QCC.storableLaws (Proxy :: Proxy Derived)) ] #endif - ,testGroup "Prim" + , testGroup "Prim" [ renameLawsToTest "Word" (primLaws (Proxy :: Proxy Word)) , renameLawsToTest "Word8" (primLaws (Proxy :: Proxy Word8)) , renameLawsToTest "Word16" (primLaws (Proxy :: Proxy Word16)) @@ -171,32 +170,24 @@ main = do , renameLawsToTest "Int64" (primLaws (Proxy :: Proxy Int64)) , renameLawsToTest "Const" (primLaws (Proxy :: Proxy (Const Int16 Int16))) , renameLawsToTest "Down" (primLaws (Proxy :: Proxy (Down Int16))) -#if MIN_VERSION_base(4,8,0) , renameLawsToTest "Identity" (primLaws (Proxy :: Proxy (Identity Int16))) , renameLawsToTest "Dual" (primLaws (Proxy :: Proxy (Monoid.Dual Int16))) , renameLawsToTest "Sum" (primLaws (Proxy :: Proxy (Monoid.Sum Int16))) , renameLawsToTest "Product" (primLaws (Proxy :: Proxy (Monoid.Product Int16))) -#endif -#if MIN_VERSION_base(4,9,0) , renameLawsToTest "First" (primLaws (Proxy :: Proxy (Semigroup.First Int16))) , renameLawsToTest "Last" (primLaws (Proxy :: Proxy (Semigroup.Last Int16))) , renameLawsToTest "Min" (primLaws (Proxy :: Proxy (Semigroup.Min Int16))) , renameLawsToTest "Max" (primLaws (Proxy :: Proxy (Semigroup.Max Int16))) -#endif - ] - ] deriving instance Arbitrary a => Arbitrary (Down a) -- Const, Dual, Sum, Product: all have Arbitrary instances defined -- in QuickCheck itself -#if MIN_VERSION_base(4,9,0) deriving instance Arbitrary a => Arbitrary (Semigroup.First a) deriving instance Arbitrary a => Arbitrary (Semigroup.Last a) deriving instance Arbitrary a => Arbitrary (Semigroup.Min a) deriving instance Arbitrary a => Arbitrary (Semigroup.Max a) -#endif word8 :: Proxy Word8 word8 = Proxy @@ -208,6 +199,24 @@ int32 :: Proxy Int32 int32 = Proxy +setByteArrayProp :: forall a. (Prim a, Eq a, Arbitrary a, Show a) => Proxy a -> QC.Property +setByteArrayProp _ = QC.property $ \(QC.NonNegative (n :: Int)) (QC.NonNegative (off :: Int)) (QC.NonNegative (len :: Int)) (x :: a) (y :: a) -> + (off < n && off + len <= n) ==> + -- We use PrimArray in this test because it makes it easier to + -- get the element-vs-byte distinction right. + let actual = runST $ do + m <- newPrimArray n + forM_ (enumFromTo 0 (n - 1)) $ \ix -> writePrimArray m ix x + setPrimArray m off len y + unsafeFreezePrimArray m + expected = runST $ do + m <- newPrimArray n + forM_ (enumFromTo 0 (n - 1)) $ \ix -> writePrimArray m ix x + forM_ (enumFromTo off (off + len - 1)) $ \ix -> writePrimArray m ix y + unsafeFreezePrimArray m + in expected === actual + + -- Tests that using resizeByteArray to shrink a byte array produces -- the same results as calling Data.List.take on the list that the -- byte array corresponds to. @@ -327,8 +336,17 @@ testByteArray = do arr3 = mkByteArray ([0xde, 0xad, 0xbe, 0xee] :: [Word8]) arr4 = mkByteArray ([0xde, 0xad, 0xbe, 0xdd] :: [Word8]) arr5 = mkByteArray ([0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xdd] :: [Word8]) + arr6 = mkByteArray ([0xde, 0xad, 0x00, 0x01, 0xb0] :: [Word8]) when (show arr1 /= "[0xde, 0xad, 0xbe, 0xef]") $ fail $ "ByteArray Show incorrect: "++show arr1 + when (show arr6 /= "[0xde, 0xad, 0x00, 0x01, 0xb0]") $ + fail $ "ByteArray Show incorrect: "++ show arr6 + when (compareByteArrays arr3 1 arr4 1 3 /= GT) $ + fail $ "arr3[1,3] should be greater than arr4[1,3]" + when (compareByteArrays arr3 0 arr4 1 3 /= GT) $ + fail $ "arr3[0,3] should be greater than arr4[1,3]" + when (compareByteArrays arr5 1 arr2 1 3 /= EQ) $ + fail $ "arr3[1,3] should be equal to than arr4[1,3]" unless (arr1 > arr3) $ fail $ "ByteArray Ord incorrect" unless (arr1 == arr2) $ @@ -339,10 +357,8 @@ testByteArray = do fail $ "ByteArray Monoid mappend not associative" unless (mconcat [arr1,arr2,arr3,arr4,arr5] == (arr1 <> arr2 <> arr3 <> arr4 <> arr5)) $ fail $ "ByteArray Monoid mconcat incorrect" -#if MIN_VERSION_base(4,9,0) unless (stimes (3 :: Int) arr4 == (arr4 <> arr4 <> arr4)) $ fail $ "ByteArray Semigroup stimes incorrect" -#endif mkByteArray :: Prim a => [a] -> ByteArray mkByteArray xs = runST $ do From 350908ce7123711347ee40aee4f0456af78190ad Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Mon, 15 May 2023 09:18:39 +0200 Subject: [PATCH 04/41] Update examples to use GHC 9.6.1 hadrian bindist --- examples/WORKSPACE | 57 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/examples/WORKSPACE b/examples/WORKSPACE index 33bcbe3c3..0d040f658 100644 --- a/examples/WORKSPACE +++ b/examples/WORKSPACE @@ -15,12 +15,56 @@ load("@rules_haskell//haskell:repositories.bzl", "rules_haskell_dependencies") rules_haskell_dependencies() -load("@rules_haskell//haskell:nixpkgs.bzl", "haskell_register_ghc_nixpkgs") +load( + "@rules_haskell//haskell:ghc_bindist_hadrian.bzl", + "haskell_register_ghc_bindists_hadrian", +) -haskell_register_ghc_nixpkgs( - attribute_path = "haskell.compiler.ghc925", - repository = "@rules_haskell//nixpkgs:default.nix", - version = "9.2.5", +# FIXME copied from non_module_deps_1.bzl +test_ghcopts = [ + "-XStandaloneDeriving", # Flag used at compile time + "-threaded", # Flag used at link time + # Used by `tests/repl-flags` + "-DTESTS_TOOLCHAIN_COMPILER_FLAGS", + # this is the default, so it does not harm other tests + "-XNoOverloadedStrings", +] + +test_haddock_flags = ["-U"] + +test_repl_ghci_args = [ + # The repl test will need this flag, but set by the local + # `repl_ghci_args`. + "-UTESTS_TOOLCHAIN_REPL_FLAGS", + # The repl test will need OverloadedString + "-XOverloadedStrings", +] + +test_cabalopts = [ + # Used by `tests/cabal-toolchain-flags` + "--ghc-option=-DTESTS_TOOLCHAIN_CABALOPTS", + "--haddock-option=--optghc=-DTESTS_TOOLCHAIN_CABALOPTS", +] + ([ + # To avoid ghcide linking errors with heapsize on Windows of the form + # + # unknown symbol `heap_view_closurePtrs' + # + # See https://github.com/haskell/ghcide/pull/954 + "--disable-library-for-ghci", +] if False else []) + +# load( +# "@rules_haskell//:non_module_deps_1.bzl", "test_cabalopts", "test_ghcopts" +# ) + +haskell_register_ghc_bindists_hadrian( + url = "https://downloads.haskell.org/~ghc/9.6.1/ghc-9.6.1-x86_64-deb9-linux.tar.xz", + sha256 = "3c727e93a82ff039fbedd6645518859849130a0fc93b7181cd69a41800aa639c", + strip_prefix = "ghc-9.6.1-x86_64-unknown-linux", + version = "9.6.1", + target = "x86_64-unknown-linux", + cabalopts = test_cabalopts, + ghcopts = test_ghcopts, ) load("@rules_haskell//haskell:toolchain.bzl", "rules_haskell_toolchains") @@ -65,7 +109,8 @@ stack_snapshot( "-pkg-config", ], }, - local_snapshot = "@rules_haskell//:stackage_snapshot.yaml", + #local_snapshot = "@rules_haskell//:stackage_snapshot.yaml", + snapshot = "nightly-2023-05-12", packages = [ "base", "bytestring", From c0f0f27a37909f648ddefa2ab3b6fba7a2f3820b Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Mon, 15 May 2023 09:19:19 +0200 Subject: [PATCH 05/41] Fix `docdir` and pass `is_clang` --- haskell/ghc_bindist_hadrian.bzl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/haskell/ghc_bindist_hadrian.bzl b/haskell/ghc_bindist_hadrian.bzl index dc7916406..b6b1a2fc2 100644 --- a/haskell/ghc_bindist_hadrian.bzl +++ b/haskell/ghc_bindist_hadrian.bzl @@ -71,7 +71,7 @@ def _ghc_bindist_hadrian_impl(ctx): bindir = "bin" libdir = "lib" - docdir = "docs" + docdir = "doc" # The bindist requires patching invalid haddock paths. See Makefile of GHC: # https://gitlab.haskell.org/ghc/ghc/-/blob/ghc-9.2.3-release/hadrian/bindist/Makefile#L54-74 @@ -151,6 +151,7 @@ find {lib}/package.conf.d -name "rts-*.conf" -print0 | \\ "%{generated_lib_filegroup}": generated_lib_filegroup, "%{generated_docdir_filegroup}": generated_docdir_filegroup, "%{generated_include_filegroup}": generated_include_filegroup, + "%{is_clang}": str(False), }, executable = False, ) From 99a3052c8e454bc8a9ddc3946c077610840bed4c Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Mon, 15 May 2023 09:22:01 +0200 Subject: [PATCH 06/41] Pass `-f ` to runghc We skip the `make install` step which would wrap executables with custom scripts. For runghc it passes the GHC executable using the `-f` flag. By default `runghc` would try to execute `ghc-stage2` instead. --- haskell/private/cabal_wrapper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/haskell/private/cabal_wrapper.py b/haskell/private/cabal_wrapper.py index 09e34efef..5d4f6b259 100755 --- a/haskell/private/cabal_wrapper.py +++ b/haskell/private/cabal_wrapper.py @@ -290,7 +290,7 @@ def distdir_prefix(): del os.environ["RUNFILES_DIR"] if "RUNFILES_MANIFEST_FILE" in os.environ: del os.environ["RUNFILES_MANIFEST_FILE"] - runghc_args = [arg.replace("./", execroot + "/") for arg in runghc_args] + runghc_args = ["-f", ghc] + [arg.replace("./", execroot + "/") for arg in runghc_args] if not deps_package_db: path_args.extend(["--package-db=" + os.path.dirname(db) for db in deps_package_databases]) From 766c505d051f8dbe3ea4b9b5676ca950894bda4e Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Mon, 15 May 2023 09:23:44 +0200 Subject: [PATCH 07/41] Add `libdir` to runfiles --- haskell/private/runghc.bzl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/haskell/private/runghc.bzl b/haskell/private/runghc.bzl index c1470893a..93c1845c3 100644 --- a/haskell/private/runghc.bzl +++ b/haskell/private/runghc.bzl @@ -16,6 +16,8 @@ load("@rules_python//python:defs.bzl", "py_binary") def _runghc_wrapper_impl(ctx): hs_toolchain = ctx.toolchains["@rules_haskell//haskell:toolchain"] + lib_dir = hs_toolchain.libdir + f = hs_toolchain.tools.runghc runghc_runfile_path = paths.join(f.owner.workspace_name, f.owner.package, hs_toolchain.tools_path, "runghc") runghc_wrapper_file = ctx.actions.declare_file(ctx.label.name) @@ -38,7 +40,7 @@ subprocess.run([r.Rlocation("{runghc}")] + sys.argv[1:], check=True) return [DefaultInfo( executable = runghc_wrapper_file, runfiles = hs_toolchain.cc_wrapper.runfiles.merge( - ctx.runfiles(files = [runghc_wrapper_file, hs_toolchain.tools.runghc]), + ctx.runfiles(files = [runghc_wrapper_file, hs_toolchain.tools.runghc] + lib_dir), ), )] From 3f7864d60d1641bcccded08cdb11eada1e1fa2b3 Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Mon, 15 May 2023 09:25:50 +0200 Subject: [PATCH 08/41] Fix srcs for _hadrian_bindist_settings --- haskell/toolchain.bzl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/haskell/toolchain.bzl b/haskell/toolchain.bzl index fd52c4c70..27a268144 100644 --- a/haskell/toolchain.bzl +++ b/haskell/toolchain.bzl @@ -609,9 +609,9 @@ def haskell_toolchain( "config.guess", "config.sub", "install-sh", - "mk/config.mk.in", - "mk/install.mk.in", + "config.mk.in", "mk/project.mk", + "mk/system-cxx-std-lib-1.0.conf.in", ], ) From 0d9cfa8c47927bfcd0a1194504a17cdfe0e22266 Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Mon, 15 May 2023 09:26:21 +0200 Subject: [PATCH 09/41] Skip haskell_register_ghc_bindists call --- rules_haskell_tests/WORKSPACE | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rules_haskell_tests/WORKSPACE b/rules_haskell_tests/WORKSPACE index 76df076b8..e9dc485ac 100644 --- a/rules_haskell_tests/WORKSPACE +++ b/rules_haskell_tests/WORKSPACE @@ -106,11 +106,11 @@ load( "haskell_register_ghc_bindists", ) -haskell_register_ghc_bindists( - cabalopts = test_cabalopts, - ghcopts = test_ghcopts, - version = GHC_VERSION, -) +# haskell_register_ghc_bindists( +# cabalopts = test_cabalopts, +# ghcopts = test_ghcopts, +# version = GHC_VERSION, +# ) load("non_module_deps_1.bzl", repositories_1 = "repositories") From 6b256e94b0bcc3eab157e4a94ab954f229dbf4b0 Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Mon, 15 May 2023 10:26:45 +0200 Subject: [PATCH 10/41] Make the `start` script work with GHC/Hadrian 9.6.1 --- start | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/start b/start index bda781ddf..31c08ce0b 100755 --- a/start +++ b/start @@ -238,6 +238,14 @@ load( # Setup all Bazel dependencies required by rules_haskell. rules_haskell_dependencies() +http_archive( + name = "io_bazel_rules_go", + sha256 = "8e968b5fcea1d2d64071872b12737bbb5514524ee5f0a4f54f5920266c261acb", + urls = [ + "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.28.0/rules_go-v0.28.0.zip", + "https://github.com/bazelbuild/rules_go/releases/download/v0.28.0/rules_go-v0.28.0.zip", + ], +) load( "@rules_haskell//haskell:toolchain.bzl", "rules_haskell_toolchains", @@ -267,11 +275,33 @@ EOF # Append toolchain and zlib rules case "${MODE}" in "bindists") cat <<-EOF + load( + "@rules_haskell//haskell:ghc_bindist_hadrian.bzl", + "haskell_register_ghc_bindists_hadrian", + ) + test_ghcopts = [ + "-XStandaloneDeriving", # Flag used at compile time + "-threaded", # Flag used at link time + # Used by `tests/repl-flags` + "-DTESTS_TOOLCHAIN_COMPILER_FLAGS", + # this is the default, so it does not harm other tests + "-XNoOverloadedStrings", + ] + test_cabalopts = [ + # Used by `tests/cabal-toolchain-flags` + "--ghc-option=-DTESTS_TOOLCHAIN_CABALOPTS", + "--haddock-option=--optghc=-DTESTS_TOOLCHAIN_CABALOPTS", + ] # Download a GHC binary distribution from haskell.org and register it as a toolchain. - rules_haskell_toolchains( - version = "${GHC_VERSION}", + haskell_register_ghc_bindists_hadrian( + url = "https://downloads.haskell.org/~ghc/9.6.1/ghc-9.6.1-x86_64-deb9-linux.tar.xz", + sha256 = "3c727e93a82ff039fbedd6645518859849130a0fc93b7181cd69a41800aa639c", + strip_prefix = "ghc-9.6.1-x86_64-unknown-linux", + version = "9.6.1", + target = "x86_64-unknown-linux", + cabalopts = test_cabalopts, + ghcopts = test_ghcopts, ) - http_archive( name = "zlib.dev", build_file = "//:${ZLIB_BUILD_FILE}", From 1df3881e80af0f5db4e044d4f140ecfa8a44c4fe Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Mon, 15 May 2023 11:01:36 +0200 Subject: [PATCH 11/41] Use GHC 9.6.1 for tests --- constants.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/constants.bzl b/constants.bzl index a1a0ccada..4f6a61762 100644 --- a/constants.bzl +++ b/constants.bzl @@ -1,2 +1,2 @@ -test_ghc_version = "9.2.5" +test_ghc_version = "9.6.1" test_asterius_version = "0.0.1" From d303a1f636976fcebe47c8fe1e91b45e5dcf37d3 Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Fri, 19 May 2023 12:48:46 +0200 Subject: [PATCH 12/41] Fix includedir --- haskell/ghc_bindist_hadrian.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/haskell/ghc_bindist_hadrian.bzl b/haskell/ghc_bindist_hadrian.bzl index b6b1a2fc2..54c3690b7 100644 --- a/haskell/ghc_bindist_hadrian.bzl +++ b/haskell/ghc_bindist_hadrian.bzl @@ -113,7 +113,7 @@ find {lib}/package.conf.d -name "rts-*.conf" -print0 | \\ generated_include_filegroup = define_rule( "copy_filegroups_to_this_package", name = "generated_include_filegroup", - srcs = [":{}".format(docdir)], + srcs = [":include"], ) toolchain_libraries = pkgdb_to_bzl(ctx, filepaths, libdir)["file_content"] From 9dfdfdf7f07ce126fa35c14fc63d6a96d7c59a2e Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Fri, 19 May 2023 14:32:25 +0200 Subject: [PATCH 13/41] Update stackage snapshot --- stackage_snapshot.json | 75 +++++++++++++++++++++--------------------- stackage_snapshot.yaml | 8 +---- 2 files changed, 39 insertions(+), 44 deletions(-) diff --git a/stackage_snapshot.json b/stackage_snapshot.json index e9b828cc4..4b83a6daa 100644 --- a/stackage_snapshot.json +++ b/stackage_snapshot.json @@ -1,28 +1,28 @@ { - "__GENERATED_FILE_DO_NOT_MODIFY_MANUALLY": 1257643182, - "all-cabal-hashes": "https://raw.githubusercontent.com/commercialhaskell/all-cabal-hashes/c74af1256291cf0dc83731d2b2088cf4422fcfd3", + "__GENERATED_FILE_DO_NOT_MODIFY_MANUALLY": 50776380, + "all-cabal-hashes": "https://raw.githubusercontent.com/commercialhaskell/all-cabal-hashes/c2e1693fe34c7825e36dbe10bfbf921ed344d594", "resolved": { - "Cabal": {"dependencies":["array","base","binary","bytestring","containers","deepseq","directory","filepath","mtl","parsec","pretty","process","text","time","transformers","unix"],"location":{"type":"git","url":"https://github.com/tweag/cabal","commit":"42f04c3f639f10dc3c7981a0c663bfe08ad833cb","subdir":"Cabal"},"name":"Cabal","version":"3.6.3.0"}, + "Cabal": {"dependencies":[],"location":{"type":"core"},"name":"Cabal","version":"3.6.3.0"}, "HUnit": {"dependencies":["base","call-stack","deepseq"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/HUnit-1.6.2.0/HUnit-1.6.2.0.tar.gz"},"name":"HUnit","pinned":{"url":["https://hackage.haskell.org/package/HUnit-1.6.2.0/HUnit-1.6.2.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/HUnit-1.6.2.0.tar.gz"],"sha256":"b0b7538871ffc058486fc00740886d2f3172f8fa6869936bfe83a5e10bd744ab","cabal-sha256":"1a79174e8af616117ad39464cac9de205ca923da6582825e97c10786fda933a4"},"version":"1.6.2.0"}, "QuickCheck": {"dependencies":["base","containers","deepseq","random","splitmix","template-haskell","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/QuickCheck-2.14.2/QuickCheck-2.14.2.tar.gz"},"name":"QuickCheck","pinned":{"url":["https://hackage.haskell.org/package/QuickCheck-2.14.2/QuickCheck-2.14.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/QuickCheck-2.14.2.tar.gz"],"sha256":"d87b6c85696b601175274361fa62217894401e401e150c3c5d4013ac53cd36f3","cabal-sha256":"4ce29211223d5e6620ebceba34a3ca9ccf1c10c0cf387d48aea45599222ee5aa"},"version":"2.14.2"}, "StateVar": {"dependencies":["base","stm","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/StateVar-1.2.2/StateVar-1.2.2.tar.gz"},"name":"StateVar","pinned":{"url":["https://hackage.haskell.org/package/StateVar-1.2.2/StateVar-1.2.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/StateVar-1.2.2.tar.gz"],"sha256":"5e4b39da395656a59827b0280508aafdc70335798b50e5d6fd52596026251825","cabal-sha256":"3c022c00485fe165e3080d5da6b3ca9c9b02f62c5deebc584d1b3d1309ce673e"},"version":"1.2.2"}, - "alex": {"dependencies":["array","base","containers","directory"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/alex-3.2.7.1/alex-3.2.7.1.tar.gz"},"name":"alex","pinned":{"url":["https://hackage.haskell.org/package/alex-3.2.7.1/alex-3.2.7.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/alex-3.2.7.1.tar.gz"],"sha256":"9bd2f1a27e8f1b2ffdb5b2fbd3ed82b6f0e85191459a1b24ffcbef4e68a81bec","cabal-sha256":"ab26a38cefae59403f746370e5a0c943b8d5bda098eb83f37052b2429ee780ce"},"version":"3.2.7.1"}, + "alex": {"dependencies":["array","base","containers","directory"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/alex-3.2.7.4/alex-3.2.7.4.tar.gz"},"name":"alex","pinned":{"url":["https://hackage.haskell.org/package/alex-3.2.7.4/alex-3.2.7.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/alex-3.2.7.4.tar.gz"],"sha256":"8a13fa01ea00883aa3d75d15ce848835b18631b8c9a4966961492d7c6095226f","cabal-sha256":"91f4b0bf2f0eca6966bab39975adc440a9d9929dc8729bf92c95c3296dcb25b9"},"version":"3.2.7.4"}, "ansi-terminal": {"dependencies":["base","colour"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/ansi-terminal-0.11.4/ansi-terminal-0.11.4.tar.gz"},"name":"ansi-terminal","pinned":{"url":["https://hackage.haskell.org/package/ansi-terminal-0.11.4/ansi-terminal-0.11.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/ansi-terminal-0.11.4.tar.gz"],"sha256":"7898e48f0a535c1857cde52c803f28096ba89759461fe4d157fd55dcdb420e25","cabal-sha256":"410737137c798e23339a08435a5511785ebf1db08700e37debbd7801cf73fc82"},"version":"0.11.4"}, - "ansi-wl-pprint": {"dependencies":["ansi-terminal","base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/ansi-wl-pprint-0.6.9/ansi-wl-pprint-0.6.9.tar.gz"},"name":"ansi-wl-pprint","pinned":{"url":["https://hackage.haskell.org/package/ansi-wl-pprint-0.6.9/ansi-wl-pprint-0.6.9.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/ansi-wl-pprint-0.6.9.tar.gz"],"sha256":"a7b2e8e7cd3f02f2954e8b17dc60a0ccd889f49e2068ebb15abfa1d42f7a4eac","cabal-sha256":"212144ea0623b1170807a4162db05d87f26cf10b334aeadd0edb377aba06a1ce"},"version":"0.6.9"}, + "ansi-wl-pprint": {"dependencies":["ansi-terminal","base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/ansi-wl-pprint-0.6.9/ansi-wl-pprint-0.6.9.tar.gz"},"name":"ansi-wl-pprint","pinned":{"url":["https://hackage.haskell.org/package/ansi-wl-pprint-0.6.9/ansi-wl-pprint-0.6.9.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/ansi-wl-pprint-0.6.9.tar.gz"],"sha256":"a7b2e8e7cd3f02f2954e8b17dc60a0ccd889f49e2068ebb15abfa1d42f7a4eac","cabal-sha256":"fb737bc96e2aef34ad595d54ced7a73f648c521ebcb00fe0679aff45ccd49212"},"version":"0.6.9"}, "array": {"dependencies":[],"location":{"type":"core"},"name":"array","version":"0.5.4.0"}, - "async": {"dependencies":["base","hashable","stm"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/async-2.2.4/async-2.2.4.tar.gz"},"name":"async","pinned":{"url":["https://hackage.haskell.org/package/async-2.2.4/async-2.2.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/async-2.2.4.tar.gz"],"sha256":"484df85be0e76c4fed9376451e48e1d0c6e97952ce79735b72d54297e7e0a725","cabal-sha256":"2b9409023536823233ce3134558565d01b3382e651fa54ac8cb8a99967e023c9"},"version":"2.2.4"}, + "async": {"dependencies":["base","hashable","stm"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/async-2.2.4/async-2.2.4.tar.gz"},"name":"async","pinned":{"url":["https://hackage.haskell.org/package/async-2.2.4/async-2.2.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/async-2.2.4.tar.gz"],"sha256":"484df85be0e76c4fed9376451e48e1d0c6e97952ce79735b72d54297e7e0a725","cabal-sha256":"46367dc0c8326dcbeb7b93f200b567491c2f6029bccf822b8bb26ee660397e08"},"version":"2.2.4"}, "atomic-primops": {"dependencies":["base","ghc-prim","primitive"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/atomic-primops-0.8.4/atomic-primops-0.8.4.tar.gz"},"name":"atomic-primops","pinned":{"url":["https://hackage.haskell.org/package/atomic-primops-0.8.4/atomic-primops-0.8.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/atomic-primops-0.8.4.tar.gz"],"sha256":"22a8617eb9e221b5daee1ae26ccce279ce3d7a53d76e82c767708f90a6c72d3e","cabal-sha256":"5218db0d8d4efe203a06c4643a0c6aeb3ab1abe159e92c122decc4f0dd1b5f38"},"version":"0.8.4"}, - "attoparsec": {"dependencies":["array","base","bytestring","containers","deepseq","ghc-prim","scientific","text","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/attoparsec-0.14.4/attoparsec-0.14.4.tar.gz"},"name":"attoparsec","pinned":{"url":["https://hackage.haskell.org/package/attoparsec-0.14.4/attoparsec-0.14.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/attoparsec-0.14.4.tar.gz"],"sha256":"3f337fe58624565de12426f607c23e60c7b09c86b4e3adfc827ca188c9979e6c","cabal-sha256":"c0569d86c02cadd403017ea414dcb5e4f7de5380de0d8a92b9337cad84cd5e02"},"version":"0.14.4"}, + "attoparsec": {"dependencies":["array","base","bytestring","containers","deepseq","ghc-prim","scientific","text","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/attoparsec-0.14.4/attoparsec-0.14.4.tar.gz"},"name":"attoparsec","pinned":{"url":["https://hackage.haskell.org/package/attoparsec-0.14.4/attoparsec-0.14.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/attoparsec-0.14.4.tar.gz"],"sha256":"3f337fe58624565de12426f607c23e60c7b09c86b4e3adfc827ca188c9979e6c","cabal-sha256":"50475b722305175f57a3ee3dbaee10aa4b91f61c9717b85b718a7df37c223fb2"},"version":"0.14.4"}, "base": {"dependencies":[],"location":{"type":"core"},"name":"base","version":"4.16.4.0"}, "base-compat": {"dependencies":["base","ghc-prim","unix"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/base-compat-0.12.2/base-compat-0.12.2.tar.gz"},"name":"base-compat","pinned":{"url":["https://hackage.haskell.org/package/base-compat-0.12.2/base-compat-0.12.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/base-compat-0.12.2.tar.gz"],"sha256":"a62adc883a5ac436f80e4ae02c3c56111cf1007492f267c291139a668d2150bd","cabal-sha256":"85d820a15e3f00f1781ac939cb9cdccdcc6f38c43e4c74a6e83e5d75f67b61a0"},"version":"0.12.2"}, "base-compat-batteries": {"dependencies":["base","base-compat","ghc-prim"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/base-compat-batteries-0.12.2/base-compat-batteries-0.12.2.tar.gz"},"name":"base-compat-batteries","pinned":{"url":["https://hackage.haskell.org/package/base-compat-batteries-0.12.2/base-compat-batteries-0.12.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/base-compat-batteries-0.12.2.tar.gz"],"sha256":"ede9092e07f904e0759160bf1ecd3fb7eb043bae6dc89a37c3dc94829ec5eb99","cabal-sha256":"ecf0bb2b39be54f1ffa185d37663702b0651d34d1cdcc32d32bb8f7279396afe"},"version":"0.12.2"}, - "base-orphans": {"dependencies":["base","ghc-prim"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/base-orphans-0.8.7/base-orphans-0.8.7.tar.gz"},"name":"base-orphans","pinned":{"url":["https://hackage.haskell.org/package/base-orphans-0.8.7/base-orphans-0.8.7.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/base-orphans-0.8.7.tar.gz"],"sha256":"888fd67f0dbe932778f5b170922ce80d0dcab1680ee98f1d6fcc362f20d9e447","cabal-sha256":"58d5514b688ec037f53b9d60097b9d87f6b3847da68f65124987d67222c3a334"},"version":"0.8.7"}, - "bifunctors": {"dependencies":["base","base-orphans","comonad","containers","tagged","template-haskell","th-abstraction","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/bifunctors-5.5.13/bifunctors-5.5.13.tar.gz"},"name":"bifunctors","pinned":{"url":["https://hackage.haskell.org/package/bifunctors-5.5.13/bifunctors-5.5.13.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/bifunctors-5.5.13.tar.gz"],"sha256":"26cc27ade3796cf03bd680f98ebb7b8c0d7fd1b67c1894dc3635f734fba7dbd7","cabal-sha256":"66f1c1d0cba5de9d8810e2ef0be700b98d3689482f605cc46a69283e92a60840"},"version":"5.5.13"}, + "base-orphans": {"dependencies":["base","ghc-prim"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/base-orphans-0.8.8.2/base-orphans-0.8.8.2.tar.gz"},"name":"base-orphans","pinned":{"url":["https://hackage.haskell.org/package/base-orphans-0.8.8.2/base-orphans-0.8.8.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/base-orphans-0.8.8.2.tar.gz"],"sha256":"61cae7063884128dc98596ab7d8e6d896f6b0fa3da4e12310c850c8c08825092","cabal-sha256":"b62d60c8b7c507f0d0085925fad398e4fcda928c14b524be0148effd99cfb97d"},"version":"0.8.8.2"}, + "bifunctors": {"dependencies":["base","base-orphans","comonad","containers","tagged","template-haskell","th-abstraction","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/bifunctors-5.5.15/bifunctors-5.5.15.tar.gz"},"name":"bifunctors","pinned":{"url":["https://hackage.haskell.org/package/bifunctors-5.5.15/bifunctors-5.5.15.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/bifunctors-5.5.15.tar.gz"],"sha256":"d6359d50d359dd6048dbf6d56c7628211a1785aab9174177faa6d2d8b0d9e3b7","cabal-sha256":"5ebaf9a1996de38ad9d77bec37a5585b6461b34f39446e8f1cadae7689a12bfd"},"version":"5.5.15"}, "binary": {"dependencies":[],"location":{"type":"core"},"name":"binary","version":"0.8.9.0"}, - "bytestring": {"dependencies":[],"location":{"type":"core"},"name":"bytestring","version":"0.11.3.1"}, + "bytestring": {"dependencies":[],"location":{"type":"core"},"name":"bytestring","version":"0.11.4.0"}, "bytestring-builder": {"dependencies":["base","bytestring","deepseq"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/bytestring-builder-0.10.8.2.0/bytestring-builder-0.10.8.2.0.tar.gz"},"name":"bytestring-builder","pinned":{"url":["https://hackage.haskell.org/package/bytestring-builder-0.10.8.2.0/bytestring-builder-0.10.8.2.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/bytestring-builder-0.10.8.2.0.tar.gz"],"sha256":"27faef6db27c5be5a3715fd68b93725853e0e668849eaf92ce7c33cef9cb2c3f","cabal-sha256":"6b2b812cdac53f5a2c82376a416dde04adbb5ca3e1604c0d075368a0498f762b"},"version":"0.10.8.2.0"}, "c2hs": {"dependencies":["array","base","bytestring","containers","directory","dlist","filepath","language-c","pretty","process"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/c2hs-0.28.8/c2hs-0.28.8.tar.gz"},"name":"c2hs","pinned":{"url":["https://hackage.haskell.org/package/c2hs-0.28.8/c2hs-0.28.8.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/c2hs-0.28.8.tar.gz"],"sha256":"390632cffc561c32483af474aac50168a68f0fa382096552e37749923617884c","cabal-sha256":"c399132e2273e70770be403fba4795d7d8c60d7bd147f0ef174342bebbd44392"},"version":"0.28.8"}, - "cabal-doctest": {"dependencies":["Cabal","base","directory","filepath"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/cabal-doctest-1.0.9/cabal-doctest-1.0.9.tar.gz"},"name":"cabal-doctest","pinned":{"url":["https://hackage.haskell.org/package/cabal-doctest-1.0.9/cabal-doctest-1.0.9.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/cabal-doctest-1.0.9.tar.gz"],"sha256":"5556088496111d33810c4ae6c4a065bb37fa3315e9e8891e8000b1ab6707ba73","cabal-sha256":"21823c6227a483b4faf210d7a55d435563ff69ddf94b48b8af1bba878196c820"},"version":"1.0.9"}, + "cabal-doctest": {"dependencies":["Cabal","base","directory","filepath"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/cabal-doctest-1.0.9/cabal-doctest-1.0.9.tar.gz"},"name":"cabal-doctest","pinned":{"url":["https://hackage.haskell.org/package/cabal-doctest-1.0.9/cabal-doctest-1.0.9.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/cabal-doctest-1.0.9.tar.gz"],"sha256":"5556088496111d33810c4ae6c4a065bb37fa3315e9e8891e8000b1ab6707ba73","cabal-sha256":"6dea0dbd1457f43d96ce1cfb1bab8b9f55d4fb82940e2bfa5aad78e6e2260656"},"version":"1.0.9"}, "call-stack": {"dependencies":["base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/call-stack-0.4.0/call-stack-0.4.0.tar.gz"},"name":"call-stack","pinned":{"url":["https://hackage.haskell.org/package/call-stack-0.4.0/call-stack-0.4.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/call-stack-0.4.0.tar.gz"],"sha256":"430bcf8a3404f7e55319573c0b807b1356946f0c8f289bb3d9afb279c636b87b","cabal-sha256":"ac44d2c00931dc20b01750da8c92ec443eb63a7231e8550188cb2ac2385f7feb"},"version":"0.4.0"}, "clock": {"dependencies":["base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/clock-0.8.3/clock-0.8.3.tar.gz"},"name":"clock","pinned":{"url":["https://hackage.haskell.org/package/clock-0.8.3/clock-0.8.3.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/clock-0.8.3.tar.gz"],"sha256":"845ce5db4c98cefd517323e005f87effceff886987305e421c4ef616dc0505d1","cabal-sha256":"a692159828c2cd278eaec317b3a7e9fb6d7b787c8a19f086004d15d9fa1fd72c"},"version":"0.8.3"}, "code-page": {"dependencies":["base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/code-page-0.2.1/code-page-0.2.1.tar.gz"},"name":"code-page","pinned":{"url":["https://hackage.haskell.org/package/code-page-0.2.1/code-page-0.2.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/code-page-0.2.1.tar.gz"],"sha256":"b2f90e19c61ed8a6ff7295f7f123d4a9913c790d4cf2c6029bc299293fdb2aaa","cabal-sha256":"fe596b0f421abd2894fdb7049b3d76230eb1de6e04e9f635e2695dd55ded856e"},"version":"0.2.1"}, @@ -32,6 +32,7 @@ "conduit-extra": {"dependencies":["async","attoparsec","base","bytestring","conduit","directory","filepath","network","primitive","process","resourcet","stm","streaming-commons","text","transformers","typed-process","unliftio-core"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/conduit-extra-1.3.6/conduit-extra-1.3.6.tar.gz"},"name":"conduit-extra","pinned":{"url":["https://hackage.haskell.org/package/conduit-extra-1.3.6/conduit-extra-1.3.6.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/conduit-extra-1.3.6.tar.gz"],"sha256":"8950c38049d892c38590d389bed49ecf880671f58ec63dd4709d9fe3d4b8f153","cabal-sha256":"83303e6fea78a683fdbb41682fc8dbc47b1d8830da1f09e88940f9a744a7f984"},"version":"1.3.6"}, "containers": {"dependencies":[],"location":{"type":"core"},"name":"containers","version":"0.6.5.1"}, "contravariant": {"dependencies":["StateVar","base","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/contravariant-1.5.5/contravariant-1.5.5.tar.gz"},"name":"contravariant","pinned":{"url":["https://hackage.haskell.org/package/contravariant-1.5.5/contravariant-1.5.5.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/contravariant-1.5.5.tar.gz"],"sha256":"062fd66580d7aad0b5ba93e644ffa7feee69276ef50f20d4ed9f1deb7642dffa","cabal-sha256":"470ed0e040e879e2da4af1b2c8f94e199f6135852a8107858d5ae0a95365835f"},"version":"1.5.5"}, + "data-array-byte": {"dependencies":["base","deepseq","template-haskell"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/data-array-byte-0.1.0.1/data-array-byte-0.1.0.1.tar.gz"},"name":"data-array-byte","pinned":{"url":["https://hackage.haskell.org/package/data-array-byte-0.1.0.1/data-array-byte-0.1.0.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/data-array-byte-0.1.0.1.tar.gz"],"sha256":"1bb6eca0b3e02d057fe7f4e14c81ef395216f421ab30fdaa1b18017c9c025600","cabal-sha256":"2ef1bd3511e82ba56f7f23cd793dd2da84338a1e7c2cbea5b151417afe3baada"},"version":"0.1.0.1"}, "data-default-class": {"dependencies":["base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/data-default-class-0.1.2.0/data-default-class-0.1.2.0.tar.gz"},"name":"data-default-class","pinned":{"url":["https://hackage.haskell.org/package/data-default-class-0.1.2.0/data-default-class-0.1.2.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/data-default-class-0.1.2.0.tar.gz"],"sha256":"4f01b423f000c3e069aaf52a348564a6536797f31498bb85c3db4bd2d0973e56","cabal-sha256":"63e62120b7efd733a5a17cf59ceb43268e9a929c748127172d7d42f4a336e327"},"version":"0.1.2.0"}, "deepseq": {"dependencies":[],"location":{"type":"core"},"name":"deepseq","version":"1.4.6.1"}, "directory": {"dependencies":[],"location":{"type":"core"},"name":"directory","version":"1.3.6.2"}, @@ -41,75 +42,75 @@ "exceptions": {"dependencies":[],"location":{"type":"core"},"name":"exceptions","version":"0.10.4"}, "filepath": {"dependencies":[],"location":{"type":"core"},"name":"filepath","version":"1.4.2.2"}, "first-class-families": {"dependencies":["base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/first-class-families-0.8.0.1/first-class-families-0.8.0.1.tar.gz"},"name":"first-class-families","pinned":{"url":["https://hackage.haskell.org/package/first-class-families-0.8.0.1/first-class-families-0.8.0.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/first-class-families-0.8.0.1.tar.gz"],"sha256":"4a1c8fbdbe01757ea8dc3190050d7a4a72c86e205d23676182292fe192c1da72","cabal-sha256":"d7a60485a2f392818808d4decbc6af7c20281713ec1d81948747f1c9c8c2b145"},"version":"0.8.0.1"}, - "generic-deriving": {"dependencies":["base","containers","ghc-prim","template-haskell","th-abstraction"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/generic-deriving-1.14.2/generic-deriving-1.14.2.tar.gz"},"name":"generic-deriving","pinned":{"url":["https://hackage.haskell.org/package/generic-deriving-1.14.2/generic-deriving-1.14.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/generic-deriving-1.14.2.tar.gz"],"sha256":"265e351117d451afaa37821ce91b44a02611cc94c7ed917a19e1efb0cc63aa2f","cabal-sha256":"55ea5f8c2c386f1791ca0053c89e6dd9d7d8c8fda0bd677f230164cad891539b"},"version":"1.14.2"}, - "ghc": {"dependencies":[],"location":{"type":"core"},"name":"ghc","version":"9.2.5"}, + "generic-deriving": {"dependencies":["base","containers","ghc-prim","template-haskell","th-abstraction"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/generic-deriving-1.14.4/generic-deriving-1.14.4.tar.gz"},"name":"generic-deriving","pinned":{"url":["https://hackage.haskell.org/package/generic-deriving-1.14.4/generic-deriving-1.14.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/generic-deriving-1.14.4.tar.gz"],"sha256":"372b87b2c91ed4ceff8602024a484944f4653456066755803b5cb268fed8195c","cabal-sha256":"8395764ff8bef9e688b9681dff3bcd0dbb324a22192e5981bcba10afa75b9ac4"},"version":"1.14.4"}, + "ghc": {"dependencies":[],"location":{"type":"core"},"name":"ghc","version":"9.2.7"}, "ghc-bignum": {"dependencies":[],"location":{"type":"core"},"name":"ghc-bignum","version":"1.2"}, - "ghc-boot": {"dependencies":[],"location":{"type":"core"},"name":"ghc-boot","version":"9.2.5"}, - "ghc-boot-th": {"dependencies":[],"location":{"type":"core"},"name":"ghc-boot-th","version":"9.2.5"}, + "ghc-boot": {"dependencies":[],"location":{"type":"core"},"name":"ghc-boot","version":"9.2.7"}, + "ghc-boot-th": {"dependencies":[],"location":{"type":"core"},"name":"ghc-boot-th","version":"9.2.7"}, "ghc-check": {"dependencies":["base","containers","directory","filepath","ghc","ghc-boot","ghc-paths","process","safe-exceptions","template-haskell","th-compat","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/ghc-check-0.5.0.8/ghc-check-0.5.0.8.tar.gz"},"name":"ghc-check","pinned":{"url":["https://hackage.haskell.org/package/ghc-check-0.5.0.8/ghc-check-0.5.0.8.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/ghc-check-0.5.0.8.tar.gz"],"sha256":"1025a8353fb7c318b27b8dc6b268d22f1f64c271031ed0ce4defb0f9100d7cd4","cabal-sha256":"4abee5e907b63c986ff4f130fa5a02a933a165af18bda98bff380763a9c1ad47"},"version":"0.5.0.8"}, - "ghc-heap": {"dependencies":[],"location":{"type":"core"},"name":"ghc-heap","version":"9.2.5"}, + "ghc-heap": {"dependencies":[],"location":{"type":"core"},"name":"ghc-heap","version":"9.2.7"}, "ghc-paths": {"dependencies":["base"],"location":{"type":"vendored"},"name":"ghc-paths","version":"0.1.0.11"}, "ghc-prim": {"dependencies":[],"location":{"type":"core"},"name":"ghc-prim","version":"0.8.0"}, "ghc-source-gen": {"dependencies":["base","ghc"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/ghc-source-gen-0.4.3.0/ghc-source-gen-0.4.3.0.tar.gz"},"name":"ghc-source-gen","pinned":{"url":["https://hackage.haskell.org/package/ghc-source-gen-0.4.3.0/ghc-source-gen-0.4.3.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/ghc-source-gen-0.4.3.0.tar.gz"],"sha256":"0e88038ab714cbe420da8ea15f5cd78565828e9dd956a461283bbe15e9d418d2","cabal-sha256":"9058ddc2e3201d7b2e5a91b79d76f952c5fb01fb34d742143e9c9b365589ad35"},"version":"0.4.3.0"}, - "happy": {"dependencies":["array","base","containers","mtl"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/happy-1.20.0/happy-1.20.0.tar.gz"},"name":"happy","pinned":{"url":["https://hackage.haskell.org/package/happy-1.20.0/happy-1.20.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/happy-1.20.0.tar.gz"],"sha256":"3b1d3a8f93a2723b554d9f07b2cd136be1a7b2fcab1855b12b7aab5cbac8868c","cabal-sha256":"5d47dc221a9fe964e36aaaa2e1ab7e8f085a225fd6528d6eff310b92360bbe99"},"version":"1.20.0"}, - "hashable": {"dependencies":["base","bytestring","containers","deepseq","ghc-bignum","ghc-prim","text"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/hashable-1.4.1.0/hashable-1.4.1.0.tar.gz"},"name":"hashable","pinned":{"url":["https://hackage.haskell.org/package/hashable-1.4.1.0/hashable-1.4.1.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/hashable-1.4.1.0.tar.gz"],"sha256":"e1b305c280e66ad827edeaedd6933b9fc4174f626882877eab2a08344e665e87","cabal-sha256":"50b2f002c68fe67730ee7a3cd8607486197dd99b084255005ad51ecd6970a41b"},"version":"1.4.1.0"}, + "happy": {"dependencies":["array","base","containers","mtl"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/happy-1.20.1.1/happy-1.20.1.1.tar.gz"},"name":"happy","pinned":{"url":["https://hackage.haskell.org/package/happy-1.20.1.1/happy-1.20.1.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/happy-1.20.1.1.tar.gz"],"sha256":"8b4e7dc5a6c5fd666f8f7163232931ab28746d0d17da8fa1cbd68be9e878881b","cabal-sha256":"a381633c5e8f9e9e5a8e1900930ce13172397b4677fcfcc08cd38eb3f73b61b1"},"version":"1.20.1.1"}, + "hashable": {"dependencies":["base","bytestring","containers","data-array-byte","deepseq","filepath","ghc-bignum","ghc-prim","text"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/hashable-1.4.2.0/hashable-1.4.2.0.tar.gz"},"name":"hashable","pinned":{"url":["https://hackage.haskell.org/package/hashable-1.4.2.0/hashable-1.4.2.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/hashable-1.4.2.0.tar.gz"],"sha256":"1b4000ea82b81f69d46d0af4152c10c6303873510738e24cfc4767760d30e3f8","cabal-sha256":"585792335d5541dba78fa8dfcb291a89cd5812a281825ff7a44afa296ab5d58a"},"version":"1.4.2.0"}, "hspec": {"dependencies":["QuickCheck","base","hspec-core","hspec-discover","hspec-expectations"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/hspec-2.9.7/hspec-2.9.7.tar.gz"},"name":"hspec","pinned":{"url":["https://hackage.haskell.org/package/hspec-2.9.7/hspec-2.9.7.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/hspec-2.9.7.tar.gz"],"sha256":"81ddacf76445fb547010d3582ec9d81d7cd9285258ca74bfeefd653525765a24","cabal-sha256":"68732c76946f111db3ecf28fa1ab11f1468c287448b139e57d543bd25a382cf0"},"version":"2.9.7"}, "hspec-core": {"dependencies":["HUnit","QuickCheck","ansi-terminal","array","base","call-stack","clock","deepseq","directory","filepath","ghc","ghc-boot-th","hspec-expectations","quickcheck-io","random","setenv","stm","tf-random","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/hspec-core-2.9.7/hspec-core-2.9.7.tar.gz"},"name":"hspec-core","pinned":{"url":["https://hackage.haskell.org/package/hspec-core-2.9.7/hspec-core-2.9.7.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/hspec-core-2.9.7.tar.gz"],"sha256":"16819b4b10fd22be4a72ec7f919417f722b0eba448c62be538e34e8e23fe1910","cabal-sha256":"153ca954ceb8eb7dff782d3de9af59553bc54284a45e7085aca5b443a5486111"},"version":"2.9.7"}, "hspec-discover": {"dependencies":["base","directory","filepath"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/hspec-discover-2.9.7/hspec-discover-2.9.7.tar.gz"},"name":"hspec-discover","pinned":{"url":["https://hackage.haskell.org/package/hspec-discover-2.9.7/hspec-discover-2.9.7.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/hspec-discover-2.9.7.tar.gz"],"sha256":"65e933fe21a88a15409b0ec4d6d67fccacbaa410b96ece9e59e81a2e7b9b6614","cabal-sha256":"7b8e52d85c07e8cfed6723255f738fb69ae08d3c0edfd3e458837496897ee629"},"version":"2.9.7"}, "hspec-expectations": {"dependencies":["HUnit","base","call-stack"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/hspec-expectations-0.8.2/hspec-expectations-0.8.2.tar.gz"},"name":"hspec-expectations","pinned":{"url":["https://hackage.haskell.org/package/hspec-expectations-0.8.2/hspec-expectations-0.8.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/hspec-expectations-0.8.2.tar.gz"],"sha256":"819607ea1faf35ce5be34be61c6f50f3389ea43892d56fb28c57a9f5d54fb4ef","cabal-sha256":"e2db24881baadc2d9d23b03cb629e80dcbda89a6b04ace9adb5f4d02ef8b31aa"},"version":"0.8.2"}, - "indexed-traversable": {"dependencies":["array","base","containers","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/indexed-traversable-0.1.2/indexed-traversable-0.1.2.tar.gz"},"name":"indexed-traversable","pinned":{"url":["https://hackage.haskell.org/package/indexed-traversable-0.1.2/indexed-traversable-0.1.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/indexed-traversable-0.1.2.tar.gz"],"sha256":"516858ee7198b1fed1b93c665157f9855fd947379db7f115d48c1b0d670e698d","cabal-sha256":"52a1b708abd921f91a5977f6ae53c4aa2b33f7c30be0fff17173f658b34c5350"},"version":"0.1.2"}, + "indexed-traversable": {"dependencies":["array","base","containers","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/indexed-traversable-0.1.2.1/indexed-traversable-0.1.2.1.tar.gz"},"name":"indexed-traversable","pinned":{"url":["https://hackage.haskell.org/package/indexed-traversable-0.1.2.1/indexed-traversable-0.1.2.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/indexed-traversable-0.1.2.1.tar.gz"],"sha256":"fe854c10285debc7d6fe3e09da0928a740ebc091ad2911ae695bb007e6f746a4","cabal-sha256":"154b4649199a602dea948a93cb34a6c4be71576c4f78410733dd9f6bc79b6e0b"},"version":"0.1.2.1"}, "integer-logarithms": {"dependencies":["array","base","ghc-bignum","ghc-prim"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/integer-logarithms-1.0.3.1/integer-logarithms-1.0.3.1.tar.gz"},"name":"integer-logarithms","pinned":{"url":["https://hackage.haskell.org/package/integer-logarithms-1.0.3.1/integer-logarithms-1.0.3.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/integer-logarithms-1.0.3.1.tar.gz"],"sha256":"9b0a9f9fab609b15cd015865721fb05f744a1bc77ae92fd133872de528bbea7f","cabal-sha256":"336fb40c3af19a59dbeb4e5b7bffe4b4c7fa04ab06006a8d4b70b1febc1bb4ca"},"version":"1.0.3.1"}, - "language-c": {"dependencies":["alex","array","base","bytestring","containers","deepseq","directory","filepath","happy","mtl","pretty","process"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/language-c-0.9.1/language-c-0.9.1.tar.gz"},"name":"language-c","pinned":{"url":["https://hackage.haskell.org/package/language-c-0.9.1/language-c-0.9.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/language-c-0.9.1.tar.gz"],"sha256":"94359566eb5da62f539fa62500f8a861db4e3eafb956d66c6821d6ffad96ad3c","cabal-sha256":"381f68bb37c00afb0f81b936f6a60066b588b5b4d4ae83a468477739ab02db01"},"version":"0.9.1"}, + "language-c": {"dependencies":["alex","array","base","bytestring","containers","deepseq","directory","filepath","happy","mtl","pretty","process"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/language-c-0.9.2/language-c-0.9.2.tar.gz"},"name":"language-c","pinned":{"url":["https://hackage.haskell.org/package/language-c-0.9.2/language-c-0.9.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/language-c-0.9.2.tar.gz"],"sha256":"b2310d2fda16df72e9f8f63ef18bec2e09ae3aff5891dc948c3d9cb72cef6cb3","cabal-sha256":"a4b77129d7d30d777e0f203ba9c18b88f4791f95c079fef573b554f915dcf57d"},"version":"0.9.2"}, "lens-family": {"dependencies":["base","containers","lens-family-core","mtl","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/lens-family-2.1.2/lens-family-2.1.2.tar.gz"},"name":"lens-family","pinned":{"url":["https://hackage.haskell.org/package/lens-family-2.1.2/lens-family-2.1.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/lens-family-2.1.2.tar.gz"],"sha256":"2b60afc3afc03b6e328fc96e291e21bb0a63b563657cabe7ba5febd471283648","cabal-sha256":"c13af34889ed9637b2dbd4542122c01a6ec1351cc6dda673de0079f9b02747ef"},"version":"2.1.2"}, "lens-family-core": {"dependencies":["base","containers","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/lens-family-core-2.1.2/lens-family-core-2.1.2.tar.gz"},"name":"lens-family-core","pinned":{"url":["https://hackage.haskell.org/package/lens-family-core-2.1.2/lens-family-core-2.1.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/lens-family-core-2.1.2.tar.gz"],"sha256":"1b5a997276c8b77a96f99f48b95b204d34f3bb84fa3691747cd30bc8c76873b6","cabal-sha256":"702013af981089f991c93598762b8804314266c2bd7d92fc35fb6a8b62af1883"},"version":"2.1.2"}, "mmorph": {"dependencies":["base","mtl","transformers","transformers-compat"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/mmorph-1.2.0/mmorph-1.2.0.tar.gz"},"name":"mmorph","pinned":{"url":["https://hackage.haskell.org/package/mmorph-1.2.0/mmorph-1.2.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/mmorph-1.2.0.tar.gz"],"sha256":"61338058eb676b466a462ca45d59f436a77a3bd6b816e4268c6d88522b6a4280","cabal-sha256":"df9b213ec18f811cb3137b478d148f3f1680ee43f841cb775835fa282fdb0295"},"version":"1.2.0"}, "mono-traversable": {"dependencies":["base","bytestring","containers","hashable","split","text","transformers","unordered-containers","vector","vector-algorithms"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/mono-traversable-1.0.15.3/mono-traversable-1.0.15.3.tar.gz"},"name":"mono-traversable","pinned":{"url":["https://hackage.haskell.org/package/mono-traversable-1.0.15.3/mono-traversable-1.0.15.3.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/mono-traversable-1.0.15.3.tar.gz"],"sha256":"98b220f3313d74227a4249210c8818e839678343e62b3ebb1b8c867cf2b974b7","cabal-sha256":"059bf3c05cdbef2d06b765333fe41c2168ced2503a23de674e2a59ceb2548c48"},"version":"1.0.15.3"}, "mtl": {"dependencies":[],"location":{"type":"core"},"name":"mtl","version":"2.2.2"}, - "network": {"dependencies":["base","bytestring","deepseq","directory"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/network-3.1.2.7/network-3.1.2.7.tar.gz"},"name":"network","pinned":{"url":["https://hackage.haskell.org/package/network-3.1.2.7/network-3.1.2.7.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/network-3.1.2.7.tar.gz"],"sha256":"7f7620fef1a1af3d3d6747f510e73223a5c600e7d7fd9ace073d1222bdc63d85","cabal-sha256":"e3d78b13db9512aeb106e44a334ab42b7aa48d26c097299084084cb8be5c5568"},"version":"3.1.2.7"}, + "network": {"dependencies":["base","bytestring","deepseq","directory"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/network-3.1.2.9/network-3.1.2.9.tar.gz"},"name":"network","pinned":{"url":["https://hackage.haskell.org/package/network-3.1.2.9/network-3.1.2.9.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/network-3.1.2.9.tar.gz"],"sha256":"0cbf95e4653dbfecc3907e10e7e7bbddb9dd673f172848a0ff3131ab3efdd900","cabal-sha256":"eacdb7f78719cc5125b25856a9114984c5c03b484995f3074b3d756553ededee"},"version":"3.1.2.9"}, "optparse-applicative": {"dependencies":["ansi-wl-pprint","base","process","transformers","transformers-compat"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/optparse-applicative-0.17.0.0/optparse-applicative-0.17.0.0.tar.gz"},"name":"optparse-applicative","pinned":{"url":["https://hackage.haskell.org/package/optparse-applicative-0.17.0.0/optparse-applicative-0.17.0.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/optparse-applicative-0.17.0.0.tar.gz"],"sha256":"825b2e4d3dafe0ba64a073366a88062b3712b81f851793d9ce2327bee70af724","cabal-sha256":"0713e54cbb341e5cae979e2ac441eb3a5ff42e303001f432bd58c19e5638bdda"},"version":"0.17.0.0"}, "parsec": {"dependencies":[],"location":{"type":"core"},"name":"parsec","version":"3.1.15.0"}, "polysemy": {"dependencies":["Cabal","QuickCheck","async","base","cabal-doctest","containers","first-class-families","mtl","stm","syb","template-haskell","th-abstraction","transformers","type-errors","unagi-chan"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/polysemy-1.7.1.0/polysemy-1.7.1.0.tar.gz"},"name":"polysemy","pinned":{"url":["https://hackage.haskell.org/package/polysemy-1.7.1.0/polysemy-1.7.1.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/polysemy-1.7.1.0.tar.gz"],"sha256":"4c9556c0c3f38f5fa655567106ecb53cd357e6ffaf8289753ba6dc26fd4bc224","cabal-sha256":"3ead7a332abd70b202920ed3bf2e36866de163f821e643adfdcc9d39867b8033"},"version":"1.7.1.0"}, "pretty": {"dependencies":[],"location":{"type":"core"},"name":"pretty","version":"1.1.3.6"}, "primitive": {"dependencies":["base","deepseq","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/primitive-0.7.3.0/primitive-0.7.3.0.tar.gz"},"name":"primitive","pinned":{"url":["https://hackage.haskell.org/package/primitive-0.7.3.0/primitive-0.7.3.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/primitive-0.7.3.0.tar.gz"],"sha256":"3c0cfda67f1ee6f7f65108ad6f973b5bbb35ddba34b3c87746a7448f787501dc","cabal-sha256":"ce9361b4d2ed296ef639380411b4cfc217a19e4b3cd4170e03e6fce52daa0176"},"version":"0.7.3.0"}, "process": {"dependencies":[],"location":{"type":"core"},"name":"process","version":"1.6.16.0"}, - "profunctors": {"dependencies":["base","base-orphans","bifunctors","comonad","contravariant","distributive","tagged","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/profunctors-5.6.2/profunctors-5.6.2.tar.gz"},"name":"profunctors","pinned":{"url":["https://hackage.haskell.org/package/profunctors-5.6.2/profunctors-5.6.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/profunctors-5.6.2.tar.gz"],"sha256":"65955d7b50525a4a3bccdab1d982d2ae342897fd38140d5a94b5ef3800d8c92a","cabal-sha256":"3d3685119243a7ebf984fa6af03299d156ab7674a432e2e15ecee2a4fd420fb6"},"version":"5.6.2"}, - "proto-lens": {"dependencies":["base","bytestring","containers","deepseq","ghc-prim","lens-family","parsec","pretty","primitive","profunctors","tagged","text","transformers","vector"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/proto-lens-0.7.1.2/proto-lens-0.7.1.2.tar.gz"},"name":"proto-lens","pinned":{"url":["https://hackage.haskell.org/package/proto-lens-0.7.1.2/proto-lens-0.7.1.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/proto-lens-0.7.1.2.tar.gz"],"sha256":"de990265b720dde6a37771a7f36f9a0b07bba39ce14d06d78e855d5bf5e4737d","cabal-sha256":"1d16d73948f4100e1de8374356c3fcfacc63dcc7b8d2130c580f79bdb0139bc5"},"version":"0.7.1.2"}, + "profunctors": {"dependencies":["base","base-orphans","bifunctors","comonad","contravariant","distributive","tagged","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/profunctors-5.6.2/profunctors-5.6.2.tar.gz"},"name":"profunctors","pinned":{"url":["https://hackage.haskell.org/package/profunctors-5.6.2/profunctors-5.6.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/profunctors-5.6.2.tar.gz"],"sha256":"65955d7b50525a4a3bccdab1d982d2ae342897fd38140d5a94b5ef3800d8c92a","cabal-sha256":"e178ba4468982326656626e2089e296f64485e68fdddc9f4476dcd5d612b4f78"},"version":"5.6.2"}, + "proto-lens": {"dependencies":["base","bytestring","containers","deepseq","ghc-prim","lens-family","parsec","pretty","primitive","profunctors","tagged","text","transformers","vector"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/proto-lens-0.7.1.3/proto-lens-0.7.1.3.tar.gz"},"name":"proto-lens","pinned":{"url":["https://hackage.haskell.org/package/proto-lens-0.7.1.3/proto-lens-0.7.1.3.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/proto-lens-0.7.1.3.tar.gz"],"sha256":"aac4317671a31d5f76cb120b5c4f75e644c45b441b4a2b9cfa7015bd8bbae3ac","cabal-sha256":"2d56bf8c37e21d741385e155d0dd327468ab1bc6897d10b0462b7e241d8e61a3"},"version":"0.7.1.3"}, "proto-lens-protoc": {"dependencies":["base","bytestring","containers","filepath","ghc","ghc-paths","ghc-source-gen","lens-family","pretty","proto-lens","proto-lens-runtime","text"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/proto-lens-protoc-0.7.1.1/proto-lens-protoc-0.7.1.1.tar.gz"},"name":"proto-lens-protoc","pinned":{"url":["https://hackage.haskell.org/package/proto-lens-protoc-0.7.1.1/proto-lens-protoc-0.7.1.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/proto-lens-protoc-0.7.1.1.tar.gz"],"sha256":"0c412b47bce8a3898a61509b9a61c16e00ee947764bd22a07817ecc97a4080f2","cabal-sha256":"4b3b97d5caac9a9f8a85d426d5ad8a129f36e852dd05f42e614d9912030b9700"},"version":"0.7.1.1"}, - "proto-lens-runtime": {"dependencies":["base","bytestring","containers","deepseq","filepath","lens-family","proto-lens","text","vector"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/proto-lens-runtime-0.7.0.3/proto-lens-runtime-0.7.0.3.tar.gz"},"name":"proto-lens-runtime","pinned":{"url":["https://hackage.haskell.org/package/proto-lens-runtime-0.7.0.3/proto-lens-runtime-0.7.0.3.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/proto-lens-runtime-0.7.0.3.tar.gz"],"sha256":"de8cffea5315734ed325f650130aec93ceaf63069a610c0915fbb497592766b9","cabal-sha256":"5165848fa8c112716a4d550dcd8dda8858226294ce3e24462e5b0d9050de9899"},"version":"0.7.0.3"}, + "proto-lens-runtime": {"dependencies":["base","bytestring","containers","deepseq","filepath","lens-family","proto-lens","text","vector"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/proto-lens-runtime-0.7.0.4/proto-lens-runtime-0.7.0.4.tar.gz"},"name":"proto-lens-runtime","pinned":{"url":["https://hackage.haskell.org/package/proto-lens-runtime-0.7.0.4/proto-lens-runtime-0.7.0.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/proto-lens-runtime-0.7.0.4.tar.gz"],"sha256":"5749cd01d97fd56bae5698830ba78adcc147e4b65b5e1b4b1cb6f9ee52587f47","cabal-sha256":"1a64cb98b49541e53ea8a19270d7247960445083a2327a091ce0a1cafdef16f3"},"version":"0.7.0.4"}, "quickcheck-io": {"dependencies":["HUnit","QuickCheck","base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/quickcheck-io-0.2.0/quickcheck-io-0.2.0.tar.gz"},"name":"quickcheck-io","pinned":{"url":["https://hackage.haskell.org/package/quickcheck-io-0.2.0/quickcheck-io-0.2.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/quickcheck-io-0.2.0.tar.gz"],"sha256":"fb779119d79fe08ff4d502fb6869a70c9a8d5fd8ae0959f605c3c937efd96422","cabal-sha256":"7bf0b68fb90873825eb2e5e958c1b76126dcf984debb998e81673e6d837e0b2d"},"version":"0.2.0"}, "random": {"dependencies":["base","bytestring","deepseq","mtl","splitmix"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/random-1.2.1.1/random-1.2.1.1.tar.gz"},"name":"random","pinned":{"url":["https://hackage.haskell.org/package/random-1.2.1.1/random-1.2.1.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/random-1.2.1.1.tar.gz"],"sha256":"3e1272f7ed6a4d7bd1712b90143ec326fee9b225789222379fea20a9c90c9b76","cabal-sha256":"dea1f11e5569332dc6c8efaad1cb301016a5587b6754943a49f9de08ae0e56d9"},"version":"1.2.1.1"}, "resourcet": {"dependencies":["base","containers","exceptions","mtl","primitive","transformers","unliftio-core"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/resourcet-1.2.6/resourcet-1.2.6.tar.gz"},"name":"resourcet","pinned":{"url":["https://hackage.haskell.org/package/resourcet-1.2.6/resourcet-1.2.6.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/resourcet-1.2.6.tar.gz"],"sha256":"f83b35b2106854750ef5f1c34695ea8b7bba6e0572cedf9f2993c5acfdb5fd34","cabal-sha256":"0c55be13d24c1e9c1e6d82327ac039a0bf41469c456e3ae678efa8a9beda3a74"},"version":"1.2.6"}, "safe-exceptions": {"dependencies":["base","deepseq","exceptions","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/safe-exceptions-0.1.7.3/safe-exceptions-0.1.7.3.tar.gz"},"name":"safe-exceptions","pinned":{"url":["https://hackage.haskell.org/package/safe-exceptions-0.1.7.3/safe-exceptions-0.1.7.3.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/safe-exceptions-0.1.7.3.tar.gz"],"sha256":"91ce28d8f8a6efd31788d4827ed5cdcb9a546ad4053a86c56f7947c66a30b5bf","cabal-sha256":"6e9b1b233af80cc0aa17ea858d2641ba146fb11cbcc5970a52649e89d77282e2"},"version":"0.1.7.3"}, - "scientific": {"dependencies":["base","binary","bytestring","containers","deepseq","hashable","integer-logarithms","primitive","template-haskell","text"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/scientific-0.3.7.0/scientific-0.3.7.0.tar.gz"},"name":"scientific","pinned":{"url":["https://hackage.haskell.org/package/scientific-0.3.7.0/scientific-0.3.7.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/scientific-0.3.7.0.tar.gz"],"sha256":"a3a121c4b3d68fb8b9f8c709ab012e48f090ed553609247a805ad070d6b343a9","cabal-sha256":"517444c944dad9db8235d7b311d7b9a0839a519ee3178288b5a9606256e0c7d8"},"version":"0.3.7.0"}, + "scientific": {"dependencies":["base","binary","bytestring","containers","deepseq","hashable","integer-logarithms","primitive","template-haskell","text"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/scientific-0.3.7.0/scientific-0.3.7.0.tar.gz"},"name":"scientific","pinned":{"url":["https://hackage.haskell.org/package/scientific-0.3.7.0/scientific-0.3.7.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/scientific-0.3.7.0.tar.gz"],"sha256":"a3a121c4b3d68fb8b9f8c709ab012e48f090ed553609247a805ad070d6b343a9","cabal-sha256":"26d8109106963a345368011081453d25ee1dfa6afae2b1f57b426b4bcd392d91"},"version":"0.3.7.0"}, "setenv": {"dependencies":["base","unix"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/setenv-0.1.1.3/setenv-0.1.1.3.tar.gz"},"name":"setenv","pinned":{"url":["https://hackage.haskell.org/package/setenv-0.1.1.3/setenv-0.1.1.3.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/setenv-0.1.1.3.tar.gz"],"sha256":"e358df39afc03d5a39e2ec650652d845c85c80cc98fe331654deafb4767ecb32","cabal-sha256":"c5916ac0d2a828473cd171261328a290afe0abd799db1ac8c310682fe778c45b"},"version":"0.1.1.3"}, "split": {"dependencies":["base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/split-0.2.3.5/split-0.2.3.5.tar.gz"},"name":"split","pinned":{"url":["https://hackage.haskell.org/package/split-0.2.3.5/split-0.2.3.5.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/split-0.2.3.5.tar.gz"],"sha256":"bf8aa8d610354a2b576946a6c838251ec5988c8374100638e6b2604513b93159","cabal-sha256":"f472fa7019647cacac3267742a6f7ac0a5c816f9890e80e4b826cd937436de87"},"version":"0.2.3.5"}, "splitmix": {"dependencies":["base","deepseq"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/splitmix-0.1.0.4/splitmix-0.1.0.4.tar.gz"},"name":"splitmix","pinned":{"url":["https://hackage.haskell.org/package/splitmix-0.1.0.4/splitmix-0.1.0.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/splitmix-0.1.0.4.tar.gz"],"sha256":"6d065402394e7a9117093dbb4530a21342c9b1e2ec509516c8a8d0ffed98ecaa","cabal-sha256":"db25c2e17967aa6b6046ab8b1b96ba3f344ca59a62b60fb6113d51ea305a3d8e"},"version":"0.1.0.4"}, "stm": {"dependencies":[],"location":{"type":"core"},"name":"stm","version":"2.5.0.2"}, "streaming": {"dependencies":["base","containers","ghc-prim","mmorph","mtl","transformers","transformers-base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/streaming-0.2.3.1/streaming-0.2.3.1.tar.gz"},"name":"streaming","pinned":{"url":["https://hackage.haskell.org/package/streaming-0.2.3.1/streaming-0.2.3.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/streaming-0.2.3.1.tar.gz"],"sha256":"fc5efae393750b9729ce5c5e979edcd3b9a5bf41ab927636174b01f999ffea88","cabal-sha256":"9dd39bfa8befa6956372722187b225d489b50b633ab56d7f411bf302b79e46cd"},"version":"0.2.3.1"}, - "streaming-commons": {"dependencies":["array","async","base","bytestring","directory","network","process","random","stm","text","transformers","unix","zlib"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/streaming-commons-0.2.2.5/streaming-commons-0.2.2.5.tar.gz"},"name":"streaming-commons","pinned":{"url":["https://hackage.haskell.org/package/streaming-commons-0.2.2.5/streaming-commons-0.2.2.5.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/streaming-commons-0.2.2.5.tar.gz"],"sha256":"ca50819bdb2b248ced790e9faab07a3a5369ef702d9f9a932f26438bbeeca704","cabal-sha256":"34959abee70e63d370b5a4bee0bc3483c66d1e53906fb5e13844ae8b9a62a4a3"},"version":"0.2.2.5"}, - "syb": {"dependencies":["base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/syb-0.7.2.2/syb-0.7.2.2.tar.gz"},"name":"syb","pinned":{"url":["https://hackage.haskell.org/package/syb-0.7.2.2/syb-0.7.2.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/syb-0.7.2.2.tar.gz"],"sha256":"8143c6983b6248d57f00e47ec3cd16541acbaa55eb8093fedd5b7cee9a95b2e3","cabal-sha256":"bc800dbd35a17b652082f7f9790fd20d196ea0f44daaa7d5ac46491d8ecc7347"},"version":"0.7.2.2"}, + "streaming-commons": {"dependencies":["array","async","base","bytestring","directory","network","process","random","stm","text","transformers","unix","zlib"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/streaming-commons-0.2.2.6/streaming-commons-0.2.2.6.tar.gz"},"name":"streaming-commons","pinned":{"url":["https://hackage.haskell.org/package/streaming-commons-0.2.2.6/streaming-commons-0.2.2.6.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/streaming-commons-0.2.2.6.tar.gz"],"sha256":"0180958a882eb0f6262b812fe886c2b1b8285474b5b958f814ae4f05409fbf79","cabal-sha256":"f3a6db1e6c12760c00a38393693d473b8b4f9211eed036388eca89996ba50d66"},"version":"0.2.2.6"}, + "syb": {"dependencies":["base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/syb-0.7.2.3/syb-0.7.2.3.tar.gz"},"name":"syb","pinned":{"url":["https://hackage.haskell.org/package/syb-0.7.2.3/syb-0.7.2.3.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/syb-0.7.2.3.tar.gz"],"sha256":"d0b72daf16a947c4d9cb2d5774072f2153433224a04fd60fad60be9ffac8d91a","cabal-sha256":"d71f6747016466b0766491eae36be842ba98ba25e2aec26eaedbeea965c0586a"},"version":"0.7.2.3"}, "tagged": {"dependencies":["base","deepseq","template-haskell","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/tagged-0.8.6.1/tagged-0.8.6.1.tar.gz"},"name":"tagged","pinned":{"url":["https://hackage.haskell.org/package/tagged-0.8.6.1/tagged-0.8.6.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/tagged-0.8.6.1.tar.gz"],"sha256":"f5e0fcf95f0bb4aa63f428f2c01955a41ea1a42cfcf39145ed631f59a9616c02","cabal-sha256":"8a24aef29b8e35447ccc56658ea07c2aded30bfa8130ea057e382936e17c74a6"},"version":"0.8.6.1"}, "template-haskell": {"dependencies":[],"location":{"type":"core"},"name":"template-haskell","version":"2.18.0.0"}, "temporary": {"dependencies":["base","directory","exceptions","filepath","random","transformers","unix"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/temporary-1.3/temporary-1.3.tar.gz"},"name":"temporary","pinned":{"url":["https://hackage.haskell.org/package/temporary-1.3/temporary-1.3.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/temporary-1.3.tar.gz"],"sha256":"8c442993694b5ffca823ce864af95bd2841fb5264ee511c61cf48cc71d879890","cabal-sha256":"3a66c136f700dbf42f3c5000ca93e80b26dead51e54322c83272b236c1ec8ef1"},"version":"1.3"}, "text": {"dependencies":[],"location":{"type":"core"},"name":"text","version":"1.2.5.0"}, - "text-show": {"dependencies":["array","base","base-compat-batteries","bifunctors","bytestring","bytestring-builder","containers","generic-deriving","ghc-boot-th","ghc-prim","template-haskell","text","th-abstraction","th-lift","transformers","transformers-compat"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/text-show-3.10/text-show-3.10.tar.gz"},"name":"text-show","pinned":{"url":["https://hackage.haskell.org/package/text-show-3.10/text-show-3.10.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/text-show-3.10.tar.gz"],"sha256":"cebbcab5235728d845f36d23364e66941b3d95e68b682d0ce388a5e22f2502c7","cabal-sha256":"eeaa34802b668cae6fc38c1f52e6f78d482c73f527967ac2bfa2d3f0af60c424"},"version":"3.10"}, + "text-show": {"dependencies":["array","base","base-compat-batteries","bifunctors","bytestring","bytestring-builder","containers","generic-deriving","ghc-boot-th","ghc-prim","template-haskell","text","th-abstraction","th-lift","transformers","transformers-compat"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/text-show-3.10.2/text-show-3.10.2.tar.gz"},"name":"text-show","pinned":{"url":["https://hackage.haskell.org/package/text-show-3.10.2/text-show-3.10.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/text-show-3.10.2.tar.gz"],"sha256":"9c34afafb6eaed63b08754045eed157430690b83135e019a72428c518ef37703","cabal-sha256":"5f6107d41b36a1780b4942f8fda23524227fef35df7b4882d87c0ecade6992e9"},"version":"3.10.2"}, "tf-random": {"dependencies":["base","primitive","random","time"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/tf-random-0.5/tf-random-0.5.tar.gz"},"name":"tf-random","pinned":{"url":["https://hackage.haskell.org/package/tf-random-0.5/tf-random-0.5.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/tf-random-0.5.tar.gz"],"sha256":"2e30cec027b313c9e1794d326635d8fc5f79b6bf6e7580ab4b00186dadc88510","cabal-sha256":"14012837d0f0e18fdbbe3d56e67da8622ee5e20b180abce952dd50bd9f36b326"},"version":"0.5"}, - "th-abstraction": {"dependencies":["base","containers","ghc-prim","template-haskell"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/th-abstraction-0.4.5.0/th-abstraction-0.4.5.0.tar.gz"},"name":"th-abstraction","pinned":{"url":["https://hackage.haskell.org/package/th-abstraction-0.4.5.0/th-abstraction-0.4.5.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/th-abstraction-0.4.5.0.tar.gz"],"sha256":"00d5e24f247e328bd9898d5af5915c1e86b134b4d40baa680258635f95031526","cabal-sha256":"313f8b3c65781310df66ba86518bcf7662b1b419b601afaf72bb977c255fe6e9"},"version":"0.4.5.0"}, - "th-compat": {"dependencies":["base","directory","filepath","template-haskell"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/th-compat-0.1.4/th-compat-0.1.4.tar.gz"},"name":"th-compat","pinned":{"url":["https://hackage.haskell.org/package/th-compat-0.1.4/th-compat-0.1.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/th-compat-0.1.4.tar.gz"],"sha256":"d8f97ac14ab47b6b8a7b0fdb4ff95426322ec56badd01652ac15da4a44d4bab8","cabal-sha256":"6ca77c4e80b4e4109e30549c269631a9cc295c8fc2431ce4123972a5f80f7bfc"},"version":"0.1.4"}, - "th-lift": {"dependencies":["base","ghc-prim","template-haskell","th-abstraction"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/th-lift-0.8.2/th-lift-0.8.2.tar.gz"},"name":"th-lift","pinned":{"url":["https://hackage.haskell.org/package/th-lift-0.8.2/th-lift-0.8.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/th-lift-0.8.2.tar.gz"],"sha256":"3a5927037a10ae63e605c02228c4027c32b7bab1985ae7b5379e6363b3cd5ce4","cabal-sha256":"f135f67b018c22889e68b094773273dcf8f9e16fcfa330bf4778f84fce8925e9"},"version":"0.8.2"}, + "th-abstraction": {"dependencies":["base","containers","ghc-prim","template-haskell"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/th-abstraction-0.4.5.0/th-abstraction-0.4.5.0.tar.gz"},"name":"th-abstraction","pinned":{"url":["https://hackage.haskell.org/package/th-abstraction-0.4.5.0/th-abstraction-0.4.5.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/th-abstraction-0.4.5.0.tar.gz"],"sha256":"00d5e24f247e328bd9898d5af5915c1e86b134b4d40baa680258635f95031526","cabal-sha256":"c28f186ae9817a059e54f63689f8985194b7f58d8fbd79e157d12374b6f9d2c3"},"version":"0.4.5.0"}, + "th-compat": {"dependencies":["base","directory","filepath","template-haskell"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/th-compat-0.1.4/th-compat-0.1.4.tar.gz"},"name":"th-compat","pinned":{"url":["https://hackage.haskell.org/package/th-compat-0.1.4/th-compat-0.1.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/th-compat-0.1.4.tar.gz"],"sha256":"d8f97ac14ab47b6b8a7b0fdb4ff95426322ec56badd01652ac15da4a44d4bab8","cabal-sha256":"e5ae7c083ef3a22248558f8451669bb1c55ea8090f5908b86b9033743c161730"},"version":"0.1.4"}, + "th-lift": {"dependencies":["base","ghc-prim","template-haskell","th-abstraction"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/th-lift-0.8.3/th-lift-0.8.3.tar.gz"},"name":"th-lift","pinned":{"url":["https://hackage.haskell.org/package/th-lift-0.8.3/th-lift-0.8.3.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/th-lift-0.8.3.tar.gz"],"sha256":"25d57bf5f8e7deefeb4ace0539805ae1e90b1ba5a034ebcc36141846408c6b75","cabal-sha256":"3043e803a08c22676dcf71a4021d0fa276fcecc2ac3dbc4b230fee0b994ca7e9"},"version":"0.8.3"}, "time": {"dependencies":[],"location":{"type":"core"},"name":"time","version":"1.11.1.1"}, "transformers": {"dependencies":[],"location":{"type":"core"},"name":"transformers","version":"0.5.6.2"}, "transformers-base": {"dependencies":["base","base-orphans","stm","transformers","transformers-compat"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/transformers-base-0.4.6/transformers-base-0.4.6.tar.gz"},"name":"transformers-base","pinned":{"url":["https://hackage.haskell.org/package/transformers-base-0.4.6/transformers-base-0.4.6.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/transformers-base-0.4.6.tar.gz"],"sha256":"323bf8689eb691b122661cffa41a25e00fea7a768433fe2dde35d3da7d32cf90","cabal-sha256":"6f18f320e371c8954c4b6b211e2fdd5d15a6d6310bd605b9d640f47ede408961"},"version":"0.4.6"}, "transformers-compat": {"dependencies":["base","ghc-prim","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/transformers-compat-0.7.2/transformers-compat-0.7.2.tar.gz"},"name":"transformers-compat","pinned":{"url":["https://hackage.haskell.org/package/transformers-compat-0.7.2/transformers-compat-0.7.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/transformers-compat-0.7.2.tar.gz"],"sha256":"b62c7304c9f3cbc9463d0739aa85cb9489f217ea092b9d625d417514fbcc9d6a","cabal-sha256":"044fb9955f63ee138fcebedfdcbe54afe741f2d5892a2d0bdf3a8052bd342643"},"version":"0.7.2"}, - "type-errors": {"dependencies":["base","first-class-families","syb","template-haskell","th-abstraction"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/type-errors-0.2.0.1/type-errors-0.2.0.1.tar.gz"},"name":"type-errors","pinned":{"url":["https://hackage.haskell.org/package/type-errors-0.2.0.1/type-errors-0.2.0.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/type-errors-0.2.0.1.tar.gz"],"sha256":"d537369e6bef4d7656d5de45e5ebb6687fe3e3666e21abdb78a23d295ff14137","cabal-sha256":"c47af01304199c6440566c0a2c9a434db7ae8027dd4701dc2e374fc341ab40b1"},"version":"0.2.0.1"}, - "typed-process": {"dependencies":["async","base","bytestring","process","stm","transformers","unliftio-core"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/typed-process-0.2.10.1/typed-process-0.2.10.1.tar.gz"},"name":"typed-process","pinned":{"url":["https://hackage.haskell.org/package/typed-process-0.2.10.1/typed-process-0.2.10.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/typed-process-0.2.10.1.tar.gz"],"sha256":"e436875ccd6664d4111e601c8e2ec6ba9473979eac49b23a1bdb88f80e95099e","cabal-sha256":"cc35b76f2ce32c708cb2f68a1c4f661a8138196d958e34a2f214208333a73f46"},"version":"0.2.10.1"}, + "type-errors": {"dependencies":["base","first-class-families","syb","template-haskell","th-abstraction"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/type-errors-0.2.0.2/type-errors-0.2.0.2.tar.gz"},"name":"type-errors","pinned":{"url":["https://hackage.haskell.org/package/type-errors-0.2.0.2/type-errors-0.2.0.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/type-errors-0.2.0.2.tar.gz"],"sha256":"697cffdd1ec573d6b8d1539976673f93bb562ee97b644077e2305bfefc897c83","cabal-sha256":"afd6b33bb582730a90ea58fd23d5b32a38b5b6c8b2f18e3250936bdc0487dfab"},"version":"0.2.0.2"}, + "typed-process": {"dependencies":["async","base","bytestring","process","stm","transformers","unliftio-core"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/typed-process-0.2.11.0/typed-process-0.2.11.0.tar.gz"},"name":"typed-process","pinned":{"url":["https://hackage.haskell.org/package/typed-process-0.2.11.0/typed-process-0.2.11.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/typed-process-0.2.11.0.tar.gz"],"sha256":"948c59540675d85f35c99e285cdb8686713ec1689f530d5d21813239ea91f625","cabal-sha256":"defde2c4dcd07750381d6e15ee7a517938c8d6353abcf27bba9f290e75a67d39"},"version":"0.2.11.0"}, "unagi-chan": {"dependencies":["atomic-primops","base","ghc-prim","primitive"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/unagi-chan-0.4.1.4/unagi-chan-0.4.1.4.tar.gz"},"name":"unagi-chan","pinned":{"url":["https://hackage.haskell.org/package/unagi-chan-0.4.1.4/unagi-chan-0.4.1.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/unagi-chan-0.4.1.4.tar.gz"],"sha256":"d9d6f4ab07def8e84a942bb23791830a61faf89166cb7185a3b2f97cb45128b5","cabal-sha256":"e9a282689a65fc66260557222789d14dcb7d299be0ab2d4e8e414b0d9f2ef459"},"version":"0.4.1.4"}, "unix": {"dependencies":[],"location":{"type":"core"},"name":"unix","version":"2.7.2.2"}, - "unliftio-core": {"dependencies":["base","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/unliftio-core-0.2.0.1/unliftio-core-0.2.0.1.tar.gz"},"name":"unliftio-core","pinned":{"url":["https://hackage.haskell.org/package/unliftio-core-0.2.0.1/unliftio-core-0.2.0.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/unliftio-core-0.2.0.1.tar.gz"],"sha256":"919f0d1297ea2f5373118553c1df2a9405d8b9e31a8307e829da67d4953c299a","cabal-sha256":"f9abcdd3f3d28e4840563efb7b8760d2de9b5707bcd6f53a87f6a0d77bb5a9f7"},"version":"0.2.0.1"}, - "unordered-containers": {"dependencies":["base","deepseq","hashable","template-haskell"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/unordered-containers-0.2.19.1/unordered-containers-0.2.19.1.tar.gz"},"name":"unordered-containers","pinned":{"url":["https://hackage.haskell.org/package/unordered-containers-0.2.19.1/unordered-containers-0.2.19.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/unordered-containers-0.2.19.1.tar.gz"],"sha256":"1b27bec5e0d522b27a6029ebf4c4a6d40acbc083c787008e32fb55c4b1d128d2","cabal-sha256":"db11042bb0356c0adea277d0794743829125b4c99455af6af2bd5f7bd5e88a39"},"version":"0.2.19.1"}, - "vector": {"dependencies":["base","deepseq","ghc-prim","primitive"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/vector-0.12.3.1/vector-0.12.3.1.tar.gz"},"name":"vector","pinned":{"url":["https://hackage.haskell.org/package/vector-0.12.3.1/vector-0.12.3.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/vector-0.12.3.1.tar.gz"],"sha256":"fb4a53c02bd4d7fdf155c0604da9a5bb0f3b3bfce5d9960aea11c2ae235b9f35","cabal-sha256":"fffbd00912d69ed7be9bc7eeb09f4f475e0d243ec43f916a9fd5bbd219ce7f3e"},"version":"0.12.3.1"}, + "unliftio-core": {"dependencies":["base","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/unliftio-core-0.2.1.0/unliftio-core-0.2.1.0.tar.gz"},"name":"unliftio-core","pinned":{"url":["https://hackage.haskell.org/package/unliftio-core-0.2.1.0/unliftio-core-0.2.1.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/unliftio-core-0.2.1.0.tar.gz"],"sha256":"99384cba8d56d9d61b85e38a313a93ebcdb78be6566367f0930ef580597fe3e3","cabal-sha256":"cb78a95718f9cb2579a8a1208d4a148ea358f0774321c8cb905bfb0b96a2813c"},"version":"0.2.1.0"}, + "unordered-containers": {"dependencies":["base","deepseq","hashable","template-haskell"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/unordered-containers-0.2.19.1/unordered-containers-0.2.19.1.tar.gz"},"name":"unordered-containers","pinned":{"url":["https://hackage.haskell.org/package/unordered-containers-0.2.19.1/unordered-containers-0.2.19.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/unordered-containers-0.2.19.1.tar.gz"],"sha256":"1b27bec5e0d522b27a6029ebf4c4a6d40acbc083c787008e32fb55c4b1d128d2","cabal-sha256":"9ad8972c2e913c37b1d4f0e1261517fd7a1b8c8a58077e057be69837e3dbaa00"},"version":"0.2.19.1"}, + "vector": {"dependencies":["base","deepseq","ghc-prim","primitive"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/vector-0.12.3.1/vector-0.12.3.1.tar.gz"},"name":"vector","pinned":{"url":["https://hackage.haskell.org/package/vector-0.12.3.1/vector-0.12.3.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/vector-0.12.3.1.tar.gz"],"sha256":"fb4a53c02bd4d7fdf155c0604da9a5bb0f3b3bfce5d9960aea11c2ae235b9f35","cabal-sha256":"39141f312871b7c793a63be76635999e84d442aa3290aec59f30638ec0bf23a7"},"version":"0.12.3.1"}, "vector-algorithms": {"dependencies":["base","bytestring","primitive","vector"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/vector-algorithms-0.8.0.4/vector-algorithms-0.8.0.4.tar.gz"},"name":"vector-algorithms","pinned":{"url":["https://hackage.haskell.org/package/vector-algorithms-0.8.0.4/vector-algorithms-0.8.0.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/vector-algorithms-0.8.0.4.tar.gz"],"sha256":"76176a56778bf30a275b1089ee6db24ec6c67d92525145f8dfe215b80137af3b","cabal-sha256":"e0656aa47388e5c80e4f5d4fd87c80fb8d473fdd41533ff7af5cbb292056a544"},"version":"0.8.0.4"}, "void": {"dependencies":["base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/void-0.7.3/void-0.7.3.tar.gz"},"name":"void","pinned":{"url":["https://hackage.haskell.org/package/void-0.7.3/void-0.7.3.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/void-0.7.3.tar.gz"],"sha256":"53af758ddc37dc63981671e503438d02c6f64a2d8744e9bec557a894431f7317","cabal-sha256":"13d30f62fcdf065e595d679d4ac8b4b0c1bb1a1b73db7b5b5a8f857cb5c8a546"},"version":"0.7.3"}, - "zlib": {"dependencies":["base","bytestring"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/zlib-0.6.3.0/zlib-0.6.3.0.tar.gz"},"name":"zlib","pinned":{"url":["https://hackage.haskell.org/package/zlib-0.6.3.0/zlib-0.6.3.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/zlib-0.6.3.0.tar.gz"],"sha256":"9eaa989ad4534438b5beb51c1d3a4c8f6a088fdff0b259a5394fbf39aaee04da","cabal-sha256":"8214a9d37580f17f8b675109578a5dbe6853559eef156e34dc2233f1123ace33"},"version":"0.6.3.0"} + "zlib": {"dependencies":["base","bytestring"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/zlib-0.6.3.0/zlib-0.6.3.0.tar.gz"},"name":"zlib","pinned":{"url":["https://hackage.haskell.org/package/zlib-0.6.3.0/zlib-0.6.3.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/zlib-0.6.3.0.tar.gz"],"sha256":"9eaa989ad4534438b5beb51c1d3a4c8f6a088fdff0b259a5394fbf39aaee04da","cabal-sha256":"9adce39e4ca0b7a87d45df0a243134816c57059a08e28cff5469c98ae1f54dfc"},"version":"0.6.3.0"} } } \ No newline at end of file diff --git a/stackage_snapshot.yaml b/stackage_snapshot.yaml index 6d6d2f8d5..edb203776 100644 --- a/stackage_snapshot.yaml +++ b/stackage_snapshot.yaml @@ -5,17 +5,11 @@ # but with versions <= 2.13.2.0 we encounter the following issue: # https://github.com/haskell/win32/issues/193 -resolver: lts-20.3 +resolver: lts-20.21 drop-packages: - Win32 -packages: -- git: https://github.com/tweag/cabal - commit: 42f04c3f639f10dc3c7981a0c663bfe08ad833cb - subdirs: - - Cabal - # stackage lts-20.3/ghc 9.2.5 only contain Win32-2.12.0.1 flags: ansi-terminal: From 693f7f61970d069a4ba02713d72aaa53ada54712 Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Fri, 19 May 2023 19:01:08 +0200 Subject: [PATCH 14/41] Keep going --- .github/workflows/workflow.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/workflow.yaml b/.github/workflows/workflow.yaml index 44d53c8f2..0b7369167 100644 --- a/.github/workflows/workflow.yaml +++ b/.github/workflows/workflow.yaml @@ -209,7 +209,7 @@ jobs: # On Windows `//...` expands to `/...`. bazel test ///... else - bazel test //... + bazel test --keep_going -- //... fi - name: Build & test - rules_haskell_tests @@ -225,7 +225,7 @@ jobs: # On Windows `//...` expands to `/...`. bazel test ///... else - bazel test //... + bazel test --keep_going -- //... fi # Test stack_snapshot pinning # NOTE keep in sync with tests/RunTests.hs From aeed150fec9161d9989938e88a7d4c9c6dd23af3 Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Fri, 19 May 2023 19:02:21 +0200 Subject: [PATCH 15/41] Fix more things --- rules_haskell_tests/stackage-pinning-test.yaml | 4 ---- .../stackage-pinning-test_snapshot.json | 11 +++-------- .../tests/haskell_module/attr_merging/Plugin.hs | 2 +- 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/rules_haskell_tests/stackage-pinning-test.yaml b/rules_haskell_tests/stackage-pinning-test.yaml index fa25d62b3..93d167084 100644 --- a/rules_haskell_tests/stackage-pinning-test.yaml +++ b/rules_haskell_tests/stackage-pinning-test.yaml @@ -12,10 +12,6 @@ packages: - archive: https://github.com/tweag/rules_haskell/raw/e4e74f17f743488f564bd0d69c580106d5b910a5/tests/haskell_cabal_library_sublibrary_name/package1.tar sha256: "302d8ddda8330c825da61fe0a2315c899ab083e641c7716ebdacb5c951682445" - - git: https://github.com/tweag/cabal - commit: 42f04c3f639f10dc3c7981a0c663bfe08ad833cb - subdirs: - - Cabal # We drop the Win32 package from the stack snapshot so that stack considers it a toolchain library. # In this case we will use the Win32 provided by the compiler instead of recompiling it. diff --git a/rules_haskell_tests/stackage-pinning-test_snapshot.json b/rules_haskell_tests/stackage-pinning-test_snapshot.json index 8735dda6e..e386e1621 100644 --- a/rules_haskell_tests/stackage-pinning-test_snapshot.json +++ b/rules_haskell_tests/stackage-pinning-test_snapshot.json @@ -1,14 +1,13 @@ { - "__GENERATED_FILE_DO_NOT_MODIFY_MANUALLY": 1765141068, - "all-cabal-hashes": "https://raw.githubusercontent.com/commercialhaskell/all-cabal-hashes/769ec969c5a81cde769b20e49e11f42ce7841932", + "__GENERATED_FILE_DO_NOT_MODIFY_MANUALLY": -368711695, + "all-cabal-hashes": "https://raw.githubusercontent.com/commercialhaskell/all-cabal-hashes/5b84231c0605b5e0aeec7fc0f15b3463dd699dec", "resolved": { - "Cabal": {"dependencies":["array","base","binary","bytestring","containers","deepseq","directory","filepath","mtl","parsec","pretty","process","text","time","transformers","unix"],"location":{"type":"git","url":"https://github.com/tweag/cabal","commit":"42f04c3f639f10dc3c7981a0c663bfe08ad833cb","subdir":"Cabal"},"name":"Cabal","version":"3.6.3.0"}, + "Cabal": {"dependencies":[],"location":{"type":"core"},"name":"Cabal","version":"3.6.3.0"}, "HUnit": {"dependencies":["base","call-stack","deepseq"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/HUnit-1.6.2.0/HUnit-1.6.2.0.tar.gz"},"name":"HUnit","pinned":{"url":["https://hackage.haskell.org/package/HUnit-1.6.2.0/HUnit-1.6.2.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/HUnit-1.6.2.0.tar.gz"],"sha256":"b0b7538871ffc058486fc00740886d2f3172f8fa6869936bfe83a5e10bd744ab","cabal-sha256":"1a79174e8af616117ad39464cac9de205ca923da6582825e97c10786fda933a4"},"version":"1.6.2.0"}, "QuickCheck": {"dependencies":["base","containers","deepseq","random","splitmix","template-haskell","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/QuickCheck-2.14.2/QuickCheck-2.14.2.tar.gz"},"name":"QuickCheck","pinned":{"url":["https://hackage.haskell.org/package/QuickCheck-2.14.2/QuickCheck-2.14.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/QuickCheck-2.14.2.tar.gz"],"sha256":"d87b6c85696b601175274361fa62217894401e401e150c3c5d4013ac53cd36f3","cabal-sha256":"4ce29211223d5e6620ebceba34a3ca9ccf1c10c0cf387d48aea45599222ee5aa"},"version":"2.14.2"}, "ansi-terminal": {"dependencies":["base","colour"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/ansi-terminal-0.11.4/ansi-terminal-0.11.4.tar.gz"},"name":"ansi-terminal","pinned":{"url":["https://hackage.haskell.org/package/ansi-terminal-0.11.4/ansi-terminal-0.11.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/ansi-terminal-0.11.4.tar.gz"],"sha256":"7898e48f0a535c1857cde52c803f28096ba89759461fe4d157fd55dcdb420e25","cabal-sha256":"410737137c798e23339a08435a5511785ebf1db08700e37debbd7801cf73fc82"},"version":"0.11.4"}, "array": {"dependencies":[],"location":{"type":"core"},"name":"array","version":"0.5.4.0"}, "base": {"dependencies":[],"location":{"type":"core"},"name":"base","version":"4.16.4.0"}, - "binary": {"dependencies":[],"location":{"type":"core"},"name":"binary","version":"0.8.9.0"}, "bytestring": {"dependencies":[],"location":{"type":"core"},"name":"bytestring","version":"0.11.3.1"}, "call-stack": {"dependencies":["base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/call-stack-0.4.0/call-stack-0.4.0.tar.gz"},"name":"call-stack","pinned":{"url":["https://hackage.haskell.org/package/call-stack-0.4.0/call-stack-0.4.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/call-stack-0.4.0.tar.gz"],"sha256":"430bcf8a3404f7e55319573c0b807b1356946f0c8f289bb3d9afb279c636b87b","cabal-sha256":"ac44d2c00931dc20b01750da8c92ec443eb63a7231e8550188cb2ac2385f7feb"},"version":"0.4.0"}, "clock": {"dependencies":["base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/clock-0.8.3/clock-0.8.3.tar.gz"},"name":"clock","pinned":{"url":["https://hackage.haskell.org/package/clock-0.8.3/clock-0.8.3.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/clock-0.8.3.tar.gz"],"sha256":"845ce5db4c98cefd517323e005f87effceff886987305e421c4ef616dc0505d1","cabal-sha256":"a692159828c2cd278eaec317b3a7e9fb6d7b787c8a19f086004d15d9fa1fd72c"},"version":"0.8.3"}, @@ -23,17 +22,13 @@ "hspec-expectations": {"dependencies":["HUnit","base","call-stack"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/hspec-expectations-0.8.2/hspec-expectations-0.8.2.tar.gz"},"name":"hspec-expectations","pinned":{"url":["https://hackage.haskell.org/package/hspec-expectations-0.8.2/hspec-expectations-0.8.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/hspec-expectations-0.8.2.tar.gz"],"sha256":"819607ea1faf35ce5be34be61c6f50f3389ea43892d56fb28c57a9f5d54fb4ef","cabal-sha256":"e2db24881baadc2d9d23b03cb629e80dcbda89a6b04ace9adb5f4d02ef8b31aa"},"version":"0.8.2"}, "mtl": {"dependencies":[],"location":{"type":"core"},"name":"mtl","version":"2.2.2"}, "package1": {"dependencies":["Cabal","base"],"location":{"type":"archive","url":"https://github.com/tweag/rules_haskell/raw/e4e74f17f743488f564bd0d69c580106d5b910a5/tests/haskell_cabal_library_sublibrary_name/package1.tar"},"name":"package1","pinned":{"sha256":"302d8ddda8330c825da61fe0a2315c899ab083e641c7716ebdacb5c951682445","strip-prefix":""},"version":"0.1.0.0"}, - "parsec": {"dependencies":[],"location":{"type":"core"},"name":"parsec","version":"3.1.15.0"}, - "pretty": {"dependencies":[],"location":{"type":"core"},"name":"pretty","version":"1.1.3.6"}, "primitive": {"dependencies":["base","deepseq","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/primitive-0.7.3.0/primitive-0.7.3.0.tar.gz"},"name":"primitive","pinned":{"url":["https://hackage.haskell.org/package/primitive-0.7.3.0/primitive-0.7.3.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/primitive-0.7.3.0.tar.gz"],"sha256":"3c0cfda67f1ee6f7f65108ad6f973b5bbb35ddba34b3c87746a7448f787501dc","cabal-sha256":"ce9361b4d2ed296ef639380411b4cfc217a19e4b3cd4170e03e6fce52daa0176"},"version":"0.7.3.0"}, - "process": {"dependencies":[],"location":{"type":"core"},"name":"process","version":"1.6.16.0"}, "quickcheck-io": {"dependencies":["HUnit","QuickCheck","base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/quickcheck-io-0.2.0/quickcheck-io-0.2.0.tar.gz"},"name":"quickcheck-io","pinned":{"url":["https://hackage.haskell.org/package/quickcheck-io-0.2.0/quickcheck-io-0.2.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/quickcheck-io-0.2.0.tar.gz"],"sha256":"fb779119d79fe08ff4d502fb6869a70c9a8d5fd8ae0959f605c3c937efd96422","cabal-sha256":"7bf0b68fb90873825eb2e5e958c1b76126dcf984debb998e81673e6d837e0b2d"},"version":"0.2.0"}, "random": {"dependencies":["base","bytestring","deepseq","mtl","splitmix"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/random-1.2.1.1/random-1.2.1.1.tar.gz"},"name":"random","pinned":{"url":["https://hackage.haskell.org/package/random-1.2.1.1/random-1.2.1.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/random-1.2.1.1.tar.gz"],"sha256":"3e1272f7ed6a4d7bd1712b90143ec326fee9b225789222379fea20a9c90c9b76","cabal-sha256":"dea1f11e5569332dc6c8efaad1cb301016a5587b6754943a49f9de08ae0e56d9"},"version":"1.2.1.1"}, "setenv": {"dependencies":["base","unix"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/setenv-0.1.1.3/setenv-0.1.1.3.tar.gz"},"name":"setenv","pinned":{"url":["https://hackage.haskell.org/package/setenv-0.1.1.3/setenv-0.1.1.3.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/setenv-0.1.1.3.tar.gz"],"sha256":"e358df39afc03d5a39e2ec650652d845c85c80cc98fe331654deafb4767ecb32","cabal-sha256":"c5916ac0d2a828473cd171261328a290afe0abd799db1ac8c310682fe778c45b"},"version":"0.1.1.3"}, "splitmix": {"dependencies":["base","deepseq"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/splitmix-0.1.0.4/splitmix-0.1.0.4.tar.gz"},"name":"splitmix","pinned":{"url":["https://hackage.haskell.org/package/splitmix-0.1.0.4/splitmix-0.1.0.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/splitmix-0.1.0.4.tar.gz"],"sha256":"6d065402394e7a9117093dbb4530a21342c9b1e2ec509516c8a8d0ffed98ecaa","cabal-sha256":"db25c2e17967aa6b6046ab8b1b96ba3f344ca59a62b60fb6113d51ea305a3d8e"},"version":"0.1.0.4"}, "stm": {"dependencies":[],"location":{"type":"core"},"name":"stm","version":"2.5.0.2"}, "template-haskell": {"dependencies":[],"location":{"type":"core"},"name":"template-haskell","version":"2.18.0.0"}, - "text": {"dependencies":[],"location":{"type":"core"},"name":"text","version":"1.2.5.0"}, "tf-random": {"dependencies":["base","primitive","random","time"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/tf-random-0.5/tf-random-0.5.tar.gz"},"name":"tf-random","pinned":{"url":["https://hackage.haskell.org/package/tf-random-0.5/tf-random-0.5.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/tf-random-0.5.tar.gz"],"sha256":"2e30cec027b313c9e1794d326635d8fc5f79b6bf6e7580ab4b00186dadc88510","cabal-sha256":"14012837d0f0e18fdbbe3d56e67da8622ee5e20b180abce952dd50bd9f36b326"},"version":"0.5"}, "time": {"dependencies":[],"location":{"type":"core"},"name":"time","version":"1.11.1.1"}, "transformers": {"dependencies":[],"location":{"type":"core"},"name":"transformers","version":"0.5.6.2"}, diff --git a/rules_haskell_tests/tests/haskell_module/attr_merging/Plugin.hs b/rules_haskell_tests/tests/haskell_module/attr_merging/Plugin.hs index b63f1690e..4498a6754 100644 --- a/rules_haskell_tests/tests/haskell_module/attr_merging/Plugin.hs +++ b/rules_haskell_tests/tests/haskell_module/attr_merging/Plugin.hs @@ -11,7 +11,7 @@ import GHC.Core.Opt.Monad import GHC.Plugins import GHC.Types.Literal import GHC.Unit.Module.ModGuts --- import GHC.Plugins TODO +import GHC.Plugins import System.Process (readProcess) From 7b381ade87d446a0c3e5780b9fda626a450d54bb Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Mon, 22 May 2023 15:52:09 +0200 Subject: [PATCH 16/41] Use GHC 9.2.5 again --- WORKSPACE | 8 ++++---- constants.bzl | 2 +- start | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/WORKSPACE b/WORKSPACE index 4086a96c9..5bfb6fa31 100755 --- a/WORKSPACE +++ b/WORKSPACE @@ -95,10 +95,10 @@ load( "non_module_deps_1.bzl", "test_cabalopts", "test_ghcopts" ) haskell_register_ghc_bindists_hadrian( - url = "https://downloads.haskell.org/~ghc/9.6.1/ghc-9.6.1-x86_64-deb9-linux.tar.xz", - sha256 = "3c727e93a82ff039fbedd6645518859849130a0fc93b7181cd69a41800aa639c", - strip_prefix = "ghc-9.6.1-x86_64-unknown-linux", - version = "9.6.1", + url = "https://github.com/avdv/testproject/releases/download/ghc-9.2.5/ghc-9.2.5-x86_64-unknown-linux.tar.xz", + sha256 = "9dea9123cd53c0d48e72de68480492eaacc2e0bf487a3cd3dfa3ce18729aa3e4", + strip_prefix = "ghc-9.2.5-x86_64-unknown-linux", + version = "9.2.5", target = "x86_64-unknown-linux", cabalopts = test_cabalopts, ghcopts = test_ghcopts, diff --git a/constants.bzl b/constants.bzl index 4f6a61762..a1a0ccada 100644 --- a/constants.bzl +++ b/constants.bzl @@ -1,2 +1,2 @@ -test_ghc_version = "9.6.1" +test_ghc_version = "9.2.5" test_asterius_version = "0.0.1" diff --git a/start b/start index 31c08ce0b..cf40a7cd0 100755 --- a/start +++ b/start @@ -294,10 +294,10 @@ case "${MODE}" in ] # Download a GHC binary distribution from haskell.org and register it as a toolchain. haskell_register_ghc_bindists_hadrian( - url = "https://downloads.haskell.org/~ghc/9.6.1/ghc-9.6.1-x86_64-deb9-linux.tar.xz", - sha256 = "3c727e93a82ff039fbedd6645518859849130a0fc93b7181cd69a41800aa639c", - strip_prefix = "ghc-9.6.1-x86_64-unknown-linux", - version = "9.6.1", + url = "https://github.com/avdv/testproject/releases/download/ghc-9.2.5/ghc-9.2.5-x86_64-unknown-linux.tar.xz", + sha256 = "9dea9123cd53c0d48e72de68480492eaacc2e0bf487a3cd3dfa3ce18729aa3e4", + strip_prefix = "ghc-9.2.5-x86_64-unknown-linux", + version = "9.2.5", target = "x86_64-unknown-linux", cabalopts = test_cabalopts, ghcopts = test_ghcopts, From 5a13d98969d79f286b5bc52e790847fb46295471 Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Mon, 22 May 2023 16:58:06 +0200 Subject: [PATCH 17/41] Difference between GHC 9.2 / 9.6 hadrian bindist --- haskell/toolchain.bzl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/haskell/toolchain.bzl b/haskell/toolchain.bzl index 27a268144..b832ac68f 100644 --- a/haskell/toolchain.bzl +++ b/haskell/toolchain.bzl @@ -609,9 +609,9 @@ def haskell_toolchain( "config.guess", "config.sub", "install-sh", - "config.mk.in", + "mk/config.mk.in", "mk/project.mk", - "mk/system-cxx-std-lib-1.0.conf.in", + #"mk/system-cxx-std-lib-1.0.conf.in", ], ) From 9d6539e63696d1ddbf42f8b20afc97f46f860c47 Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Mon, 22 May 2023 20:20:26 +0200 Subject: [PATCH 18/41] examples: Use GHC 9.2.5 --- examples/WORKSPACE | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/WORKSPACE b/examples/WORKSPACE index 0d040f658..045a3af2b 100644 --- a/examples/WORKSPACE +++ b/examples/WORKSPACE @@ -58,10 +58,10 @@ test_cabalopts = [ # ) haskell_register_ghc_bindists_hadrian( - url = "https://downloads.haskell.org/~ghc/9.6.1/ghc-9.6.1-x86_64-deb9-linux.tar.xz", - sha256 = "3c727e93a82ff039fbedd6645518859849130a0fc93b7181cd69a41800aa639c", - strip_prefix = "ghc-9.6.1-x86_64-unknown-linux", - version = "9.6.1", + url = "https://github.com/avdv/testproject/releases/download/ghc-9.2.5/ghc-9.2.5-x86_64-unknown-linux.tar.xz", + sha256 = "9dea9123cd53c0d48e72de68480492eaacc2e0bf487a3cd3dfa3ce18729aa3e4", + strip_prefix = "ghc-9.2.5-x86_64-unknown-linux", + version = "9.2.5", target = "x86_64-unknown-linux", cabalopts = test_cabalopts, ghcopts = test_ghcopts, From cc3fcaca08231c4504094fef779e884eb4d78e5a Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Tue, 23 May 2023 08:15:45 +0200 Subject: [PATCH 19/41] Revert "Update stackage snapshot" This reverts commit f81b9ab9eb64a48f742a5010ada5b7ae67bc13fe. --- stackage_snapshot.json | 75 +++++++++++++++++++++--------------------- stackage_snapshot.yaml | 8 ++++- 2 files changed, 44 insertions(+), 39 deletions(-) diff --git a/stackage_snapshot.json b/stackage_snapshot.json index 4b83a6daa..e9b828cc4 100644 --- a/stackage_snapshot.json +++ b/stackage_snapshot.json @@ -1,28 +1,28 @@ { - "__GENERATED_FILE_DO_NOT_MODIFY_MANUALLY": 50776380, - "all-cabal-hashes": "https://raw.githubusercontent.com/commercialhaskell/all-cabal-hashes/c2e1693fe34c7825e36dbe10bfbf921ed344d594", + "__GENERATED_FILE_DO_NOT_MODIFY_MANUALLY": 1257643182, + "all-cabal-hashes": "https://raw.githubusercontent.com/commercialhaskell/all-cabal-hashes/c74af1256291cf0dc83731d2b2088cf4422fcfd3", "resolved": { - "Cabal": {"dependencies":[],"location":{"type":"core"},"name":"Cabal","version":"3.6.3.0"}, + "Cabal": {"dependencies":["array","base","binary","bytestring","containers","deepseq","directory","filepath","mtl","parsec","pretty","process","text","time","transformers","unix"],"location":{"type":"git","url":"https://github.com/tweag/cabal","commit":"42f04c3f639f10dc3c7981a0c663bfe08ad833cb","subdir":"Cabal"},"name":"Cabal","version":"3.6.3.0"}, "HUnit": {"dependencies":["base","call-stack","deepseq"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/HUnit-1.6.2.0/HUnit-1.6.2.0.tar.gz"},"name":"HUnit","pinned":{"url":["https://hackage.haskell.org/package/HUnit-1.6.2.0/HUnit-1.6.2.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/HUnit-1.6.2.0.tar.gz"],"sha256":"b0b7538871ffc058486fc00740886d2f3172f8fa6869936bfe83a5e10bd744ab","cabal-sha256":"1a79174e8af616117ad39464cac9de205ca923da6582825e97c10786fda933a4"},"version":"1.6.2.0"}, "QuickCheck": {"dependencies":["base","containers","deepseq","random","splitmix","template-haskell","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/QuickCheck-2.14.2/QuickCheck-2.14.2.tar.gz"},"name":"QuickCheck","pinned":{"url":["https://hackage.haskell.org/package/QuickCheck-2.14.2/QuickCheck-2.14.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/QuickCheck-2.14.2.tar.gz"],"sha256":"d87b6c85696b601175274361fa62217894401e401e150c3c5d4013ac53cd36f3","cabal-sha256":"4ce29211223d5e6620ebceba34a3ca9ccf1c10c0cf387d48aea45599222ee5aa"},"version":"2.14.2"}, "StateVar": {"dependencies":["base","stm","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/StateVar-1.2.2/StateVar-1.2.2.tar.gz"},"name":"StateVar","pinned":{"url":["https://hackage.haskell.org/package/StateVar-1.2.2/StateVar-1.2.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/StateVar-1.2.2.tar.gz"],"sha256":"5e4b39da395656a59827b0280508aafdc70335798b50e5d6fd52596026251825","cabal-sha256":"3c022c00485fe165e3080d5da6b3ca9c9b02f62c5deebc584d1b3d1309ce673e"},"version":"1.2.2"}, - "alex": {"dependencies":["array","base","containers","directory"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/alex-3.2.7.4/alex-3.2.7.4.tar.gz"},"name":"alex","pinned":{"url":["https://hackage.haskell.org/package/alex-3.2.7.4/alex-3.2.7.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/alex-3.2.7.4.tar.gz"],"sha256":"8a13fa01ea00883aa3d75d15ce848835b18631b8c9a4966961492d7c6095226f","cabal-sha256":"91f4b0bf2f0eca6966bab39975adc440a9d9929dc8729bf92c95c3296dcb25b9"},"version":"3.2.7.4"}, + "alex": {"dependencies":["array","base","containers","directory"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/alex-3.2.7.1/alex-3.2.7.1.tar.gz"},"name":"alex","pinned":{"url":["https://hackage.haskell.org/package/alex-3.2.7.1/alex-3.2.7.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/alex-3.2.7.1.tar.gz"],"sha256":"9bd2f1a27e8f1b2ffdb5b2fbd3ed82b6f0e85191459a1b24ffcbef4e68a81bec","cabal-sha256":"ab26a38cefae59403f746370e5a0c943b8d5bda098eb83f37052b2429ee780ce"},"version":"3.2.7.1"}, "ansi-terminal": {"dependencies":["base","colour"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/ansi-terminal-0.11.4/ansi-terminal-0.11.4.tar.gz"},"name":"ansi-terminal","pinned":{"url":["https://hackage.haskell.org/package/ansi-terminal-0.11.4/ansi-terminal-0.11.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/ansi-terminal-0.11.4.tar.gz"],"sha256":"7898e48f0a535c1857cde52c803f28096ba89759461fe4d157fd55dcdb420e25","cabal-sha256":"410737137c798e23339a08435a5511785ebf1db08700e37debbd7801cf73fc82"},"version":"0.11.4"}, - "ansi-wl-pprint": {"dependencies":["ansi-terminal","base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/ansi-wl-pprint-0.6.9/ansi-wl-pprint-0.6.9.tar.gz"},"name":"ansi-wl-pprint","pinned":{"url":["https://hackage.haskell.org/package/ansi-wl-pprint-0.6.9/ansi-wl-pprint-0.6.9.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/ansi-wl-pprint-0.6.9.tar.gz"],"sha256":"a7b2e8e7cd3f02f2954e8b17dc60a0ccd889f49e2068ebb15abfa1d42f7a4eac","cabal-sha256":"fb737bc96e2aef34ad595d54ced7a73f648c521ebcb00fe0679aff45ccd49212"},"version":"0.6.9"}, + "ansi-wl-pprint": {"dependencies":["ansi-terminal","base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/ansi-wl-pprint-0.6.9/ansi-wl-pprint-0.6.9.tar.gz"},"name":"ansi-wl-pprint","pinned":{"url":["https://hackage.haskell.org/package/ansi-wl-pprint-0.6.9/ansi-wl-pprint-0.6.9.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/ansi-wl-pprint-0.6.9.tar.gz"],"sha256":"a7b2e8e7cd3f02f2954e8b17dc60a0ccd889f49e2068ebb15abfa1d42f7a4eac","cabal-sha256":"212144ea0623b1170807a4162db05d87f26cf10b334aeadd0edb377aba06a1ce"},"version":"0.6.9"}, "array": {"dependencies":[],"location":{"type":"core"},"name":"array","version":"0.5.4.0"}, - "async": {"dependencies":["base","hashable","stm"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/async-2.2.4/async-2.2.4.tar.gz"},"name":"async","pinned":{"url":["https://hackage.haskell.org/package/async-2.2.4/async-2.2.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/async-2.2.4.tar.gz"],"sha256":"484df85be0e76c4fed9376451e48e1d0c6e97952ce79735b72d54297e7e0a725","cabal-sha256":"46367dc0c8326dcbeb7b93f200b567491c2f6029bccf822b8bb26ee660397e08"},"version":"2.2.4"}, + "async": {"dependencies":["base","hashable","stm"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/async-2.2.4/async-2.2.4.tar.gz"},"name":"async","pinned":{"url":["https://hackage.haskell.org/package/async-2.2.4/async-2.2.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/async-2.2.4.tar.gz"],"sha256":"484df85be0e76c4fed9376451e48e1d0c6e97952ce79735b72d54297e7e0a725","cabal-sha256":"2b9409023536823233ce3134558565d01b3382e651fa54ac8cb8a99967e023c9"},"version":"2.2.4"}, "atomic-primops": {"dependencies":["base","ghc-prim","primitive"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/atomic-primops-0.8.4/atomic-primops-0.8.4.tar.gz"},"name":"atomic-primops","pinned":{"url":["https://hackage.haskell.org/package/atomic-primops-0.8.4/atomic-primops-0.8.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/atomic-primops-0.8.4.tar.gz"],"sha256":"22a8617eb9e221b5daee1ae26ccce279ce3d7a53d76e82c767708f90a6c72d3e","cabal-sha256":"5218db0d8d4efe203a06c4643a0c6aeb3ab1abe159e92c122decc4f0dd1b5f38"},"version":"0.8.4"}, - "attoparsec": {"dependencies":["array","base","bytestring","containers","deepseq","ghc-prim","scientific","text","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/attoparsec-0.14.4/attoparsec-0.14.4.tar.gz"},"name":"attoparsec","pinned":{"url":["https://hackage.haskell.org/package/attoparsec-0.14.4/attoparsec-0.14.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/attoparsec-0.14.4.tar.gz"],"sha256":"3f337fe58624565de12426f607c23e60c7b09c86b4e3adfc827ca188c9979e6c","cabal-sha256":"50475b722305175f57a3ee3dbaee10aa4b91f61c9717b85b718a7df37c223fb2"},"version":"0.14.4"}, + "attoparsec": {"dependencies":["array","base","bytestring","containers","deepseq","ghc-prim","scientific","text","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/attoparsec-0.14.4/attoparsec-0.14.4.tar.gz"},"name":"attoparsec","pinned":{"url":["https://hackage.haskell.org/package/attoparsec-0.14.4/attoparsec-0.14.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/attoparsec-0.14.4.tar.gz"],"sha256":"3f337fe58624565de12426f607c23e60c7b09c86b4e3adfc827ca188c9979e6c","cabal-sha256":"c0569d86c02cadd403017ea414dcb5e4f7de5380de0d8a92b9337cad84cd5e02"},"version":"0.14.4"}, "base": {"dependencies":[],"location":{"type":"core"},"name":"base","version":"4.16.4.0"}, "base-compat": {"dependencies":["base","ghc-prim","unix"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/base-compat-0.12.2/base-compat-0.12.2.tar.gz"},"name":"base-compat","pinned":{"url":["https://hackage.haskell.org/package/base-compat-0.12.2/base-compat-0.12.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/base-compat-0.12.2.tar.gz"],"sha256":"a62adc883a5ac436f80e4ae02c3c56111cf1007492f267c291139a668d2150bd","cabal-sha256":"85d820a15e3f00f1781ac939cb9cdccdcc6f38c43e4c74a6e83e5d75f67b61a0"},"version":"0.12.2"}, "base-compat-batteries": {"dependencies":["base","base-compat","ghc-prim"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/base-compat-batteries-0.12.2/base-compat-batteries-0.12.2.tar.gz"},"name":"base-compat-batteries","pinned":{"url":["https://hackage.haskell.org/package/base-compat-batteries-0.12.2/base-compat-batteries-0.12.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/base-compat-batteries-0.12.2.tar.gz"],"sha256":"ede9092e07f904e0759160bf1ecd3fb7eb043bae6dc89a37c3dc94829ec5eb99","cabal-sha256":"ecf0bb2b39be54f1ffa185d37663702b0651d34d1cdcc32d32bb8f7279396afe"},"version":"0.12.2"}, - "base-orphans": {"dependencies":["base","ghc-prim"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/base-orphans-0.8.8.2/base-orphans-0.8.8.2.tar.gz"},"name":"base-orphans","pinned":{"url":["https://hackage.haskell.org/package/base-orphans-0.8.8.2/base-orphans-0.8.8.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/base-orphans-0.8.8.2.tar.gz"],"sha256":"61cae7063884128dc98596ab7d8e6d896f6b0fa3da4e12310c850c8c08825092","cabal-sha256":"b62d60c8b7c507f0d0085925fad398e4fcda928c14b524be0148effd99cfb97d"},"version":"0.8.8.2"}, - "bifunctors": {"dependencies":["base","base-orphans","comonad","containers","tagged","template-haskell","th-abstraction","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/bifunctors-5.5.15/bifunctors-5.5.15.tar.gz"},"name":"bifunctors","pinned":{"url":["https://hackage.haskell.org/package/bifunctors-5.5.15/bifunctors-5.5.15.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/bifunctors-5.5.15.tar.gz"],"sha256":"d6359d50d359dd6048dbf6d56c7628211a1785aab9174177faa6d2d8b0d9e3b7","cabal-sha256":"5ebaf9a1996de38ad9d77bec37a5585b6461b34f39446e8f1cadae7689a12bfd"},"version":"5.5.15"}, + "base-orphans": {"dependencies":["base","ghc-prim"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/base-orphans-0.8.7/base-orphans-0.8.7.tar.gz"},"name":"base-orphans","pinned":{"url":["https://hackage.haskell.org/package/base-orphans-0.8.7/base-orphans-0.8.7.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/base-orphans-0.8.7.tar.gz"],"sha256":"888fd67f0dbe932778f5b170922ce80d0dcab1680ee98f1d6fcc362f20d9e447","cabal-sha256":"58d5514b688ec037f53b9d60097b9d87f6b3847da68f65124987d67222c3a334"},"version":"0.8.7"}, + "bifunctors": {"dependencies":["base","base-orphans","comonad","containers","tagged","template-haskell","th-abstraction","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/bifunctors-5.5.13/bifunctors-5.5.13.tar.gz"},"name":"bifunctors","pinned":{"url":["https://hackage.haskell.org/package/bifunctors-5.5.13/bifunctors-5.5.13.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/bifunctors-5.5.13.tar.gz"],"sha256":"26cc27ade3796cf03bd680f98ebb7b8c0d7fd1b67c1894dc3635f734fba7dbd7","cabal-sha256":"66f1c1d0cba5de9d8810e2ef0be700b98d3689482f605cc46a69283e92a60840"},"version":"5.5.13"}, "binary": {"dependencies":[],"location":{"type":"core"},"name":"binary","version":"0.8.9.0"}, - "bytestring": {"dependencies":[],"location":{"type":"core"},"name":"bytestring","version":"0.11.4.0"}, + "bytestring": {"dependencies":[],"location":{"type":"core"},"name":"bytestring","version":"0.11.3.1"}, "bytestring-builder": {"dependencies":["base","bytestring","deepseq"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/bytestring-builder-0.10.8.2.0/bytestring-builder-0.10.8.2.0.tar.gz"},"name":"bytestring-builder","pinned":{"url":["https://hackage.haskell.org/package/bytestring-builder-0.10.8.2.0/bytestring-builder-0.10.8.2.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/bytestring-builder-0.10.8.2.0.tar.gz"],"sha256":"27faef6db27c5be5a3715fd68b93725853e0e668849eaf92ce7c33cef9cb2c3f","cabal-sha256":"6b2b812cdac53f5a2c82376a416dde04adbb5ca3e1604c0d075368a0498f762b"},"version":"0.10.8.2.0"}, "c2hs": {"dependencies":["array","base","bytestring","containers","directory","dlist","filepath","language-c","pretty","process"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/c2hs-0.28.8/c2hs-0.28.8.tar.gz"},"name":"c2hs","pinned":{"url":["https://hackage.haskell.org/package/c2hs-0.28.8/c2hs-0.28.8.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/c2hs-0.28.8.tar.gz"],"sha256":"390632cffc561c32483af474aac50168a68f0fa382096552e37749923617884c","cabal-sha256":"c399132e2273e70770be403fba4795d7d8c60d7bd147f0ef174342bebbd44392"},"version":"0.28.8"}, - "cabal-doctest": {"dependencies":["Cabal","base","directory","filepath"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/cabal-doctest-1.0.9/cabal-doctest-1.0.9.tar.gz"},"name":"cabal-doctest","pinned":{"url":["https://hackage.haskell.org/package/cabal-doctest-1.0.9/cabal-doctest-1.0.9.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/cabal-doctest-1.0.9.tar.gz"],"sha256":"5556088496111d33810c4ae6c4a065bb37fa3315e9e8891e8000b1ab6707ba73","cabal-sha256":"6dea0dbd1457f43d96ce1cfb1bab8b9f55d4fb82940e2bfa5aad78e6e2260656"},"version":"1.0.9"}, + "cabal-doctest": {"dependencies":["Cabal","base","directory","filepath"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/cabal-doctest-1.0.9/cabal-doctest-1.0.9.tar.gz"},"name":"cabal-doctest","pinned":{"url":["https://hackage.haskell.org/package/cabal-doctest-1.0.9/cabal-doctest-1.0.9.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/cabal-doctest-1.0.9.tar.gz"],"sha256":"5556088496111d33810c4ae6c4a065bb37fa3315e9e8891e8000b1ab6707ba73","cabal-sha256":"21823c6227a483b4faf210d7a55d435563ff69ddf94b48b8af1bba878196c820"},"version":"1.0.9"}, "call-stack": {"dependencies":["base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/call-stack-0.4.0/call-stack-0.4.0.tar.gz"},"name":"call-stack","pinned":{"url":["https://hackage.haskell.org/package/call-stack-0.4.0/call-stack-0.4.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/call-stack-0.4.0.tar.gz"],"sha256":"430bcf8a3404f7e55319573c0b807b1356946f0c8f289bb3d9afb279c636b87b","cabal-sha256":"ac44d2c00931dc20b01750da8c92ec443eb63a7231e8550188cb2ac2385f7feb"},"version":"0.4.0"}, "clock": {"dependencies":["base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/clock-0.8.3/clock-0.8.3.tar.gz"},"name":"clock","pinned":{"url":["https://hackage.haskell.org/package/clock-0.8.3/clock-0.8.3.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/clock-0.8.3.tar.gz"],"sha256":"845ce5db4c98cefd517323e005f87effceff886987305e421c4ef616dc0505d1","cabal-sha256":"a692159828c2cd278eaec317b3a7e9fb6d7b787c8a19f086004d15d9fa1fd72c"},"version":"0.8.3"}, "code-page": {"dependencies":["base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/code-page-0.2.1/code-page-0.2.1.tar.gz"},"name":"code-page","pinned":{"url":["https://hackage.haskell.org/package/code-page-0.2.1/code-page-0.2.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/code-page-0.2.1.tar.gz"],"sha256":"b2f90e19c61ed8a6ff7295f7f123d4a9913c790d4cf2c6029bc299293fdb2aaa","cabal-sha256":"fe596b0f421abd2894fdb7049b3d76230eb1de6e04e9f635e2695dd55ded856e"},"version":"0.2.1"}, @@ -32,7 +32,6 @@ "conduit-extra": {"dependencies":["async","attoparsec","base","bytestring","conduit","directory","filepath","network","primitive","process","resourcet","stm","streaming-commons","text","transformers","typed-process","unliftio-core"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/conduit-extra-1.3.6/conduit-extra-1.3.6.tar.gz"},"name":"conduit-extra","pinned":{"url":["https://hackage.haskell.org/package/conduit-extra-1.3.6/conduit-extra-1.3.6.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/conduit-extra-1.3.6.tar.gz"],"sha256":"8950c38049d892c38590d389bed49ecf880671f58ec63dd4709d9fe3d4b8f153","cabal-sha256":"83303e6fea78a683fdbb41682fc8dbc47b1d8830da1f09e88940f9a744a7f984"},"version":"1.3.6"}, "containers": {"dependencies":[],"location":{"type":"core"},"name":"containers","version":"0.6.5.1"}, "contravariant": {"dependencies":["StateVar","base","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/contravariant-1.5.5/contravariant-1.5.5.tar.gz"},"name":"contravariant","pinned":{"url":["https://hackage.haskell.org/package/contravariant-1.5.5/contravariant-1.5.5.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/contravariant-1.5.5.tar.gz"],"sha256":"062fd66580d7aad0b5ba93e644ffa7feee69276ef50f20d4ed9f1deb7642dffa","cabal-sha256":"470ed0e040e879e2da4af1b2c8f94e199f6135852a8107858d5ae0a95365835f"},"version":"1.5.5"}, - "data-array-byte": {"dependencies":["base","deepseq","template-haskell"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/data-array-byte-0.1.0.1/data-array-byte-0.1.0.1.tar.gz"},"name":"data-array-byte","pinned":{"url":["https://hackage.haskell.org/package/data-array-byte-0.1.0.1/data-array-byte-0.1.0.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/data-array-byte-0.1.0.1.tar.gz"],"sha256":"1bb6eca0b3e02d057fe7f4e14c81ef395216f421ab30fdaa1b18017c9c025600","cabal-sha256":"2ef1bd3511e82ba56f7f23cd793dd2da84338a1e7c2cbea5b151417afe3baada"},"version":"0.1.0.1"}, "data-default-class": {"dependencies":["base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/data-default-class-0.1.2.0/data-default-class-0.1.2.0.tar.gz"},"name":"data-default-class","pinned":{"url":["https://hackage.haskell.org/package/data-default-class-0.1.2.0/data-default-class-0.1.2.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/data-default-class-0.1.2.0.tar.gz"],"sha256":"4f01b423f000c3e069aaf52a348564a6536797f31498bb85c3db4bd2d0973e56","cabal-sha256":"63e62120b7efd733a5a17cf59ceb43268e9a929c748127172d7d42f4a336e327"},"version":"0.1.2.0"}, "deepseq": {"dependencies":[],"location":{"type":"core"},"name":"deepseq","version":"1.4.6.1"}, "directory": {"dependencies":[],"location":{"type":"core"},"name":"directory","version":"1.3.6.2"}, @@ -42,75 +41,75 @@ "exceptions": {"dependencies":[],"location":{"type":"core"},"name":"exceptions","version":"0.10.4"}, "filepath": {"dependencies":[],"location":{"type":"core"},"name":"filepath","version":"1.4.2.2"}, "first-class-families": {"dependencies":["base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/first-class-families-0.8.0.1/first-class-families-0.8.0.1.tar.gz"},"name":"first-class-families","pinned":{"url":["https://hackage.haskell.org/package/first-class-families-0.8.0.1/first-class-families-0.8.0.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/first-class-families-0.8.0.1.tar.gz"],"sha256":"4a1c8fbdbe01757ea8dc3190050d7a4a72c86e205d23676182292fe192c1da72","cabal-sha256":"d7a60485a2f392818808d4decbc6af7c20281713ec1d81948747f1c9c8c2b145"},"version":"0.8.0.1"}, - "generic-deriving": {"dependencies":["base","containers","ghc-prim","template-haskell","th-abstraction"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/generic-deriving-1.14.4/generic-deriving-1.14.4.tar.gz"},"name":"generic-deriving","pinned":{"url":["https://hackage.haskell.org/package/generic-deriving-1.14.4/generic-deriving-1.14.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/generic-deriving-1.14.4.tar.gz"],"sha256":"372b87b2c91ed4ceff8602024a484944f4653456066755803b5cb268fed8195c","cabal-sha256":"8395764ff8bef9e688b9681dff3bcd0dbb324a22192e5981bcba10afa75b9ac4"},"version":"1.14.4"}, - "ghc": {"dependencies":[],"location":{"type":"core"},"name":"ghc","version":"9.2.7"}, + "generic-deriving": {"dependencies":["base","containers","ghc-prim","template-haskell","th-abstraction"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/generic-deriving-1.14.2/generic-deriving-1.14.2.tar.gz"},"name":"generic-deriving","pinned":{"url":["https://hackage.haskell.org/package/generic-deriving-1.14.2/generic-deriving-1.14.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/generic-deriving-1.14.2.tar.gz"],"sha256":"265e351117d451afaa37821ce91b44a02611cc94c7ed917a19e1efb0cc63aa2f","cabal-sha256":"55ea5f8c2c386f1791ca0053c89e6dd9d7d8c8fda0bd677f230164cad891539b"},"version":"1.14.2"}, + "ghc": {"dependencies":[],"location":{"type":"core"},"name":"ghc","version":"9.2.5"}, "ghc-bignum": {"dependencies":[],"location":{"type":"core"},"name":"ghc-bignum","version":"1.2"}, - "ghc-boot": {"dependencies":[],"location":{"type":"core"},"name":"ghc-boot","version":"9.2.7"}, - "ghc-boot-th": {"dependencies":[],"location":{"type":"core"},"name":"ghc-boot-th","version":"9.2.7"}, + "ghc-boot": {"dependencies":[],"location":{"type":"core"},"name":"ghc-boot","version":"9.2.5"}, + "ghc-boot-th": {"dependencies":[],"location":{"type":"core"},"name":"ghc-boot-th","version":"9.2.5"}, "ghc-check": {"dependencies":["base","containers","directory","filepath","ghc","ghc-boot","ghc-paths","process","safe-exceptions","template-haskell","th-compat","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/ghc-check-0.5.0.8/ghc-check-0.5.0.8.tar.gz"},"name":"ghc-check","pinned":{"url":["https://hackage.haskell.org/package/ghc-check-0.5.0.8/ghc-check-0.5.0.8.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/ghc-check-0.5.0.8.tar.gz"],"sha256":"1025a8353fb7c318b27b8dc6b268d22f1f64c271031ed0ce4defb0f9100d7cd4","cabal-sha256":"4abee5e907b63c986ff4f130fa5a02a933a165af18bda98bff380763a9c1ad47"},"version":"0.5.0.8"}, - "ghc-heap": {"dependencies":[],"location":{"type":"core"},"name":"ghc-heap","version":"9.2.7"}, + "ghc-heap": {"dependencies":[],"location":{"type":"core"},"name":"ghc-heap","version":"9.2.5"}, "ghc-paths": {"dependencies":["base"],"location":{"type":"vendored"},"name":"ghc-paths","version":"0.1.0.11"}, "ghc-prim": {"dependencies":[],"location":{"type":"core"},"name":"ghc-prim","version":"0.8.0"}, "ghc-source-gen": {"dependencies":["base","ghc"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/ghc-source-gen-0.4.3.0/ghc-source-gen-0.4.3.0.tar.gz"},"name":"ghc-source-gen","pinned":{"url":["https://hackage.haskell.org/package/ghc-source-gen-0.4.3.0/ghc-source-gen-0.4.3.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/ghc-source-gen-0.4.3.0.tar.gz"],"sha256":"0e88038ab714cbe420da8ea15f5cd78565828e9dd956a461283bbe15e9d418d2","cabal-sha256":"9058ddc2e3201d7b2e5a91b79d76f952c5fb01fb34d742143e9c9b365589ad35"},"version":"0.4.3.0"}, - "happy": {"dependencies":["array","base","containers","mtl"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/happy-1.20.1.1/happy-1.20.1.1.tar.gz"},"name":"happy","pinned":{"url":["https://hackage.haskell.org/package/happy-1.20.1.1/happy-1.20.1.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/happy-1.20.1.1.tar.gz"],"sha256":"8b4e7dc5a6c5fd666f8f7163232931ab28746d0d17da8fa1cbd68be9e878881b","cabal-sha256":"a381633c5e8f9e9e5a8e1900930ce13172397b4677fcfcc08cd38eb3f73b61b1"},"version":"1.20.1.1"}, - "hashable": {"dependencies":["base","bytestring","containers","data-array-byte","deepseq","filepath","ghc-bignum","ghc-prim","text"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/hashable-1.4.2.0/hashable-1.4.2.0.tar.gz"},"name":"hashable","pinned":{"url":["https://hackage.haskell.org/package/hashable-1.4.2.0/hashable-1.4.2.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/hashable-1.4.2.0.tar.gz"],"sha256":"1b4000ea82b81f69d46d0af4152c10c6303873510738e24cfc4767760d30e3f8","cabal-sha256":"585792335d5541dba78fa8dfcb291a89cd5812a281825ff7a44afa296ab5d58a"},"version":"1.4.2.0"}, + "happy": {"dependencies":["array","base","containers","mtl"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/happy-1.20.0/happy-1.20.0.tar.gz"},"name":"happy","pinned":{"url":["https://hackage.haskell.org/package/happy-1.20.0/happy-1.20.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/happy-1.20.0.tar.gz"],"sha256":"3b1d3a8f93a2723b554d9f07b2cd136be1a7b2fcab1855b12b7aab5cbac8868c","cabal-sha256":"5d47dc221a9fe964e36aaaa2e1ab7e8f085a225fd6528d6eff310b92360bbe99"},"version":"1.20.0"}, + "hashable": {"dependencies":["base","bytestring","containers","deepseq","ghc-bignum","ghc-prim","text"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/hashable-1.4.1.0/hashable-1.4.1.0.tar.gz"},"name":"hashable","pinned":{"url":["https://hackage.haskell.org/package/hashable-1.4.1.0/hashable-1.4.1.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/hashable-1.4.1.0.tar.gz"],"sha256":"e1b305c280e66ad827edeaedd6933b9fc4174f626882877eab2a08344e665e87","cabal-sha256":"50b2f002c68fe67730ee7a3cd8607486197dd99b084255005ad51ecd6970a41b"},"version":"1.4.1.0"}, "hspec": {"dependencies":["QuickCheck","base","hspec-core","hspec-discover","hspec-expectations"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/hspec-2.9.7/hspec-2.9.7.tar.gz"},"name":"hspec","pinned":{"url":["https://hackage.haskell.org/package/hspec-2.9.7/hspec-2.9.7.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/hspec-2.9.7.tar.gz"],"sha256":"81ddacf76445fb547010d3582ec9d81d7cd9285258ca74bfeefd653525765a24","cabal-sha256":"68732c76946f111db3ecf28fa1ab11f1468c287448b139e57d543bd25a382cf0"},"version":"2.9.7"}, "hspec-core": {"dependencies":["HUnit","QuickCheck","ansi-terminal","array","base","call-stack","clock","deepseq","directory","filepath","ghc","ghc-boot-th","hspec-expectations","quickcheck-io","random","setenv","stm","tf-random","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/hspec-core-2.9.7/hspec-core-2.9.7.tar.gz"},"name":"hspec-core","pinned":{"url":["https://hackage.haskell.org/package/hspec-core-2.9.7/hspec-core-2.9.7.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/hspec-core-2.9.7.tar.gz"],"sha256":"16819b4b10fd22be4a72ec7f919417f722b0eba448c62be538e34e8e23fe1910","cabal-sha256":"153ca954ceb8eb7dff782d3de9af59553bc54284a45e7085aca5b443a5486111"},"version":"2.9.7"}, "hspec-discover": {"dependencies":["base","directory","filepath"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/hspec-discover-2.9.7/hspec-discover-2.9.7.tar.gz"},"name":"hspec-discover","pinned":{"url":["https://hackage.haskell.org/package/hspec-discover-2.9.7/hspec-discover-2.9.7.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/hspec-discover-2.9.7.tar.gz"],"sha256":"65e933fe21a88a15409b0ec4d6d67fccacbaa410b96ece9e59e81a2e7b9b6614","cabal-sha256":"7b8e52d85c07e8cfed6723255f738fb69ae08d3c0edfd3e458837496897ee629"},"version":"2.9.7"}, "hspec-expectations": {"dependencies":["HUnit","base","call-stack"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/hspec-expectations-0.8.2/hspec-expectations-0.8.2.tar.gz"},"name":"hspec-expectations","pinned":{"url":["https://hackage.haskell.org/package/hspec-expectations-0.8.2/hspec-expectations-0.8.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/hspec-expectations-0.8.2.tar.gz"],"sha256":"819607ea1faf35ce5be34be61c6f50f3389ea43892d56fb28c57a9f5d54fb4ef","cabal-sha256":"e2db24881baadc2d9d23b03cb629e80dcbda89a6b04ace9adb5f4d02ef8b31aa"},"version":"0.8.2"}, - "indexed-traversable": {"dependencies":["array","base","containers","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/indexed-traversable-0.1.2.1/indexed-traversable-0.1.2.1.tar.gz"},"name":"indexed-traversable","pinned":{"url":["https://hackage.haskell.org/package/indexed-traversable-0.1.2.1/indexed-traversable-0.1.2.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/indexed-traversable-0.1.2.1.tar.gz"],"sha256":"fe854c10285debc7d6fe3e09da0928a740ebc091ad2911ae695bb007e6f746a4","cabal-sha256":"154b4649199a602dea948a93cb34a6c4be71576c4f78410733dd9f6bc79b6e0b"},"version":"0.1.2.1"}, + "indexed-traversable": {"dependencies":["array","base","containers","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/indexed-traversable-0.1.2/indexed-traversable-0.1.2.tar.gz"},"name":"indexed-traversable","pinned":{"url":["https://hackage.haskell.org/package/indexed-traversable-0.1.2/indexed-traversable-0.1.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/indexed-traversable-0.1.2.tar.gz"],"sha256":"516858ee7198b1fed1b93c665157f9855fd947379db7f115d48c1b0d670e698d","cabal-sha256":"52a1b708abd921f91a5977f6ae53c4aa2b33f7c30be0fff17173f658b34c5350"},"version":"0.1.2"}, "integer-logarithms": {"dependencies":["array","base","ghc-bignum","ghc-prim"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/integer-logarithms-1.0.3.1/integer-logarithms-1.0.3.1.tar.gz"},"name":"integer-logarithms","pinned":{"url":["https://hackage.haskell.org/package/integer-logarithms-1.0.3.1/integer-logarithms-1.0.3.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/integer-logarithms-1.0.3.1.tar.gz"],"sha256":"9b0a9f9fab609b15cd015865721fb05f744a1bc77ae92fd133872de528bbea7f","cabal-sha256":"336fb40c3af19a59dbeb4e5b7bffe4b4c7fa04ab06006a8d4b70b1febc1bb4ca"},"version":"1.0.3.1"}, - "language-c": {"dependencies":["alex","array","base","bytestring","containers","deepseq","directory","filepath","happy","mtl","pretty","process"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/language-c-0.9.2/language-c-0.9.2.tar.gz"},"name":"language-c","pinned":{"url":["https://hackage.haskell.org/package/language-c-0.9.2/language-c-0.9.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/language-c-0.9.2.tar.gz"],"sha256":"b2310d2fda16df72e9f8f63ef18bec2e09ae3aff5891dc948c3d9cb72cef6cb3","cabal-sha256":"a4b77129d7d30d777e0f203ba9c18b88f4791f95c079fef573b554f915dcf57d"},"version":"0.9.2"}, + "language-c": {"dependencies":["alex","array","base","bytestring","containers","deepseq","directory","filepath","happy","mtl","pretty","process"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/language-c-0.9.1/language-c-0.9.1.tar.gz"},"name":"language-c","pinned":{"url":["https://hackage.haskell.org/package/language-c-0.9.1/language-c-0.9.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/language-c-0.9.1.tar.gz"],"sha256":"94359566eb5da62f539fa62500f8a861db4e3eafb956d66c6821d6ffad96ad3c","cabal-sha256":"381f68bb37c00afb0f81b936f6a60066b588b5b4d4ae83a468477739ab02db01"},"version":"0.9.1"}, "lens-family": {"dependencies":["base","containers","lens-family-core","mtl","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/lens-family-2.1.2/lens-family-2.1.2.tar.gz"},"name":"lens-family","pinned":{"url":["https://hackage.haskell.org/package/lens-family-2.1.2/lens-family-2.1.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/lens-family-2.1.2.tar.gz"],"sha256":"2b60afc3afc03b6e328fc96e291e21bb0a63b563657cabe7ba5febd471283648","cabal-sha256":"c13af34889ed9637b2dbd4542122c01a6ec1351cc6dda673de0079f9b02747ef"},"version":"2.1.2"}, "lens-family-core": {"dependencies":["base","containers","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/lens-family-core-2.1.2/lens-family-core-2.1.2.tar.gz"},"name":"lens-family-core","pinned":{"url":["https://hackage.haskell.org/package/lens-family-core-2.1.2/lens-family-core-2.1.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/lens-family-core-2.1.2.tar.gz"],"sha256":"1b5a997276c8b77a96f99f48b95b204d34f3bb84fa3691747cd30bc8c76873b6","cabal-sha256":"702013af981089f991c93598762b8804314266c2bd7d92fc35fb6a8b62af1883"},"version":"2.1.2"}, "mmorph": {"dependencies":["base","mtl","transformers","transformers-compat"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/mmorph-1.2.0/mmorph-1.2.0.tar.gz"},"name":"mmorph","pinned":{"url":["https://hackage.haskell.org/package/mmorph-1.2.0/mmorph-1.2.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/mmorph-1.2.0.tar.gz"],"sha256":"61338058eb676b466a462ca45d59f436a77a3bd6b816e4268c6d88522b6a4280","cabal-sha256":"df9b213ec18f811cb3137b478d148f3f1680ee43f841cb775835fa282fdb0295"},"version":"1.2.0"}, "mono-traversable": {"dependencies":["base","bytestring","containers","hashable","split","text","transformers","unordered-containers","vector","vector-algorithms"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/mono-traversable-1.0.15.3/mono-traversable-1.0.15.3.tar.gz"},"name":"mono-traversable","pinned":{"url":["https://hackage.haskell.org/package/mono-traversable-1.0.15.3/mono-traversable-1.0.15.3.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/mono-traversable-1.0.15.3.tar.gz"],"sha256":"98b220f3313d74227a4249210c8818e839678343e62b3ebb1b8c867cf2b974b7","cabal-sha256":"059bf3c05cdbef2d06b765333fe41c2168ced2503a23de674e2a59ceb2548c48"},"version":"1.0.15.3"}, "mtl": {"dependencies":[],"location":{"type":"core"},"name":"mtl","version":"2.2.2"}, - "network": {"dependencies":["base","bytestring","deepseq","directory"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/network-3.1.2.9/network-3.1.2.9.tar.gz"},"name":"network","pinned":{"url":["https://hackage.haskell.org/package/network-3.1.2.9/network-3.1.2.9.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/network-3.1.2.9.tar.gz"],"sha256":"0cbf95e4653dbfecc3907e10e7e7bbddb9dd673f172848a0ff3131ab3efdd900","cabal-sha256":"eacdb7f78719cc5125b25856a9114984c5c03b484995f3074b3d756553ededee"},"version":"3.1.2.9"}, + "network": {"dependencies":["base","bytestring","deepseq","directory"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/network-3.1.2.7/network-3.1.2.7.tar.gz"},"name":"network","pinned":{"url":["https://hackage.haskell.org/package/network-3.1.2.7/network-3.1.2.7.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/network-3.1.2.7.tar.gz"],"sha256":"7f7620fef1a1af3d3d6747f510e73223a5c600e7d7fd9ace073d1222bdc63d85","cabal-sha256":"e3d78b13db9512aeb106e44a334ab42b7aa48d26c097299084084cb8be5c5568"},"version":"3.1.2.7"}, "optparse-applicative": {"dependencies":["ansi-wl-pprint","base","process","transformers","transformers-compat"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/optparse-applicative-0.17.0.0/optparse-applicative-0.17.0.0.tar.gz"},"name":"optparse-applicative","pinned":{"url":["https://hackage.haskell.org/package/optparse-applicative-0.17.0.0/optparse-applicative-0.17.0.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/optparse-applicative-0.17.0.0.tar.gz"],"sha256":"825b2e4d3dafe0ba64a073366a88062b3712b81f851793d9ce2327bee70af724","cabal-sha256":"0713e54cbb341e5cae979e2ac441eb3a5ff42e303001f432bd58c19e5638bdda"},"version":"0.17.0.0"}, "parsec": {"dependencies":[],"location":{"type":"core"},"name":"parsec","version":"3.1.15.0"}, "polysemy": {"dependencies":["Cabal","QuickCheck","async","base","cabal-doctest","containers","first-class-families","mtl","stm","syb","template-haskell","th-abstraction","transformers","type-errors","unagi-chan"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/polysemy-1.7.1.0/polysemy-1.7.1.0.tar.gz"},"name":"polysemy","pinned":{"url":["https://hackage.haskell.org/package/polysemy-1.7.1.0/polysemy-1.7.1.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/polysemy-1.7.1.0.tar.gz"],"sha256":"4c9556c0c3f38f5fa655567106ecb53cd357e6ffaf8289753ba6dc26fd4bc224","cabal-sha256":"3ead7a332abd70b202920ed3bf2e36866de163f821e643adfdcc9d39867b8033"},"version":"1.7.1.0"}, "pretty": {"dependencies":[],"location":{"type":"core"},"name":"pretty","version":"1.1.3.6"}, "primitive": {"dependencies":["base","deepseq","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/primitive-0.7.3.0/primitive-0.7.3.0.tar.gz"},"name":"primitive","pinned":{"url":["https://hackage.haskell.org/package/primitive-0.7.3.0/primitive-0.7.3.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/primitive-0.7.3.0.tar.gz"],"sha256":"3c0cfda67f1ee6f7f65108ad6f973b5bbb35ddba34b3c87746a7448f787501dc","cabal-sha256":"ce9361b4d2ed296ef639380411b4cfc217a19e4b3cd4170e03e6fce52daa0176"},"version":"0.7.3.0"}, "process": {"dependencies":[],"location":{"type":"core"},"name":"process","version":"1.6.16.0"}, - "profunctors": {"dependencies":["base","base-orphans","bifunctors","comonad","contravariant","distributive","tagged","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/profunctors-5.6.2/profunctors-5.6.2.tar.gz"},"name":"profunctors","pinned":{"url":["https://hackage.haskell.org/package/profunctors-5.6.2/profunctors-5.6.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/profunctors-5.6.2.tar.gz"],"sha256":"65955d7b50525a4a3bccdab1d982d2ae342897fd38140d5a94b5ef3800d8c92a","cabal-sha256":"e178ba4468982326656626e2089e296f64485e68fdddc9f4476dcd5d612b4f78"},"version":"5.6.2"}, - "proto-lens": {"dependencies":["base","bytestring","containers","deepseq","ghc-prim","lens-family","parsec","pretty","primitive","profunctors","tagged","text","transformers","vector"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/proto-lens-0.7.1.3/proto-lens-0.7.1.3.tar.gz"},"name":"proto-lens","pinned":{"url":["https://hackage.haskell.org/package/proto-lens-0.7.1.3/proto-lens-0.7.1.3.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/proto-lens-0.7.1.3.tar.gz"],"sha256":"aac4317671a31d5f76cb120b5c4f75e644c45b441b4a2b9cfa7015bd8bbae3ac","cabal-sha256":"2d56bf8c37e21d741385e155d0dd327468ab1bc6897d10b0462b7e241d8e61a3"},"version":"0.7.1.3"}, + "profunctors": {"dependencies":["base","base-orphans","bifunctors","comonad","contravariant","distributive","tagged","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/profunctors-5.6.2/profunctors-5.6.2.tar.gz"},"name":"profunctors","pinned":{"url":["https://hackage.haskell.org/package/profunctors-5.6.2/profunctors-5.6.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/profunctors-5.6.2.tar.gz"],"sha256":"65955d7b50525a4a3bccdab1d982d2ae342897fd38140d5a94b5ef3800d8c92a","cabal-sha256":"3d3685119243a7ebf984fa6af03299d156ab7674a432e2e15ecee2a4fd420fb6"},"version":"5.6.2"}, + "proto-lens": {"dependencies":["base","bytestring","containers","deepseq","ghc-prim","lens-family","parsec","pretty","primitive","profunctors","tagged","text","transformers","vector"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/proto-lens-0.7.1.2/proto-lens-0.7.1.2.tar.gz"},"name":"proto-lens","pinned":{"url":["https://hackage.haskell.org/package/proto-lens-0.7.1.2/proto-lens-0.7.1.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/proto-lens-0.7.1.2.tar.gz"],"sha256":"de990265b720dde6a37771a7f36f9a0b07bba39ce14d06d78e855d5bf5e4737d","cabal-sha256":"1d16d73948f4100e1de8374356c3fcfacc63dcc7b8d2130c580f79bdb0139bc5"},"version":"0.7.1.2"}, "proto-lens-protoc": {"dependencies":["base","bytestring","containers","filepath","ghc","ghc-paths","ghc-source-gen","lens-family","pretty","proto-lens","proto-lens-runtime","text"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/proto-lens-protoc-0.7.1.1/proto-lens-protoc-0.7.1.1.tar.gz"},"name":"proto-lens-protoc","pinned":{"url":["https://hackage.haskell.org/package/proto-lens-protoc-0.7.1.1/proto-lens-protoc-0.7.1.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/proto-lens-protoc-0.7.1.1.tar.gz"],"sha256":"0c412b47bce8a3898a61509b9a61c16e00ee947764bd22a07817ecc97a4080f2","cabal-sha256":"4b3b97d5caac9a9f8a85d426d5ad8a129f36e852dd05f42e614d9912030b9700"},"version":"0.7.1.1"}, - "proto-lens-runtime": {"dependencies":["base","bytestring","containers","deepseq","filepath","lens-family","proto-lens","text","vector"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/proto-lens-runtime-0.7.0.4/proto-lens-runtime-0.7.0.4.tar.gz"},"name":"proto-lens-runtime","pinned":{"url":["https://hackage.haskell.org/package/proto-lens-runtime-0.7.0.4/proto-lens-runtime-0.7.0.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/proto-lens-runtime-0.7.0.4.tar.gz"],"sha256":"5749cd01d97fd56bae5698830ba78adcc147e4b65b5e1b4b1cb6f9ee52587f47","cabal-sha256":"1a64cb98b49541e53ea8a19270d7247960445083a2327a091ce0a1cafdef16f3"},"version":"0.7.0.4"}, + "proto-lens-runtime": {"dependencies":["base","bytestring","containers","deepseq","filepath","lens-family","proto-lens","text","vector"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/proto-lens-runtime-0.7.0.3/proto-lens-runtime-0.7.0.3.tar.gz"},"name":"proto-lens-runtime","pinned":{"url":["https://hackage.haskell.org/package/proto-lens-runtime-0.7.0.3/proto-lens-runtime-0.7.0.3.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/proto-lens-runtime-0.7.0.3.tar.gz"],"sha256":"de8cffea5315734ed325f650130aec93ceaf63069a610c0915fbb497592766b9","cabal-sha256":"5165848fa8c112716a4d550dcd8dda8858226294ce3e24462e5b0d9050de9899"},"version":"0.7.0.3"}, "quickcheck-io": {"dependencies":["HUnit","QuickCheck","base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/quickcheck-io-0.2.0/quickcheck-io-0.2.0.tar.gz"},"name":"quickcheck-io","pinned":{"url":["https://hackage.haskell.org/package/quickcheck-io-0.2.0/quickcheck-io-0.2.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/quickcheck-io-0.2.0.tar.gz"],"sha256":"fb779119d79fe08ff4d502fb6869a70c9a8d5fd8ae0959f605c3c937efd96422","cabal-sha256":"7bf0b68fb90873825eb2e5e958c1b76126dcf984debb998e81673e6d837e0b2d"},"version":"0.2.0"}, "random": {"dependencies":["base","bytestring","deepseq","mtl","splitmix"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/random-1.2.1.1/random-1.2.1.1.tar.gz"},"name":"random","pinned":{"url":["https://hackage.haskell.org/package/random-1.2.1.1/random-1.2.1.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/random-1.2.1.1.tar.gz"],"sha256":"3e1272f7ed6a4d7bd1712b90143ec326fee9b225789222379fea20a9c90c9b76","cabal-sha256":"dea1f11e5569332dc6c8efaad1cb301016a5587b6754943a49f9de08ae0e56d9"},"version":"1.2.1.1"}, "resourcet": {"dependencies":["base","containers","exceptions","mtl","primitive","transformers","unliftio-core"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/resourcet-1.2.6/resourcet-1.2.6.tar.gz"},"name":"resourcet","pinned":{"url":["https://hackage.haskell.org/package/resourcet-1.2.6/resourcet-1.2.6.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/resourcet-1.2.6.tar.gz"],"sha256":"f83b35b2106854750ef5f1c34695ea8b7bba6e0572cedf9f2993c5acfdb5fd34","cabal-sha256":"0c55be13d24c1e9c1e6d82327ac039a0bf41469c456e3ae678efa8a9beda3a74"},"version":"1.2.6"}, "safe-exceptions": {"dependencies":["base","deepseq","exceptions","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/safe-exceptions-0.1.7.3/safe-exceptions-0.1.7.3.tar.gz"},"name":"safe-exceptions","pinned":{"url":["https://hackage.haskell.org/package/safe-exceptions-0.1.7.3/safe-exceptions-0.1.7.3.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/safe-exceptions-0.1.7.3.tar.gz"],"sha256":"91ce28d8f8a6efd31788d4827ed5cdcb9a546ad4053a86c56f7947c66a30b5bf","cabal-sha256":"6e9b1b233af80cc0aa17ea858d2641ba146fb11cbcc5970a52649e89d77282e2"},"version":"0.1.7.3"}, - "scientific": {"dependencies":["base","binary","bytestring","containers","deepseq","hashable","integer-logarithms","primitive","template-haskell","text"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/scientific-0.3.7.0/scientific-0.3.7.0.tar.gz"},"name":"scientific","pinned":{"url":["https://hackage.haskell.org/package/scientific-0.3.7.0/scientific-0.3.7.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/scientific-0.3.7.0.tar.gz"],"sha256":"a3a121c4b3d68fb8b9f8c709ab012e48f090ed553609247a805ad070d6b343a9","cabal-sha256":"26d8109106963a345368011081453d25ee1dfa6afae2b1f57b426b4bcd392d91"},"version":"0.3.7.0"}, + "scientific": {"dependencies":["base","binary","bytestring","containers","deepseq","hashable","integer-logarithms","primitive","template-haskell","text"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/scientific-0.3.7.0/scientific-0.3.7.0.tar.gz"},"name":"scientific","pinned":{"url":["https://hackage.haskell.org/package/scientific-0.3.7.0/scientific-0.3.7.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/scientific-0.3.7.0.tar.gz"],"sha256":"a3a121c4b3d68fb8b9f8c709ab012e48f090ed553609247a805ad070d6b343a9","cabal-sha256":"517444c944dad9db8235d7b311d7b9a0839a519ee3178288b5a9606256e0c7d8"},"version":"0.3.7.0"}, "setenv": {"dependencies":["base","unix"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/setenv-0.1.1.3/setenv-0.1.1.3.tar.gz"},"name":"setenv","pinned":{"url":["https://hackage.haskell.org/package/setenv-0.1.1.3/setenv-0.1.1.3.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/setenv-0.1.1.3.tar.gz"],"sha256":"e358df39afc03d5a39e2ec650652d845c85c80cc98fe331654deafb4767ecb32","cabal-sha256":"c5916ac0d2a828473cd171261328a290afe0abd799db1ac8c310682fe778c45b"},"version":"0.1.1.3"}, "split": {"dependencies":["base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/split-0.2.3.5/split-0.2.3.5.tar.gz"},"name":"split","pinned":{"url":["https://hackage.haskell.org/package/split-0.2.3.5/split-0.2.3.5.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/split-0.2.3.5.tar.gz"],"sha256":"bf8aa8d610354a2b576946a6c838251ec5988c8374100638e6b2604513b93159","cabal-sha256":"f472fa7019647cacac3267742a6f7ac0a5c816f9890e80e4b826cd937436de87"},"version":"0.2.3.5"}, "splitmix": {"dependencies":["base","deepseq"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/splitmix-0.1.0.4/splitmix-0.1.0.4.tar.gz"},"name":"splitmix","pinned":{"url":["https://hackage.haskell.org/package/splitmix-0.1.0.4/splitmix-0.1.0.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/splitmix-0.1.0.4.tar.gz"],"sha256":"6d065402394e7a9117093dbb4530a21342c9b1e2ec509516c8a8d0ffed98ecaa","cabal-sha256":"db25c2e17967aa6b6046ab8b1b96ba3f344ca59a62b60fb6113d51ea305a3d8e"},"version":"0.1.0.4"}, "stm": {"dependencies":[],"location":{"type":"core"},"name":"stm","version":"2.5.0.2"}, "streaming": {"dependencies":["base","containers","ghc-prim","mmorph","mtl","transformers","transformers-base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/streaming-0.2.3.1/streaming-0.2.3.1.tar.gz"},"name":"streaming","pinned":{"url":["https://hackage.haskell.org/package/streaming-0.2.3.1/streaming-0.2.3.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/streaming-0.2.3.1.tar.gz"],"sha256":"fc5efae393750b9729ce5c5e979edcd3b9a5bf41ab927636174b01f999ffea88","cabal-sha256":"9dd39bfa8befa6956372722187b225d489b50b633ab56d7f411bf302b79e46cd"},"version":"0.2.3.1"}, - "streaming-commons": {"dependencies":["array","async","base","bytestring","directory","network","process","random","stm","text","transformers","unix","zlib"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/streaming-commons-0.2.2.6/streaming-commons-0.2.2.6.tar.gz"},"name":"streaming-commons","pinned":{"url":["https://hackage.haskell.org/package/streaming-commons-0.2.2.6/streaming-commons-0.2.2.6.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/streaming-commons-0.2.2.6.tar.gz"],"sha256":"0180958a882eb0f6262b812fe886c2b1b8285474b5b958f814ae4f05409fbf79","cabal-sha256":"f3a6db1e6c12760c00a38393693d473b8b4f9211eed036388eca89996ba50d66"},"version":"0.2.2.6"}, - "syb": {"dependencies":["base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/syb-0.7.2.3/syb-0.7.2.3.tar.gz"},"name":"syb","pinned":{"url":["https://hackage.haskell.org/package/syb-0.7.2.3/syb-0.7.2.3.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/syb-0.7.2.3.tar.gz"],"sha256":"d0b72daf16a947c4d9cb2d5774072f2153433224a04fd60fad60be9ffac8d91a","cabal-sha256":"d71f6747016466b0766491eae36be842ba98ba25e2aec26eaedbeea965c0586a"},"version":"0.7.2.3"}, + "streaming-commons": {"dependencies":["array","async","base","bytestring","directory","network","process","random","stm","text","transformers","unix","zlib"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/streaming-commons-0.2.2.5/streaming-commons-0.2.2.5.tar.gz"},"name":"streaming-commons","pinned":{"url":["https://hackage.haskell.org/package/streaming-commons-0.2.2.5/streaming-commons-0.2.2.5.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/streaming-commons-0.2.2.5.tar.gz"],"sha256":"ca50819bdb2b248ced790e9faab07a3a5369ef702d9f9a932f26438bbeeca704","cabal-sha256":"34959abee70e63d370b5a4bee0bc3483c66d1e53906fb5e13844ae8b9a62a4a3"},"version":"0.2.2.5"}, + "syb": {"dependencies":["base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/syb-0.7.2.2/syb-0.7.2.2.tar.gz"},"name":"syb","pinned":{"url":["https://hackage.haskell.org/package/syb-0.7.2.2/syb-0.7.2.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/syb-0.7.2.2.tar.gz"],"sha256":"8143c6983b6248d57f00e47ec3cd16541acbaa55eb8093fedd5b7cee9a95b2e3","cabal-sha256":"bc800dbd35a17b652082f7f9790fd20d196ea0f44daaa7d5ac46491d8ecc7347"},"version":"0.7.2.2"}, "tagged": {"dependencies":["base","deepseq","template-haskell","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/tagged-0.8.6.1/tagged-0.8.6.1.tar.gz"},"name":"tagged","pinned":{"url":["https://hackage.haskell.org/package/tagged-0.8.6.1/tagged-0.8.6.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/tagged-0.8.6.1.tar.gz"],"sha256":"f5e0fcf95f0bb4aa63f428f2c01955a41ea1a42cfcf39145ed631f59a9616c02","cabal-sha256":"8a24aef29b8e35447ccc56658ea07c2aded30bfa8130ea057e382936e17c74a6"},"version":"0.8.6.1"}, "template-haskell": {"dependencies":[],"location":{"type":"core"},"name":"template-haskell","version":"2.18.0.0"}, "temporary": {"dependencies":["base","directory","exceptions","filepath","random","transformers","unix"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/temporary-1.3/temporary-1.3.tar.gz"},"name":"temporary","pinned":{"url":["https://hackage.haskell.org/package/temporary-1.3/temporary-1.3.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/temporary-1.3.tar.gz"],"sha256":"8c442993694b5ffca823ce864af95bd2841fb5264ee511c61cf48cc71d879890","cabal-sha256":"3a66c136f700dbf42f3c5000ca93e80b26dead51e54322c83272b236c1ec8ef1"},"version":"1.3"}, "text": {"dependencies":[],"location":{"type":"core"},"name":"text","version":"1.2.5.0"}, - "text-show": {"dependencies":["array","base","base-compat-batteries","bifunctors","bytestring","bytestring-builder","containers","generic-deriving","ghc-boot-th","ghc-prim","template-haskell","text","th-abstraction","th-lift","transformers","transformers-compat"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/text-show-3.10.2/text-show-3.10.2.tar.gz"},"name":"text-show","pinned":{"url":["https://hackage.haskell.org/package/text-show-3.10.2/text-show-3.10.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/text-show-3.10.2.tar.gz"],"sha256":"9c34afafb6eaed63b08754045eed157430690b83135e019a72428c518ef37703","cabal-sha256":"5f6107d41b36a1780b4942f8fda23524227fef35df7b4882d87c0ecade6992e9"},"version":"3.10.2"}, + "text-show": {"dependencies":["array","base","base-compat-batteries","bifunctors","bytestring","bytestring-builder","containers","generic-deriving","ghc-boot-th","ghc-prim","template-haskell","text","th-abstraction","th-lift","transformers","transformers-compat"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/text-show-3.10/text-show-3.10.tar.gz"},"name":"text-show","pinned":{"url":["https://hackage.haskell.org/package/text-show-3.10/text-show-3.10.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/text-show-3.10.tar.gz"],"sha256":"cebbcab5235728d845f36d23364e66941b3d95e68b682d0ce388a5e22f2502c7","cabal-sha256":"eeaa34802b668cae6fc38c1f52e6f78d482c73f527967ac2bfa2d3f0af60c424"},"version":"3.10"}, "tf-random": {"dependencies":["base","primitive","random","time"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/tf-random-0.5/tf-random-0.5.tar.gz"},"name":"tf-random","pinned":{"url":["https://hackage.haskell.org/package/tf-random-0.5/tf-random-0.5.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/tf-random-0.5.tar.gz"],"sha256":"2e30cec027b313c9e1794d326635d8fc5f79b6bf6e7580ab4b00186dadc88510","cabal-sha256":"14012837d0f0e18fdbbe3d56e67da8622ee5e20b180abce952dd50bd9f36b326"},"version":"0.5"}, - "th-abstraction": {"dependencies":["base","containers","ghc-prim","template-haskell"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/th-abstraction-0.4.5.0/th-abstraction-0.4.5.0.tar.gz"},"name":"th-abstraction","pinned":{"url":["https://hackage.haskell.org/package/th-abstraction-0.4.5.0/th-abstraction-0.4.5.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/th-abstraction-0.4.5.0.tar.gz"],"sha256":"00d5e24f247e328bd9898d5af5915c1e86b134b4d40baa680258635f95031526","cabal-sha256":"c28f186ae9817a059e54f63689f8985194b7f58d8fbd79e157d12374b6f9d2c3"},"version":"0.4.5.0"}, - "th-compat": {"dependencies":["base","directory","filepath","template-haskell"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/th-compat-0.1.4/th-compat-0.1.4.tar.gz"},"name":"th-compat","pinned":{"url":["https://hackage.haskell.org/package/th-compat-0.1.4/th-compat-0.1.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/th-compat-0.1.4.tar.gz"],"sha256":"d8f97ac14ab47b6b8a7b0fdb4ff95426322ec56badd01652ac15da4a44d4bab8","cabal-sha256":"e5ae7c083ef3a22248558f8451669bb1c55ea8090f5908b86b9033743c161730"},"version":"0.1.4"}, - "th-lift": {"dependencies":["base","ghc-prim","template-haskell","th-abstraction"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/th-lift-0.8.3/th-lift-0.8.3.tar.gz"},"name":"th-lift","pinned":{"url":["https://hackage.haskell.org/package/th-lift-0.8.3/th-lift-0.8.3.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/th-lift-0.8.3.tar.gz"],"sha256":"25d57bf5f8e7deefeb4ace0539805ae1e90b1ba5a034ebcc36141846408c6b75","cabal-sha256":"3043e803a08c22676dcf71a4021d0fa276fcecc2ac3dbc4b230fee0b994ca7e9"},"version":"0.8.3"}, + "th-abstraction": {"dependencies":["base","containers","ghc-prim","template-haskell"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/th-abstraction-0.4.5.0/th-abstraction-0.4.5.0.tar.gz"},"name":"th-abstraction","pinned":{"url":["https://hackage.haskell.org/package/th-abstraction-0.4.5.0/th-abstraction-0.4.5.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/th-abstraction-0.4.5.0.tar.gz"],"sha256":"00d5e24f247e328bd9898d5af5915c1e86b134b4d40baa680258635f95031526","cabal-sha256":"313f8b3c65781310df66ba86518bcf7662b1b419b601afaf72bb977c255fe6e9"},"version":"0.4.5.0"}, + "th-compat": {"dependencies":["base","directory","filepath","template-haskell"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/th-compat-0.1.4/th-compat-0.1.4.tar.gz"},"name":"th-compat","pinned":{"url":["https://hackage.haskell.org/package/th-compat-0.1.4/th-compat-0.1.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/th-compat-0.1.4.tar.gz"],"sha256":"d8f97ac14ab47b6b8a7b0fdb4ff95426322ec56badd01652ac15da4a44d4bab8","cabal-sha256":"6ca77c4e80b4e4109e30549c269631a9cc295c8fc2431ce4123972a5f80f7bfc"},"version":"0.1.4"}, + "th-lift": {"dependencies":["base","ghc-prim","template-haskell","th-abstraction"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/th-lift-0.8.2/th-lift-0.8.2.tar.gz"},"name":"th-lift","pinned":{"url":["https://hackage.haskell.org/package/th-lift-0.8.2/th-lift-0.8.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/th-lift-0.8.2.tar.gz"],"sha256":"3a5927037a10ae63e605c02228c4027c32b7bab1985ae7b5379e6363b3cd5ce4","cabal-sha256":"f135f67b018c22889e68b094773273dcf8f9e16fcfa330bf4778f84fce8925e9"},"version":"0.8.2"}, "time": {"dependencies":[],"location":{"type":"core"},"name":"time","version":"1.11.1.1"}, "transformers": {"dependencies":[],"location":{"type":"core"},"name":"transformers","version":"0.5.6.2"}, "transformers-base": {"dependencies":["base","base-orphans","stm","transformers","transformers-compat"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/transformers-base-0.4.6/transformers-base-0.4.6.tar.gz"},"name":"transformers-base","pinned":{"url":["https://hackage.haskell.org/package/transformers-base-0.4.6/transformers-base-0.4.6.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/transformers-base-0.4.6.tar.gz"],"sha256":"323bf8689eb691b122661cffa41a25e00fea7a768433fe2dde35d3da7d32cf90","cabal-sha256":"6f18f320e371c8954c4b6b211e2fdd5d15a6d6310bd605b9d640f47ede408961"},"version":"0.4.6"}, "transformers-compat": {"dependencies":["base","ghc-prim","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/transformers-compat-0.7.2/transformers-compat-0.7.2.tar.gz"},"name":"transformers-compat","pinned":{"url":["https://hackage.haskell.org/package/transformers-compat-0.7.2/transformers-compat-0.7.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/transformers-compat-0.7.2.tar.gz"],"sha256":"b62c7304c9f3cbc9463d0739aa85cb9489f217ea092b9d625d417514fbcc9d6a","cabal-sha256":"044fb9955f63ee138fcebedfdcbe54afe741f2d5892a2d0bdf3a8052bd342643"},"version":"0.7.2"}, - "type-errors": {"dependencies":["base","first-class-families","syb","template-haskell","th-abstraction"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/type-errors-0.2.0.2/type-errors-0.2.0.2.tar.gz"},"name":"type-errors","pinned":{"url":["https://hackage.haskell.org/package/type-errors-0.2.0.2/type-errors-0.2.0.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/type-errors-0.2.0.2.tar.gz"],"sha256":"697cffdd1ec573d6b8d1539976673f93bb562ee97b644077e2305bfefc897c83","cabal-sha256":"afd6b33bb582730a90ea58fd23d5b32a38b5b6c8b2f18e3250936bdc0487dfab"},"version":"0.2.0.2"}, - "typed-process": {"dependencies":["async","base","bytestring","process","stm","transformers","unliftio-core"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/typed-process-0.2.11.0/typed-process-0.2.11.0.tar.gz"},"name":"typed-process","pinned":{"url":["https://hackage.haskell.org/package/typed-process-0.2.11.0/typed-process-0.2.11.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/typed-process-0.2.11.0.tar.gz"],"sha256":"948c59540675d85f35c99e285cdb8686713ec1689f530d5d21813239ea91f625","cabal-sha256":"defde2c4dcd07750381d6e15ee7a517938c8d6353abcf27bba9f290e75a67d39"},"version":"0.2.11.0"}, + "type-errors": {"dependencies":["base","first-class-families","syb","template-haskell","th-abstraction"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/type-errors-0.2.0.1/type-errors-0.2.0.1.tar.gz"},"name":"type-errors","pinned":{"url":["https://hackage.haskell.org/package/type-errors-0.2.0.1/type-errors-0.2.0.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/type-errors-0.2.0.1.tar.gz"],"sha256":"d537369e6bef4d7656d5de45e5ebb6687fe3e3666e21abdb78a23d295ff14137","cabal-sha256":"c47af01304199c6440566c0a2c9a434db7ae8027dd4701dc2e374fc341ab40b1"},"version":"0.2.0.1"}, + "typed-process": {"dependencies":["async","base","bytestring","process","stm","transformers","unliftio-core"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/typed-process-0.2.10.1/typed-process-0.2.10.1.tar.gz"},"name":"typed-process","pinned":{"url":["https://hackage.haskell.org/package/typed-process-0.2.10.1/typed-process-0.2.10.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/typed-process-0.2.10.1.tar.gz"],"sha256":"e436875ccd6664d4111e601c8e2ec6ba9473979eac49b23a1bdb88f80e95099e","cabal-sha256":"cc35b76f2ce32c708cb2f68a1c4f661a8138196d958e34a2f214208333a73f46"},"version":"0.2.10.1"}, "unagi-chan": {"dependencies":["atomic-primops","base","ghc-prim","primitive"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/unagi-chan-0.4.1.4/unagi-chan-0.4.1.4.tar.gz"},"name":"unagi-chan","pinned":{"url":["https://hackage.haskell.org/package/unagi-chan-0.4.1.4/unagi-chan-0.4.1.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/unagi-chan-0.4.1.4.tar.gz"],"sha256":"d9d6f4ab07def8e84a942bb23791830a61faf89166cb7185a3b2f97cb45128b5","cabal-sha256":"e9a282689a65fc66260557222789d14dcb7d299be0ab2d4e8e414b0d9f2ef459"},"version":"0.4.1.4"}, "unix": {"dependencies":[],"location":{"type":"core"},"name":"unix","version":"2.7.2.2"}, - "unliftio-core": {"dependencies":["base","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/unliftio-core-0.2.1.0/unliftio-core-0.2.1.0.tar.gz"},"name":"unliftio-core","pinned":{"url":["https://hackage.haskell.org/package/unliftio-core-0.2.1.0/unliftio-core-0.2.1.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/unliftio-core-0.2.1.0.tar.gz"],"sha256":"99384cba8d56d9d61b85e38a313a93ebcdb78be6566367f0930ef580597fe3e3","cabal-sha256":"cb78a95718f9cb2579a8a1208d4a148ea358f0774321c8cb905bfb0b96a2813c"},"version":"0.2.1.0"}, - "unordered-containers": {"dependencies":["base","deepseq","hashable","template-haskell"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/unordered-containers-0.2.19.1/unordered-containers-0.2.19.1.tar.gz"},"name":"unordered-containers","pinned":{"url":["https://hackage.haskell.org/package/unordered-containers-0.2.19.1/unordered-containers-0.2.19.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/unordered-containers-0.2.19.1.tar.gz"],"sha256":"1b27bec5e0d522b27a6029ebf4c4a6d40acbc083c787008e32fb55c4b1d128d2","cabal-sha256":"9ad8972c2e913c37b1d4f0e1261517fd7a1b8c8a58077e057be69837e3dbaa00"},"version":"0.2.19.1"}, - "vector": {"dependencies":["base","deepseq","ghc-prim","primitive"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/vector-0.12.3.1/vector-0.12.3.1.tar.gz"},"name":"vector","pinned":{"url":["https://hackage.haskell.org/package/vector-0.12.3.1/vector-0.12.3.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/vector-0.12.3.1.tar.gz"],"sha256":"fb4a53c02bd4d7fdf155c0604da9a5bb0f3b3bfce5d9960aea11c2ae235b9f35","cabal-sha256":"39141f312871b7c793a63be76635999e84d442aa3290aec59f30638ec0bf23a7"},"version":"0.12.3.1"}, + "unliftio-core": {"dependencies":["base","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/unliftio-core-0.2.0.1/unliftio-core-0.2.0.1.tar.gz"},"name":"unliftio-core","pinned":{"url":["https://hackage.haskell.org/package/unliftio-core-0.2.0.1/unliftio-core-0.2.0.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/unliftio-core-0.2.0.1.tar.gz"],"sha256":"919f0d1297ea2f5373118553c1df2a9405d8b9e31a8307e829da67d4953c299a","cabal-sha256":"f9abcdd3f3d28e4840563efb7b8760d2de9b5707bcd6f53a87f6a0d77bb5a9f7"},"version":"0.2.0.1"}, + "unordered-containers": {"dependencies":["base","deepseq","hashable","template-haskell"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/unordered-containers-0.2.19.1/unordered-containers-0.2.19.1.tar.gz"},"name":"unordered-containers","pinned":{"url":["https://hackage.haskell.org/package/unordered-containers-0.2.19.1/unordered-containers-0.2.19.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/unordered-containers-0.2.19.1.tar.gz"],"sha256":"1b27bec5e0d522b27a6029ebf4c4a6d40acbc083c787008e32fb55c4b1d128d2","cabal-sha256":"db11042bb0356c0adea277d0794743829125b4c99455af6af2bd5f7bd5e88a39"},"version":"0.2.19.1"}, + "vector": {"dependencies":["base","deepseq","ghc-prim","primitive"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/vector-0.12.3.1/vector-0.12.3.1.tar.gz"},"name":"vector","pinned":{"url":["https://hackage.haskell.org/package/vector-0.12.3.1/vector-0.12.3.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/vector-0.12.3.1.tar.gz"],"sha256":"fb4a53c02bd4d7fdf155c0604da9a5bb0f3b3bfce5d9960aea11c2ae235b9f35","cabal-sha256":"fffbd00912d69ed7be9bc7eeb09f4f475e0d243ec43f916a9fd5bbd219ce7f3e"},"version":"0.12.3.1"}, "vector-algorithms": {"dependencies":["base","bytestring","primitive","vector"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/vector-algorithms-0.8.0.4/vector-algorithms-0.8.0.4.tar.gz"},"name":"vector-algorithms","pinned":{"url":["https://hackage.haskell.org/package/vector-algorithms-0.8.0.4/vector-algorithms-0.8.0.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/vector-algorithms-0.8.0.4.tar.gz"],"sha256":"76176a56778bf30a275b1089ee6db24ec6c67d92525145f8dfe215b80137af3b","cabal-sha256":"e0656aa47388e5c80e4f5d4fd87c80fb8d473fdd41533ff7af5cbb292056a544"},"version":"0.8.0.4"}, "void": {"dependencies":["base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/void-0.7.3/void-0.7.3.tar.gz"},"name":"void","pinned":{"url":["https://hackage.haskell.org/package/void-0.7.3/void-0.7.3.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/void-0.7.3.tar.gz"],"sha256":"53af758ddc37dc63981671e503438d02c6f64a2d8744e9bec557a894431f7317","cabal-sha256":"13d30f62fcdf065e595d679d4ac8b4b0c1bb1a1b73db7b5b5a8f857cb5c8a546"},"version":"0.7.3"}, - "zlib": {"dependencies":["base","bytestring"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/zlib-0.6.3.0/zlib-0.6.3.0.tar.gz"},"name":"zlib","pinned":{"url":["https://hackage.haskell.org/package/zlib-0.6.3.0/zlib-0.6.3.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/zlib-0.6.3.0.tar.gz"],"sha256":"9eaa989ad4534438b5beb51c1d3a4c8f6a088fdff0b259a5394fbf39aaee04da","cabal-sha256":"9adce39e4ca0b7a87d45df0a243134816c57059a08e28cff5469c98ae1f54dfc"},"version":"0.6.3.0"} + "zlib": {"dependencies":["base","bytestring"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/zlib-0.6.3.0/zlib-0.6.3.0.tar.gz"},"name":"zlib","pinned":{"url":["https://hackage.haskell.org/package/zlib-0.6.3.0/zlib-0.6.3.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/zlib-0.6.3.0.tar.gz"],"sha256":"9eaa989ad4534438b5beb51c1d3a4c8f6a088fdff0b259a5394fbf39aaee04da","cabal-sha256":"8214a9d37580f17f8b675109578a5dbe6853559eef156e34dc2233f1123ace33"},"version":"0.6.3.0"} } } \ No newline at end of file diff --git a/stackage_snapshot.yaml b/stackage_snapshot.yaml index edb203776..6d6d2f8d5 100644 --- a/stackage_snapshot.yaml +++ b/stackage_snapshot.yaml @@ -5,11 +5,17 @@ # but with versions <= 2.13.2.0 we encounter the following issue: # https://github.com/haskell/win32/issues/193 -resolver: lts-20.21 +resolver: lts-20.3 drop-packages: - Win32 +packages: +- git: https://github.com/tweag/cabal + commit: 42f04c3f639f10dc3c7981a0c663bfe08ad833cb + subdirs: + - Cabal + # stackage lts-20.3/ghc 9.2.5 only contain Win32-2.12.0.1 flags: ansi-terminal: From b3e924478ccb220c71fb306ec9b884aee9b72ca8 Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Thu, 15 Jun 2023 09:34:08 +0200 Subject: [PATCH 20/41] Add missing install.mk.in --- haskell/toolchain.bzl | 1 + 1 file changed, 1 insertion(+) diff --git a/haskell/toolchain.bzl b/haskell/toolchain.bzl index b832ac68f..c89ce3b13 100644 --- a/haskell/toolchain.bzl +++ b/haskell/toolchain.bzl @@ -610,6 +610,7 @@ def haskell_toolchain( "config.sub", "install-sh", "mk/config.mk.in", + "mk/install.mk.in", "mk/project.mk", #"mk/system-cxx-std-lib-1.0.conf.in", ], From 73cf49cf41d041db1c699283c3dae9a91f05b036 Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Thu, 15 Jun 2023 10:05:33 +0200 Subject: [PATCH 21/41] Fix docdir --- haskell/ghc_bindist_hadrian.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/haskell/ghc_bindist_hadrian.bzl b/haskell/ghc_bindist_hadrian.bzl index 54c3690b7..8a8b099d6 100644 --- a/haskell/ghc_bindist_hadrian.bzl +++ b/haskell/ghc_bindist_hadrian.bzl @@ -71,7 +71,7 @@ def _ghc_bindist_hadrian_impl(ctx): bindir = "bin" libdir = "lib" - docdir = "doc" + docdir = "docs" # is "doc" for more recent GHC # The bindist requires patching invalid haddock paths. See Makefile of GHC: # https://gitlab.haskell.org/ghc/ghc/-/blob/ghc-9.2.3-release/hadrian/bindist/Makefile#L54-74 From 8808d51a591e7e267bcac49a43c72d94f58add40 Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Thu, 15 Jun 2023 10:06:46 +0200 Subject: [PATCH 22/41] Only build ubuntu bindists for the time being --- .github/workflows/workflow.yaml | 102 +------------------------------- 1 file changed, 1 insertion(+), 101 deletions(-) diff --git a/.github/workflows/workflow.yaml b/.github/workflows/workflow.yaml index 0b7369167..8725c0244 100644 --- a/.github/workflows/workflow.yaml +++ b/.github/workflows/workflow.yaml @@ -10,106 +10,6 @@ env: cache-version: 0 jobs: - test-nixpkgs: - name: Build & Test - Nixpkgs - concurrency: - group: ${{ github.workflow }}-${{ github.ref }}-${{ matrix.os }}-${{ matrix.module }}-${{ matrix.bzlmod }}-${{ matrix.ghc }}-nixpkgs - cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, macos-11] - module: [rules_haskell, rules_haskell_nix, rules_haskell_tests] - bzlmod: [true, false] - ghc: - - 9.2.5 - - 9.4.5 - exclude: - - module: rules_haskell_nix - bzlmod: false - # TODO: in a MODULE.bazel file we declare version specific dependencies, would need to use stack snapshot json - # and stack config per GHC version - - ghc: 9.4.5 - bzlmod: true - runs-on: ${{ matrix.os }} - steps: - - if: ${{ matrix.os == 'ubuntu-latest' }} - run: |- - sudo swapoff -a - sudo rm -rf /swapfile /usr/share/dotnet /usr/local/lib/android /opt/ghc - docker rmi $(docker images -q) -f - - uses: actions/checkout@v4 - - name: Mount Bazel cache - uses: actions/cache@v3 - with: - path: ~/repo-cache - key: repo-cache-${{ runner.os }}-nixpkgs-${{ env.cache-version }} - - uses: cachix/install-nix-action@v23 - with: - nix_path: nixpkgs=./nixpkgs/default.nix - extra_nix_config: | - trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= - extra-substituters = https://cache.iog.io - - name: Configure - env: - BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }} - run: | - # Avoid failures of the form `deadline exceeded after 14999958197ns DEADLINE_EXCEEDED`. - # See https://github.com/tweag/rules_haskell/issues/1498 and https://github.com/tweag/rules_haskell/pull/1692. - [[ ${{ runner.os }} == Linux ]] && sudo sysctl -w net.ipv4.tcp_keepalive_time=60 - case ${{ runner.os }} in - macOS) BUILD_CONFIG=ci-macos-nixpkgs;; - Linux) BUILD_CONFIG=ci-linux-nixpkgs;; - esac - if [ -z "$BUILDBUDDY_API_KEY" ]; then - cache_setting='--noremote_upload_local_results' - else - cache_setting="--remote_header=x-buildbuddy-api-key=$BUILDBUDDY_API_KEY" - fi - cat >.bazelrc.local <~/.netrc < Date: Thu, 15 Jun 2023 13:39:35 +0200 Subject: [PATCH 23/41] Revert "Fix more things" This reverts commit 5b0856c6f53d2f5f88a0e20d62a901b4aad1a4c7. --- rules_haskell_tests/stackage-pinning-test.yaml | 4 ++++ .../stackage-pinning-test_snapshot.json | 11 ++++++++--- .../tests/haskell_module/plugin/Plugin.hs | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/rules_haskell_tests/stackage-pinning-test.yaml b/rules_haskell_tests/stackage-pinning-test.yaml index 93d167084..fa25d62b3 100644 --- a/rules_haskell_tests/stackage-pinning-test.yaml +++ b/rules_haskell_tests/stackage-pinning-test.yaml @@ -12,6 +12,10 @@ packages: - archive: https://github.com/tweag/rules_haskell/raw/e4e74f17f743488f564bd0d69c580106d5b910a5/tests/haskell_cabal_library_sublibrary_name/package1.tar sha256: "302d8ddda8330c825da61fe0a2315c899ab083e641c7716ebdacb5c951682445" + - git: https://github.com/tweag/cabal + commit: 42f04c3f639f10dc3c7981a0c663bfe08ad833cb + subdirs: + - Cabal # We drop the Win32 package from the stack snapshot so that stack considers it a toolchain library. # In this case we will use the Win32 provided by the compiler instead of recompiling it. diff --git a/rules_haskell_tests/stackage-pinning-test_snapshot.json b/rules_haskell_tests/stackage-pinning-test_snapshot.json index e386e1621..8735dda6e 100644 --- a/rules_haskell_tests/stackage-pinning-test_snapshot.json +++ b/rules_haskell_tests/stackage-pinning-test_snapshot.json @@ -1,13 +1,14 @@ { - "__GENERATED_FILE_DO_NOT_MODIFY_MANUALLY": -368711695, - "all-cabal-hashes": "https://raw.githubusercontent.com/commercialhaskell/all-cabal-hashes/5b84231c0605b5e0aeec7fc0f15b3463dd699dec", + "__GENERATED_FILE_DO_NOT_MODIFY_MANUALLY": 1765141068, + "all-cabal-hashes": "https://raw.githubusercontent.com/commercialhaskell/all-cabal-hashes/769ec969c5a81cde769b20e49e11f42ce7841932", "resolved": { - "Cabal": {"dependencies":[],"location":{"type":"core"},"name":"Cabal","version":"3.6.3.0"}, + "Cabal": {"dependencies":["array","base","binary","bytestring","containers","deepseq","directory","filepath","mtl","parsec","pretty","process","text","time","transformers","unix"],"location":{"type":"git","url":"https://github.com/tweag/cabal","commit":"42f04c3f639f10dc3c7981a0c663bfe08ad833cb","subdir":"Cabal"},"name":"Cabal","version":"3.6.3.0"}, "HUnit": {"dependencies":["base","call-stack","deepseq"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/HUnit-1.6.2.0/HUnit-1.6.2.0.tar.gz"},"name":"HUnit","pinned":{"url":["https://hackage.haskell.org/package/HUnit-1.6.2.0/HUnit-1.6.2.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/HUnit-1.6.2.0.tar.gz"],"sha256":"b0b7538871ffc058486fc00740886d2f3172f8fa6869936bfe83a5e10bd744ab","cabal-sha256":"1a79174e8af616117ad39464cac9de205ca923da6582825e97c10786fda933a4"},"version":"1.6.2.0"}, "QuickCheck": {"dependencies":["base","containers","deepseq","random","splitmix","template-haskell","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/QuickCheck-2.14.2/QuickCheck-2.14.2.tar.gz"},"name":"QuickCheck","pinned":{"url":["https://hackage.haskell.org/package/QuickCheck-2.14.2/QuickCheck-2.14.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/QuickCheck-2.14.2.tar.gz"],"sha256":"d87b6c85696b601175274361fa62217894401e401e150c3c5d4013ac53cd36f3","cabal-sha256":"4ce29211223d5e6620ebceba34a3ca9ccf1c10c0cf387d48aea45599222ee5aa"},"version":"2.14.2"}, "ansi-terminal": {"dependencies":["base","colour"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/ansi-terminal-0.11.4/ansi-terminal-0.11.4.tar.gz"},"name":"ansi-terminal","pinned":{"url":["https://hackage.haskell.org/package/ansi-terminal-0.11.4/ansi-terminal-0.11.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/ansi-terminal-0.11.4.tar.gz"],"sha256":"7898e48f0a535c1857cde52c803f28096ba89759461fe4d157fd55dcdb420e25","cabal-sha256":"410737137c798e23339a08435a5511785ebf1db08700e37debbd7801cf73fc82"},"version":"0.11.4"}, "array": {"dependencies":[],"location":{"type":"core"},"name":"array","version":"0.5.4.0"}, "base": {"dependencies":[],"location":{"type":"core"},"name":"base","version":"4.16.4.0"}, + "binary": {"dependencies":[],"location":{"type":"core"},"name":"binary","version":"0.8.9.0"}, "bytestring": {"dependencies":[],"location":{"type":"core"},"name":"bytestring","version":"0.11.3.1"}, "call-stack": {"dependencies":["base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/call-stack-0.4.0/call-stack-0.4.0.tar.gz"},"name":"call-stack","pinned":{"url":["https://hackage.haskell.org/package/call-stack-0.4.0/call-stack-0.4.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/call-stack-0.4.0.tar.gz"],"sha256":"430bcf8a3404f7e55319573c0b807b1356946f0c8f289bb3d9afb279c636b87b","cabal-sha256":"ac44d2c00931dc20b01750da8c92ec443eb63a7231e8550188cb2ac2385f7feb"},"version":"0.4.0"}, "clock": {"dependencies":["base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/clock-0.8.3/clock-0.8.3.tar.gz"},"name":"clock","pinned":{"url":["https://hackage.haskell.org/package/clock-0.8.3/clock-0.8.3.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/clock-0.8.3.tar.gz"],"sha256":"845ce5db4c98cefd517323e005f87effceff886987305e421c4ef616dc0505d1","cabal-sha256":"a692159828c2cd278eaec317b3a7e9fb6d7b787c8a19f086004d15d9fa1fd72c"},"version":"0.8.3"}, @@ -22,13 +23,17 @@ "hspec-expectations": {"dependencies":["HUnit","base","call-stack"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/hspec-expectations-0.8.2/hspec-expectations-0.8.2.tar.gz"},"name":"hspec-expectations","pinned":{"url":["https://hackage.haskell.org/package/hspec-expectations-0.8.2/hspec-expectations-0.8.2.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/hspec-expectations-0.8.2.tar.gz"],"sha256":"819607ea1faf35ce5be34be61c6f50f3389ea43892d56fb28c57a9f5d54fb4ef","cabal-sha256":"e2db24881baadc2d9d23b03cb629e80dcbda89a6b04ace9adb5f4d02ef8b31aa"},"version":"0.8.2"}, "mtl": {"dependencies":[],"location":{"type":"core"},"name":"mtl","version":"2.2.2"}, "package1": {"dependencies":["Cabal","base"],"location":{"type":"archive","url":"https://github.com/tweag/rules_haskell/raw/e4e74f17f743488f564bd0d69c580106d5b910a5/tests/haskell_cabal_library_sublibrary_name/package1.tar"},"name":"package1","pinned":{"sha256":"302d8ddda8330c825da61fe0a2315c899ab083e641c7716ebdacb5c951682445","strip-prefix":""},"version":"0.1.0.0"}, + "parsec": {"dependencies":[],"location":{"type":"core"},"name":"parsec","version":"3.1.15.0"}, + "pretty": {"dependencies":[],"location":{"type":"core"},"name":"pretty","version":"1.1.3.6"}, "primitive": {"dependencies":["base","deepseq","transformers"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/primitive-0.7.3.0/primitive-0.7.3.0.tar.gz"},"name":"primitive","pinned":{"url":["https://hackage.haskell.org/package/primitive-0.7.3.0/primitive-0.7.3.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/primitive-0.7.3.0.tar.gz"],"sha256":"3c0cfda67f1ee6f7f65108ad6f973b5bbb35ddba34b3c87746a7448f787501dc","cabal-sha256":"ce9361b4d2ed296ef639380411b4cfc217a19e4b3cd4170e03e6fce52daa0176"},"version":"0.7.3.0"}, + "process": {"dependencies":[],"location":{"type":"core"},"name":"process","version":"1.6.16.0"}, "quickcheck-io": {"dependencies":["HUnit","QuickCheck","base"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/quickcheck-io-0.2.0/quickcheck-io-0.2.0.tar.gz"},"name":"quickcheck-io","pinned":{"url":["https://hackage.haskell.org/package/quickcheck-io-0.2.0/quickcheck-io-0.2.0.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/quickcheck-io-0.2.0.tar.gz"],"sha256":"fb779119d79fe08ff4d502fb6869a70c9a8d5fd8ae0959f605c3c937efd96422","cabal-sha256":"7bf0b68fb90873825eb2e5e958c1b76126dcf984debb998e81673e6d837e0b2d"},"version":"0.2.0"}, "random": {"dependencies":["base","bytestring","deepseq","mtl","splitmix"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/random-1.2.1.1/random-1.2.1.1.tar.gz"},"name":"random","pinned":{"url":["https://hackage.haskell.org/package/random-1.2.1.1/random-1.2.1.1.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/random-1.2.1.1.tar.gz"],"sha256":"3e1272f7ed6a4d7bd1712b90143ec326fee9b225789222379fea20a9c90c9b76","cabal-sha256":"dea1f11e5569332dc6c8efaad1cb301016a5587b6754943a49f9de08ae0e56d9"},"version":"1.2.1.1"}, "setenv": {"dependencies":["base","unix"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/setenv-0.1.1.3/setenv-0.1.1.3.tar.gz"},"name":"setenv","pinned":{"url":["https://hackage.haskell.org/package/setenv-0.1.1.3/setenv-0.1.1.3.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/setenv-0.1.1.3.tar.gz"],"sha256":"e358df39afc03d5a39e2ec650652d845c85c80cc98fe331654deafb4767ecb32","cabal-sha256":"c5916ac0d2a828473cd171261328a290afe0abd799db1ac8c310682fe778c45b"},"version":"0.1.1.3"}, "splitmix": {"dependencies":["base","deepseq"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/splitmix-0.1.0.4/splitmix-0.1.0.4.tar.gz"},"name":"splitmix","pinned":{"url":["https://hackage.haskell.org/package/splitmix-0.1.0.4/splitmix-0.1.0.4.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/splitmix-0.1.0.4.tar.gz"],"sha256":"6d065402394e7a9117093dbb4530a21342c9b1e2ec509516c8a8d0ffed98ecaa","cabal-sha256":"db25c2e17967aa6b6046ab8b1b96ba3f344ca59a62b60fb6113d51ea305a3d8e"},"version":"0.1.0.4"}, "stm": {"dependencies":[],"location":{"type":"core"},"name":"stm","version":"2.5.0.2"}, "template-haskell": {"dependencies":[],"location":{"type":"core"},"name":"template-haskell","version":"2.18.0.0"}, + "text": {"dependencies":[],"location":{"type":"core"},"name":"text","version":"1.2.5.0"}, "tf-random": {"dependencies":["base","primitive","random","time"],"location":{"type":"hackage","url":"https://hackage.haskell.org/package/tf-random-0.5/tf-random-0.5.tar.gz"},"name":"tf-random","pinned":{"url":["https://hackage.haskell.org/package/tf-random-0.5/tf-random-0.5.tar.gz","https://s3.amazonaws.com/hackage.fpcomplete.com/package/tf-random-0.5.tar.gz"],"sha256":"2e30cec027b313c9e1794d326635d8fc5f79b6bf6e7580ab4b00186dadc88510","cabal-sha256":"14012837d0f0e18fdbbe3d56e67da8622ee5e20b180abce952dd50bd9f36b326"},"version":"0.5"}, "time": {"dependencies":[],"location":{"type":"core"},"name":"time","version":"1.11.1.1"}, "transformers": {"dependencies":[],"location":{"type":"core"},"name":"transformers","version":"0.5.6.2"}, diff --git a/rules_haskell_tests/tests/haskell_module/plugin/Plugin.hs b/rules_haskell_tests/tests/haskell_module/plugin/Plugin.hs index a43148bc5..16052f679 100644 --- a/rules_haskell_tests/tests/haskell_module/plugin/Plugin.hs +++ b/rules_haskell_tests/tests/haskell_module/plugin/Plugin.hs @@ -10,7 +10,7 @@ import GHC.Core import GHC.Core.Opt.Monad import GHC.Types.Literal import GHC.Unit.Module.ModGuts -import GHC.Plugins +-- import GHC.Plugins TODO import System.Process (readProcess) From 767346db76db1a1df1d8fc8231bad49d59147684 Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Thu, 15 Jun 2023 15:43:27 +0200 Subject: [PATCH 24/41] buildfier fix --- WORKSPACE | 14 ++++++++------ examples/WORKSPACE | 12 ++++++------ haskell/ghc_bindist_hadrian.bzl | 23 +++++++++++------------ haskell/toolchain.bzl | 1 - 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/WORKSPACE b/WORKSPACE index 5bfb6fa31..cb6470295 100755 --- a/WORKSPACE +++ b/WORKSPACE @@ -90,18 +90,20 @@ load( "@rules_haskell//haskell:ghc_bindist_hadrian.bzl", "haskell_register_ghc_bindists_hadrian", ) - load( - "non_module_deps_1.bzl", "test_cabalopts", "test_ghcopts" + "non_module_deps_1.bzl", + "test_cabalopts", + "test_ghcopts", ) + haskell_register_ghc_bindists_hadrian( - url = "https://github.com/avdv/testproject/releases/download/ghc-9.2.5/ghc-9.2.5-x86_64-unknown-linux.tar.xz", + cabalopts = test_cabalopts, + ghcopts = test_ghcopts, sha256 = "9dea9123cd53c0d48e72de68480492eaacc2e0bf487a3cd3dfa3ce18729aa3e4", strip_prefix = "ghc-9.2.5-x86_64-unknown-linux", - version = "9.2.5", target = "x86_64-unknown-linux", - cabalopts = test_cabalopts, - ghcopts = test_ghcopts, + url = "https://github.com/avdv/testproject/releases/download/ghc-9.2.5/ghc-9.2.5-x86_64-unknown-linux.tar.xz", + version = "9.2.5", ) register_toolchains( diff --git a/examples/WORKSPACE b/examples/WORKSPACE index 045a3af2b..069648831 100644 --- a/examples/WORKSPACE +++ b/examples/WORKSPACE @@ -58,13 +58,13 @@ test_cabalopts = [ # ) haskell_register_ghc_bindists_hadrian( - url = "https://github.com/avdv/testproject/releases/download/ghc-9.2.5/ghc-9.2.5-x86_64-unknown-linux.tar.xz", + cabalopts = test_cabalopts, + ghcopts = test_ghcopts, sha256 = "9dea9123cd53c0d48e72de68480492eaacc2e0bf487a3cd3dfa3ce18729aa3e4", strip_prefix = "ghc-9.2.5-x86_64-unknown-linux", - version = "9.2.5", target = "x86_64-unknown-linux", - cabalopts = test_cabalopts, - ghcopts = test_ghcopts, + url = "https://github.com/avdv/testproject/releases/download/ghc-9.2.5/ghc-9.2.5-x86_64-unknown-linux.tar.xz", + version = "9.2.5", ) load("@rules_haskell//haskell:toolchain.bzl", "rules_haskell_toolchains") @@ -109,8 +109,6 @@ stack_snapshot( "-pkg-config", ], }, - #local_snapshot = "@rules_haskell//:stackage_snapshot.yaml", - snapshot = "nightly-2023-05-12", packages = [ "base", "bytestring", @@ -121,6 +119,8 @@ stack_snapshot( "text", "text-show", ], + #local_snapshot = "@rules_haskell//:stackage_snapshot.yaml", + snapshot = "nightly-2023-05-12", # This example uses an unpinned version of stack_snapshot, meaning that stack is invoked on every build. # To switch to pinned stackage dependencies, run `bazel run @stackage-unpinned//:pin` and # uncomment the following line. diff --git a/haskell/ghc_bindist_hadrian.bzl b/haskell/ghc_bindist_hadrian.bzl index 8a8b099d6..8590f03d3 100644 --- a/haskell/ghc_bindist_hadrian.bzl +++ b/haskell/ghc_bindist_hadrian.bzl @@ -27,21 +27,22 @@ def _copy_filegroup_impl(ctx): out = ctx.actions.declare_file(output_path) all_outputs.append(out) ctx.actions.run_shell( - outputs=[out], - inputs=depset([f]), - arguments=[f.path, out.path], - command="mkdir -p $(dirname $2) && cp $1 $2") + outputs = [out], + inputs = depset([f]), + arguments = [f.path, out.path], + command = "mkdir -p $(dirname $2) && cp $1 $2", + ) return [ DefaultInfo( - files=depset(all_outputs), - runfiles=ctx.runfiles(files=all_outputs)) + files = depset(all_outputs), + runfiles = ctx.runfiles(files = all_outputs), + ), ] - copy_filegroups_to_this_package = rule( - implementation=_copy_filegroup_impl, - attrs={ + implementation = _copy_filegroup_impl, + attrs = { "srcs": attr.label_list(), }, ) @@ -71,7 +72,7 @@ def _ghc_bindist_hadrian_impl(ctx): bindir = "bin" libdir = "lib" - docdir = "docs" # is "doc" for more recent GHC + docdir = "docs" # is "doc" for more recent GHC # The bindist requires patching invalid haddock paths. See Makefile of GHC: # https://gitlab.haskell.org/ghc/ghc/-/blob/ghc-9.2.3-release/hadrian/bindist/Makefile#L54-74 @@ -91,7 +92,6 @@ find {lib}/package.conf.d -name "rts-*.conf" -print0 | \\ # one has to move all the files coming from the GHC bindist tarball (which is unpacked by a repository rule) to an execroot. # These copied versions of the files are the 'generated_*_filegroup' targets. - generated_bin_filegroup = define_rule( "copy_filegroups_to_this_package", name = "generated_bin_filegroup", @@ -255,7 +255,6 @@ def ghc_bindist_hadrian( repl_ghci_args = None, cabalopts = None, locale = None): - bindist_name = name toolchain_name = "{}-toolchain".format(name) diff --git a/haskell/toolchain.bzl b/haskell/toolchain.bzl index c89ce3b13..350cead46 100644 --- a/haskell/toolchain.bzl +++ b/haskell/toolchain.bzl @@ -616,7 +616,6 @@ def haskell_toolchain( ], ) - toolchain_rule = _ahc_haskell_toolchain if asterius_binaries else _haskell_toolchain toolchain_rule( name = name, From 0ddac25a1a218e334b62245cb62b8c3145362aa0 Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Fri, 16 Jun 2023 10:44:28 +0200 Subject: [PATCH 25/41] Move generated_*_filegroup to toolchain.bzl --- haskell/ghc.BUILD.tpl | 16 ----------- haskell/ghc_bindist_hadrian.bzl | 32 --------------------- haskell/toolchain.bzl | 51 +++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 48 deletions(-) diff --git a/haskell/ghc.BUILD.tpl b/haskell/ghc.BUILD.tpl index 76cc502e4..d661fecee 100644 --- a/haskell/ghc.BUILD.tpl +++ b/haskell/ghc.BUILD.tpl @@ -12,10 +12,6 @@ load( "haskell_import", "haskell_toolchain", ) -load( - "@rules_haskell//haskell:ghc_bindist_hadrian.bzl", - "copy_filegroups_to_this_package", -) package(default_visibility = ["//visibility:public"]) @@ -43,18 +39,6 @@ filegroup( srcs = glob(["%{docdir}/**"]), ) -# Since Bazel regular rules generate files in the "execroots" and GHC requires some files to be next to each other, -# one has to move all the files coming from the GHC bindist tarball to an execroot. -# These copied versions of the files are the 'generated_*_filegroup' targets. - -%{generated_bin_filegroup} - -%{generated_lib_filegroup} - -%{generated_include_filegroup} - -%{generated_docdir_filegroup} - # Expose embedded MinGW toolchain when on Windows. filegroup( diff --git a/haskell/ghc_bindist_hadrian.bzl b/haskell/ghc_bindist_hadrian.bzl index 8590f03d3..0dc4e5d63 100644 --- a/haskell/ghc_bindist_hadrian.bzl +++ b/haskell/ghc_bindist_hadrian.bzl @@ -88,34 +88,6 @@ find {lib}/package.conf.d -name "rts-*.conf" -print0 | \\ if result.return_code != 0: fail(result.stderr) - # Since Bazel regular rules generate files in the "execroots" and GHC requires some files to be next to eachothers, - # one has to move all the files coming from the GHC bindist tarball (which is unpacked by a repository rule) to an execroot. - # These copied versions of the files are the 'generated_*_filegroup' targets. - - generated_bin_filegroup = define_rule( - "copy_filegroups_to_this_package", - name = "generated_bin_filegroup", - srcs = [":bin"], - ) - - generated_lib_filegroup = define_rule( - "copy_filegroups_to_this_package", - name = "generated_lib_filegroup", - srcs = [":lib"], - ) - - generated_docdir_filegroup = define_rule( - "copy_filegroups_to_this_package", - name = "generated_docdir_filegroup", - srcs = [":{}".format(docdir)], - ) - - generated_include_filegroup = define_rule( - "copy_filegroups_to_this_package", - name = "generated_include_filegroup", - srcs = [":include"], - ) - toolchain_libraries = pkgdb_to_bzl(ctx, filepaths, libdir)["file_content"] locale = ctx.attr.locale or ("en_US.UTF-8" if os == "darwin" else "C.UTF-8") toolchain = define_rule( @@ -147,10 +119,6 @@ find {lib}/package.conf.d -name "rts-*.conf" -print0 | \\ "%{toolchain_libraries}": toolchain_libraries, "%{toolchain}": toolchain, "%{docdir}": docdir, - "%{generated_bin_filegroup}": generated_bin_filegroup, - "%{generated_lib_filegroup}": generated_lib_filegroup, - "%{generated_docdir_filegroup}": generated_docdir_filegroup, - "%{generated_include_filegroup}": generated_include_filegroup, "%{is_clang}": str(False), }, executable = False, diff --git a/haskell/toolchain.bzl b/haskell/toolchain.bzl index 350cead46..40168d26f 100644 --- a/haskell/toolchain.bzl +++ b/haskell/toolchain.bzl @@ -26,6 +26,10 @@ load( "ASTERIUS_BINARIES", "asterius_tools_config", ) +load( + "@rules_haskell//haskell:ghc_bindist_hadrian.bzl", + "copy_filegroups_to_this_package", +) _GHC_BINARIES = ["ghc", "ghc-pkg", "hsc2hs", "haddock", "runghc", "hpc"] @@ -532,6 +536,8 @@ def haskell_toolchain( haddock_flags = [], cabalopts = [], locale_archive = None, + docdir = None, + docdir_path = None, **kwargs): """Declare a compiler toolchain. @@ -600,6 +606,27 @@ def haskell_toolchain( new_attr_value = ghcopts, ) + # if docdir_path: + # print("path:", docdir_path) + # elif docdir: + # docdir_path = None + + # # Find a file matching `html/libraries/base-*.*.*.*/*` and infer `docdir` from its path. + # # `GHC.Paths.docdir` reports paths such as `.../doc/html/libraries/base-4.13.0.0`. + # for f in docdir: + # html_start = f.path.find("html/libraries/base") + # if html_start != -1: + # base_end = f.path.find("/", html_start + len("html/libraries/base")) + # if base_end != -1: + # docdir_path = f.path[:base_end] + # break + # if docdir_path == None: + # fail("Could not infer `docdir_path` from provided `docdir` attribute. Missing `lib/settings` file.", "docdir") + # else: + # fail("One of `docdir` and `docdir_path` is required.") + + # fail("docdir: " + ", ".join(docdir)) + if hadrian_bindist: _hadrian_bindist_settings( name = "settings", @@ -615,6 +642,28 @@ def haskell_toolchain( #"mk/system-cxx-std-lib-1.0.conf.in", ], ) + # Since Bazel regular rules generate files in the "execroots" and GHC requires some files to be next to each other, + # one has to move all the files coming from the GHC bindist tarball to an execroot. + # These copied versions of the files are the 'generated_*_filegroup' targets. + + # These copied versions of the files are the 'generated_*_filegroup' targets. + + copy_filegroups_to_this_package( + name = "generated_bin_filegroup", + srcs = [":bin"], + ) + copy_filegroups_to_this_package( + name = "generated_lib_filegroup", + srcs = [":lib"], + ) + copy_filegroups_to_this_package( + name = "generated_docdir_filegroup", + srcs = [":{}".format(docdir_path)], + ) + copy_filegroups_to_this_package( + name = "generated_include_filegroup", + srcs = [":include"], + ) toolchain_rule = _ahc_haskell_toolchain if asterius_binaries else _haskell_toolchain toolchain_rule( @@ -645,6 +694,8 @@ def haskell_toolchain( "//conditions:default": None, }), asterius_binaries = asterius_binaries, + docdir = docdir, + docdir_path = docdir_path, **kwargs ) From e66363b891ef18bad86e43a1bd22162f45a0e48b Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Fri, 16 Jun 2023 10:46:42 +0200 Subject: [PATCH 26/41] Fix syntax error when setting arguments array --- haskell/repl.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/haskell/repl.bzl b/haskell/repl.bzl index a98224885..e2e16084f 100644 --- a/haskell/repl.bzl +++ b/haskell/repl.bzl @@ -490,7 +490,7 @@ def _haskell_repl_impl(ctx): "%{ENV}": render_env(env), "%{TOOL}": hs.tools.ghc.path, "%{OUTPUT}": paths.dirname(output.path), - "%{ARGS}": "--interactive (" + " ".join( + "%{ARGS}": "(--interactive " + " ".join( args + [ shell.quote(a) for a in quote_args From bc8d38494accc4cdd041fe10d986908b9d24ba77 Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Tue, 20 Jun 2023 10:36:40 +0200 Subject: [PATCH 27/41] Fix tools_path for original bindist --- haskell/ghc_bindist.bzl | 1 + 1 file changed, 1 insertion(+) diff --git a/haskell/ghc_bindist.bzl b/haskell/ghc_bindist.bzl index 0cbff6530..31314562b 100644 --- a/haskell/ghc_bindist.bzl +++ b/haskell/ghc_bindist.bzl @@ -243,6 +243,7 @@ rm -f "haskell_toolchain", name = "toolchain-impl", tools = [":bin"], + tools_path = repr("bin"), libraries = "toolchain_libraries", # See Note [GHC toolchain files] libdir = [":lib"], From dfedd3748c1ef70bc77279c3058b082408eb8a5c Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Tue, 20 Jun 2023 10:37:05 +0200 Subject: [PATCH 28/41] Determine docdir dynamically --- haskell/ghc_bindist_hadrian.bzl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/haskell/ghc_bindist_hadrian.bzl b/haskell/ghc_bindist_hadrian.bzl index 0dc4e5d63..608d3ffa0 100644 --- a/haskell/ghc_bindist_hadrian.bzl +++ b/haskell/ghc_bindist_hadrian.bzl @@ -72,7 +72,12 @@ def _ghc_bindist_hadrian_impl(ctx): bindir = "bin" libdir = "lib" - docdir = "docs" # is "doc" for more recent GHC + docdir = None + for d in ["doc", "docs", "docs/html"]: + if ctx.path(d).exists: + if ctx.path(d).get_child("index.html").exists: + docdir = d + break # The bindist requires patching invalid haddock paths. See Makefile of GHC: # https://gitlab.haskell.org/ghc/ghc/-/blob/ghc-9.2.3-release/hadrian/bindist/Makefile#L54-74 From a76f99cb6bd2d96cecee78aaf2116e5a29d01b1e Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Fri, 23 Jun 2023 10:52:17 +0200 Subject: [PATCH 29/41] Fix libdir and docdir path (it is relative to the bindist root) --- haskell/private/context.bzl | 2 +- tools/ghc-paths/ghc_paths.bzl | 15 +++++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/haskell/private/context.bzl b/haskell/private/context.bzl index a0284e628..f8a10466d 100644 --- a/haskell/private/context.bzl +++ b/haskell/private/context.bzl @@ -37,7 +37,7 @@ def haskell_context(ctx, attr = None): "LANG": toolchain.locale, "RULES_HASKELL_GHC_PATH": toolchain.tools.ghc.path, "RULES_HASKELL_GHC_PKG_PATH": toolchain.tools.ghc_pkg.path, - "RULES_HASKELL_LIBDIR_PATH": toolchain.libdir_path, + "RULES_HASKELL_LIBDIR_PATH": paths.join(paths.dirname(paths.dirname(toolchain.tools.ghc.path)), toolchain.libdir_path), "RULES_HASKELL_DOCDIR_PATH": toolchain.docdir_path, } diff --git a/tools/ghc-paths/ghc_paths.bzl b/tools/ghc-paths/ghc_paths.bzl index 229ad68af..11ad5159f 100644 --- a/tools/ghc-paths/ghc_paths.bzl +++ b/tools/ghc-paths/ghc_paths.bzl @@ -2,18 +2,25 @@ load("@bazel_skylib//lib:paths.bzl", "paths") def _ghc_paths_impl(ctx): hs = ctx.toolchains["@rules_haskell//haskell:toolchain"] + print("ws:", ctx.workspace_name) + print("ws:", ctx.label.workspace_root) + print("ghc:", hs.tools.ghc.path) + print("ghc_pkg:", hs.tools.ghc_pkg.path) + print("libdir:", hs.libdir_path) + print("libdir2:", paths.join(hs.tools.ghc.root.path, hs.libdir_path)) ctx.actions.expand_template( template = ctx.file.template, output = ctx.outputs.output, substitutions = { - "%GHC%": paths.join(ctx.workspace_name, hs.tools.ghc.path), - "%GHC_PKG%": paths.join(ctx.workspace_name, hs.tools.ghc_pkg.path), - "%LIBDIR%": paths.join(ctx.workspace_name, hs.libdir_path), - "%DOCDIR%": paths.join(ctx.workspace_name, hs.docdir_path), + "%GHC%": paths.join(ctx.workspace_name, hs.tools.ghc.short_path), + "%GHC_PKG%": paths.join(ctx.workspace_name, hs.tools.ghc_pkg.short_path), + "%LIBDIR%": paths.join(ctx.workspace_name, paths.dirname(paths.dirname(hs.tools.ghc.short_path)), hs.libdir_path), + "%DOCDIR%": paths.join(ctx.workspace_name, paths.dirname(paths.dirname(hs.tools.ghc.short_path)), hs.docdir_path), }, ) return [DefaultInfo( files = depset(direct = [ctx.outputs.output]), + #runfiles = ctx.runfiles(collect_default = True), )] ghc_paths = rule( From 79752f5a1f63a9d36d6fb88d71572f379ae35b5b Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Fri, 23 Jun 2023 10:53:33 +0200 Subject: [PATCH 30/41] ghc-check depends on ghc-paths:bin --- rules_haskell_tests/tests/ghc-check/BUILD.bazel | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/rules_haskell_tests/tests/ghc-check/BUILD.bazel b/rules_haskell_tests/tests/ghc-check/BUILD.bazel index 50c49b204..1e9b6f339 100644 --- a/rules_haskell_tests/tests/ghc-check/BUILD.bazel +++ b/rules_haskell_tests/tests/ghc-check/BUILD.bazel @@ -11,7 +11,10 @@ load( haskell_test( name = "ghc-check", srcs = ["Main.hs"], - data = ["@rules_haskell//tools/ghc-paths:libdir"], + data = [ + "@rules_haskell//tools/ghc-paths:bin", + "@rules_haskell//tools/ghc-paths:libdir", + ], tags = ["requires_dynamic"], deps = [ "@stackage//:base", @@ -39,7 +42,10 @@ haskell_cabal_binary( sh_test( name = "ghc-check-cabal-test{}".format(".exe" if is_windows else ""), srcs = [":ghc-check-cabal"], - data = ["@rules_haskell//tools/ghc-paths:libdir"], + data = [ + "@rules_haskell//tools/ghc-paths:bin", + "@rules_haskell//tools/ghc-paths:libdir", + ], tags = ["requires_dynamic"], ) From 4ec556ba223d8f4319d149b38a27b7892c792be0 Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Mon, 26 Jun 2023 09:04:05 +0200 Subject: [PATCH 31/41] Skip running asterius tests --- .github/workflows/workflow.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/workflow.yaml b/.github/workflows/workflow.yaml index 8725c0244..ba2155a67 100644 --- a/.github/workflows/workflow.yaml +++ b/.github/workflows/workflow.yaml @@ -125,7 +125,7 @@ jobs: # On Windows `//...` expands to `/...`. bazel test ///... else - bazel test --keep_going -- //... + bazel test --keep_going -- //... -//tests/asterius/... fi # Test stack_snapshot pinning # NOTE keep in sync with tests/RunTests.hs From 979e5542ea1afe0daa064b5de8bdb63d526bca21 Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Mon, 26 Jun 2023 17:30:54 +0200 Subject: [PATCH 32/41] Add hadrian bindist for macos and re-enable CI job --- .github/workflows/workflow.yaml | 2 +- WORKSPACE | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/workflow.yaml b/.github/workflows/workflow.yaml index ba2155a67..1c21bdf13 100644 --- a/.github/workflows/workflow.yaml +++ b/.github/workflows/workflow.yaml @@ -18,7 +18,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest] + os: [ubuntu-latest, macos-latest] module: [rules_haskell, rules_haskell_tests] bzlmod: [true, false] ghc: diff --git a/WORKSPACE b/WORKSPACE index cb6470295..a5210b131 100755 --- a/WORKSPACE +++ b/WORKSPACE @@ -106,6 +106,16 @@ haskell_register_ghc_bindists_hadrian( version = "9.2.5", ) +haskell_register_ghc_bindists_hadrian( + cabalopts = test_cabalopts, + ghcopts = test_ghcopts, + sha256 = "55c6a09d00aac69efd03112bd5fcf9a50f87060b1feb6c81f8698752bf164536", + strip_prefix = "ghc-9.2.5-x86_64-apple-darwin", + target = "x86_64-apple-darwin", + url = "https://github.com/avdv/testproject/releases/download/ghc-9.2.5/ghc-9.2.5-x86_64-apple-darwin.tar.xz", + version = "9.2.5", +) + register_toolchains( "//tests:protobuf-toolchain", "//tests:protobuf-toolchain-osx_arm64", From 5b527adaae0dd74adef5aee1bd83548d6ab7176e Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Mon, 26 Jun 2023 19:03:35 +0200 Subject: [PATCH 33/41] Add hadrian bindist for macos to start script too --- start | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/start b/start index cf40a7cd0..f7e720700 100755 --- a/start +++ b/start @@ -302,6 +302,16 @@ case "${MODE}" in cabalopts = test_cabalopts, ghcopts = test_ghcopts, ) + haskell_register_ghc_bindists_hadrian( + cabalopts = test_cabalopts, + ghcopts = test_ghcopts, + sha256 = "55c6a09d00aac69efd03112bd5fcf9a50f87060b1feb6c81f8698752bf164536", + strip_prefix = "ghc-9.2.5-x86_64-apple-darwin", + target = "x86_64-apple-darwin", + url = "https://github.com/avdv/testproject/releases/download/ghc-9.2.5/ghc-9.2.5-x86_64-apple-darwin.tar.xz", + version = "9.2.5", + ) + http_archive( name = "zlib.dev", build_file = "//:${ZLIB_BUILD_FILE}", From cd703c756672cb6131c52c21320619387a427d1b Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Mon, 26 Jun 2023 19:05:45 +0200 Subject: [PATCH 34/41] Enable `--test_verbose_timeout_warnings` on CI --- .bazelrc.common | 1 + 1 file changed, 1 insertion(+) diff --git a/.bazelrc.common b/.bazelrc.common index 5127fd6b1..cf0e0233e 100644 --- a/.bazelrc.common +++ b/.bazelrc.common @@ -61,6 +61,7 @@ build:ci-common --verbose_failures build:ci-common --symlink_prefix=bazel-ci- build:ci-common --repository_cache=~/repo-cache/ build:ci-common --experimental_repository_cache_hardlinks +build:ci-common --test_verbose_timeout_warnings # Use a remote cache during CI build:ci-windows-bindist --bes_upload_mode=wait_for_upload_complete --bes_timeout=600s From 1398da037e773ebe200014aa6991b11b9e25cd69 Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Tue, 27 Jun 2023 08:05:18 +0200 Subject: [PATCH 35/41] Fix libdir path for protoc --- haskell/protobuf.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/haskell/protobuf.bzl b/haskell/protobuf.bzl index 5a1565d53..44c8aa982 100644 --- a/haskell/protobuf.bzl +++ b/haskell/protobuf.bzl @@ -159,7 +159,7 @@ def _haskell_proto_aspect_impl(target, ctx): env = { "RULES_HASKELL_GHC_PATH": hs.tools.ghc.path, "RULES_HASKELL_GHC_PKG_PATH": hs.tools.ghc_pkg.path, - "RULES_HASKELL_LIBDIR_PATH": hs.libdir_path, + "RULES_HASKELL_LIBDIR_PATH": paths.join(paths.dirname(paths.dirname(hs.tools.ghc.path)), hs.libdir_path), "RULES_HASKELL_DOCDIR_PATH": hs.docdir_path, }, ) From 4492dddc977fa5ac7e43abfb226887e62e02f82d Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Tue, 27 Jun 2023 08:09:43 +0200 Subject: [PATCH 36/41] Debug toolchain resolution --- .bazelrc.common | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.bazelrc.common b/.bazelrc.common index cf0e0233e..3c85f1feb 100644 --- a/.bazelrc.common +++ b/.bazelrc.common @@ -103,6 +103,8 @@ build:linux-bindist --experimental_strict_action_env build:macos-bindist --experimental_strict_action_env build:windows-bindist --experimental_strict_action_env +build:macos-bindist --toolchain_resolution_debug='.*' + # Note [backward compatible options] build:linux-bindist --incompatible_enable_cc_toolchain_resolution build:macos-bindist --incompatible_enable_cc_toolchain_resolution From e4780339a75ec70e351d8e0458a0de7e6b6cb07c Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Tue, 27 Jun 2023 09:46:26 +0200 Subject: [PATCH 37/41] Only enable test_verbose_timeout_warnings for tests --- .bazelrc.common | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.bazelrc.common b/.bazelrc.common index 3c85f1feb..c0cdf26a3 100644 --- a/.bazelrc.common +++ b/.bazelrc.common @@ -61,7 +61,8 @@ build:ci-common --verbose_failures build:ci-common --symlink_prefix=bazel-ci- build:ci-common --repository_cache=~/repo-cache/ build:ci-common --experimental_repository_cache_hardlinks -build:ci-common --test_verbose_timeout_warnings + +test:ci-common --test_verbose_timeout_warnings # Use a remote cache during CI build:ci-windows-bindist --bes_upload_mode=wait_for_upload_complete --bes_timeout=600s From b344d21a66b094c02fee45d1fd8560526e84992c Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Tue, 27 Jun 2023 09:47:36 +0200 Subject: [PATCH 38/41] Debug toolchain resolution in start script --- start | 2 ++ 1 file changed, 2 insertions(+) diff --git a/start b/start index f7e720700..5c2084033 100755 --- a/start +++ b/start @@ -396,6 +396,8 @@ test:ci --test_output=errors # Should become the default in bazel 7 build --incompatible_enable_cc_toolchain_resolution +common --toolchain_resolution_debug='.*' + EOF if [ "${MODE}" = "nix" ]; then From efeec34eafbd9b21ab23e70c7affe4a377951530 Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Fri, 3 Nov 2023 11:10:59 +0100 Subject: [PATCH 39/41] CI: Skip GHC 9.4.x for now --- .github/workflows/workflow.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/workflow.yaml b/.github/workflows/workflow.yaml index 1c21bdf13..d41e5d3f0 100644 --- a/.github/workflows/workflow.yaml +++ b/.github/workflows/workflow.yaml @@ -23,7 +23,7 @@ jobs: bzlmod: [true, false] ghc: - 9.2.5 - - 9.4.5 + #- 9.4.5 exclude: # TODO: in a MODULE.bazel file we declare version specific dependencies, would need to use stack snapshot json # and stack config per GHC version From 97dfac2b1ce2a9952f1e5cc48d903e5a8bf1b2e8 Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Fri, 3 Nov 2023 12:31:33 +0100 Subject: [PATCH 40/41] Fix WORKSPACE setup for hadrian bindist --- WORKSPACE | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/WORKSPACE b/WORKSPACE index a5210b131..e7b525d4a 100755 --- a/WORKSPACE +++ b/WORKSPACE @@ -90,11 +90,21 @@ load( "@rules_haskell//haskell:ghc_bindist_hadrian.bzl", "haskell_register_ghc_bindists_hadrian", ) -load( - "non_module_deps_1.bzl", - "test_cabalopts", - "test_ghcopts", -) + +test_ghcopts = [ + "-XStandaloneDeriving", # Flag used at compile time + "-threaded", # Flag used at link time + # Used by `tests/repl-flags` + "-DTESTS_TOOLCHAIN_COMPILER_FLAGS", + # this is the default, so it does not harm other tests + "-XNoOverloadedStrings", +] + +test_cabalopts = [ + # Used by `tests/cabal-toolchain-flags` + "--ghc-option=-DTESTS_TOOLCHAIN_CABALOPTS", + "--haddock-option=--optghc=-DTESTS_TOOLCHAIN_CABALOPTS", +] haskell_register_ghc_bindists_hadrian( cabalopts = test_cabalopts, From c1e1916462e68cf84d8cb1e8062aa07d3923532f Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Mon, 6 Nov 2023 11:28:38 +0100 Subject: [PATCH 41/41] Skip registering normal ghc bindists --- WORKSPACE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WORKSPACE b/WORKSPACE index e7b525d4a..c4188fac5 100755 --- a/WORKSPACE +++ b/WORKSPACE @@ -64,7 +64,7 @@ load( "haskell_register_ghc_bindists", ) -haskell_register_ghc_bindists(version = GHC_VERSION) +#haskell_register_ghc_bindists(version = GHC_VERSION) load( "@rules_haskell//haskell/asterius:repositories.bzl",