From e3859934e2c38db20f2a6f6998aba55dc49940a9 Mon Sep 17 00:00:00 2001 From: Lionel Parreaux Date: Wed, 20 Nov 2024 15:54:04 +0800 Subject: [PATCH] Add some documentation and minor changes --- .github/workflows/nix.yml | 4 +- README.md | 8 + compiler/shared/test/diff-ir/cpp/Makefile | 4 +- flake.nix | 2 +- shared/src/test/diff/fcp/NestedDataTypes.mls | 183 +------------------ 5 files changed, 22 insertions(+), 179 deletions(-) diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index a3e1b79f07..044e4df66e 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -1,9 +1,9 @@ -name: Cpp Backend CI with Nix +name: CI with Nix on: pull_request: push: - branches: [ mlscript ] + branches: [ mlscript, hkmc2 ] jobs: build: diff --git a/README.md b/README.md index f0eeec9564..d236fe4444 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,14 @@ We recommend you to install JDK and sbt via [coursier][coursier]. The versions o [node.js]: https://nodejs.org/ [coursier]: https://get-coursier.io/ +Some tests in the `compiler` subproject generate and compile C++ while making use of some libraries. +You can run these by installing `nix` (for MacOS, we recommend https://determinate.systems/posts/graphical-nix-installer/) +and running `nix develop` before launching SBT. +If you don't want to use nix, you can install the dependencies manually as follows, but this has not been tested on non-MacOS systems: +```bash +brew install mimalloc boost gmp +``` + ### Running the tests Running the main MLscript tests only requires the Scala Build Tool installed. diff --git a/compiler/shared/test/diff-ir/cpp/Makefile b/compiler/shared/test/diff-ir/cpp/Makefile index 082a04fbea..2f7a2bd6fc 100644 --- a/compiler/shared/test/diff-ir/cpp/Makefile +++ b/compiler/shared/test/diff-ir/cpp/Makefile @@ -1,6 +1,6 @@ CXX := g++ -CFLAGS := $(CFLAGS) -O3 -Wall -Wextra -std=c++20 -I. -Wno-inconsistent-missing-override -LDFLAGS := $(LDFLAGS) -lmimalloc -lgmp +CFLAGS := $(CFLAGS) -O3 -Wall -Wextra -std=c++20 -I. -Wno-inconsistent-missing-override -I/opt/homebrew/include +LDFLAGS := $(LDFLAGS) -lmimalloc -lgmp -L/opt/homebrew/lib SRC := INCLUDES = mlsprelude.h DST := diff --git a/flake.nix b/flake.nix index 5619a8410d..5f81da24a5 100644 --- a/flake.nix +++ b/flake.nix @@ -31,4 +31,4 @@ ]; }; }); -} \ No newline at end of file +} diff --git a/shared/src/test/diff/fcp/NestedDataTypes.mls b/shared/src/test/diff/fcp/NestedDataTypes.mls index 9aa94da253..5f81436048 100644 --- a/shared/src/test/diff/fcp/NestedDataTypes.mls +++ b/shared/src/test/diff/fcp/NestedDataTypes.mls @@ -60,177 +60,12 @@ n4: PerfectTree[int] //│ = Node1 { subTree: Node1 { subTree: Leaf { value: [Array] } } } -:e // * Needs precise-rec-typing (see below) -rec def map f tree = case tree of { - | Leaf -> Leaf { value = f tree.value } - | Node -> Node { subTree = map (mapTwo f) tree.subTree } - } -//│ ╔══[ERROR] Inferred recursive type: 'a -//│ where -//│ 'a <: {subTree: Leaf[?] & {value: ((?, (?, ?,),), ((?, ?,), ?,),)} | Node[?] & 'a} -//│ ║ l.64: rec def map f tree = case tree of { -//│ ╙── ^^^^ -//│ ╔══[ERROR] Cyclic-looking constraint while typing binding of lambda expression; a type annotation may be required -//│ ║ l.64: rec def map f tree = case tree of { -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.65: | Leaf -> Leaf { value = f tree.value } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.66: | Node -> Node { subTree = map (mapTwo f) tree.subTree } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.67: } -//│ ║ ^^^ -//│ ╙── Note: use flag `:ex` to see internal error info. -//│ ╔══[ERROR] Cyclic-looking constraint while typing binding of lambda expression; a type annotation may be required -//│ ║ l.64: rec def map f tree = case tree of { -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.65: | Leaf -> Leaf { value = f tree.value } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.66: | Node -> Node { subTree = map (mapTwo f) tree.subTree } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.67: } -//│ ║ ^^^ -//│ ╙── Note: use flag `:ex` to see internal error info. -//│ ╔══[ERROR] Cyclic-looking constraint while typing binding of lambda expression; a type annotation may be required -//│ ║ l.64: rec def map f tree = case tree of { -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.65: | Leaf -> Leaf { value = f tree.value } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.66: | Node -> Node { subTree = map (mapTwo f) tree.subTree } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.67: } -//│ ║ ^^^ -//│ ╙── Note: use flag `:ex` to see internal error info. -//│ ╔══[ERROR] Cyclic-looking constraint while typing binding of lambda expression; a type annotation may be required -//│ ║ l.64: rec def map f tree = case tree of { -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.65: | Leaf -> Leaf { value = f tree.value } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.66: | Node -> Node { subTree = map (mapTwo f) tree.subTree } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.67: } -//│ ║ ^^^ -//│ ╙── Note: use flag `:ex` to see internal error info. -//│ ╔══[ERROR] Cyclic-looking constraint while typing binding of lambda expression; a type annotation may be required -//│ ║ l.64: rec def map f tree = case tree of { -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.65: | Leaf -> Leaf { value = f tree.value } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.66: | Node -> Node { subTree = map (mapTwo f) tree.subTree } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.67: } -//│ ║ ^^^ -//│ ╙── Note: use flag `:ex` to see internal error info. -//│ ╔══[ERROR] Cyclic-looking constraint while typing binding of lambda expression; a type annotation may be required -//│ ║ l.64: rec def map f tree = case tree of { -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.65: | Leaf -> Leaf { value = f tree.value } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.66: | Node -> Node { subTree = map (mapTwo f) tree.subTree } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.67: } -//│ ║ ^^^ -//│ ╙── Note: use flag `:ex` to see internal error info. -//│ ╔══[ERROR] Cyclic-looking constraint while typing binding of lambda expression; a type annotation may be required -//│ ║ l.64: rec def map f tree = case tree of { -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.65: | Leaf -> Leaf { value = f tree.value } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.66: | Node -> Node { subTree = map (mapTwo f) tree.subTree } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.67: } -//│ ║ ^^^ -//│ ╙── Note: use flag `:ex` to see internal error info. -//│ ╔══[ERROR] Cyclic-looking constraint while typing binding of lambda expression; a type annotation may be required -//│ ║ l.64: rec def map f tree = case tree of { -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.65: | Leaf -> Leaf { value = f tree.value } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.66: | Node -> Node { subTree = map (mapTwo f) tree.subTree } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.67: } -//│ ║ ^^^ -//│ ╙── Note: use flag `:ex` to see internal error info. -//│ ╔══[ERROR] Cyclic-looking constraint while typing binding of lambda expression; a type annotation may be required -//│ ║ l.64: rec def map f tree = case tree of { -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.65: | Leaf -> Leaf { value = f tree.value } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.66: | Node -> Node { subTree = map (mapTwo f) tree.subTree } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.67: } -//│ ║ ^^^ -//│ ╙── Note: use flag `:ex` to see internal error info. -//│ ╔══[ERROR] Cyclic-looking constraint while typing binding of lambda expression; a type annotation may be required -//│ ║ l.64: rec def map f tree = case tree of { -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.65: | Leaf -> Leaf { value = f tree.value } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.66: | Node -> Node { subTree = map (mapTwo f) tree.subTree } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.67: } -//│ ║ ^^^ -//│ ╙── Note: use flag `:ex` to see internal error info. -//│ ╔══[ERROR] Cyclic-looking constraint while typing binding of lambda expression; a type annotation may be required -//│ ║ l.64: rec def map f tree = case tree of { -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.65: | Leaf -> Leaf { value = f tree.value } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.66: | Node -> Node { subTree = map (mapTwo f) tree.subTree } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.67: } -//│ ║ ^^^ -//│ ╙── Note: use flag `:ex` to see internal error info. -//│ ╔══[ERROR] Cyclic-looking constraint while typing binding of lambda expression; a type annotation may be required -//│ ║ l.64: rec def map f tree = case tree of { -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.65: | Leaf -> Leaf { value = f tree.value } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.66: | Node -> Node { subTree = map (mapTwo f) tree.subTree } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.67: } -//│ ║ ^^^ -//│ ╙── Note: use flag `:ex` to see internal error info. -//│ ╔══[ERROR] Cyclic-looking constraint while typing binding of lambda expression; a type annotation may be required -//│ ║ l.64: rec def map f tree = case tree of { -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.65: | Leaf -> Leaf { value = f tree.value } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.66: | Node -> Node { subTree = map (mapTwo f) tree.subTree } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.67: } -//│ ║ ^^^ -//│ ╙── Note: use flag `:ex` to see internal error info. -//│ ╔══[ERROR] Cyclic-looking constraint while typing binding of lambda expression; a type annotation may be required -//│ ║ l.64: rec def map f tree = case tree of { -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.65: | Leaf -> Leaf { value = f tree.value } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.66: | Node -> Node { subTree = map (mapTwo f) tree.subTree } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.67: } -//│ ║ ^^^ -//│ ╙── Note: use flag `:ex` to see internal error info. -//│ ╔══[ERROR] Subtyping constraint of the form `?a -> ?b -> (?c | ?d) <: ?map` exceeded recursion depth limit (250) -//│ ║ l.64: rec def map f tree = case tree of { -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.65: | Leaf -> Leaf { value = f tree.value } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.66: | Node -> Node { subTree = map (mapTwo f) tree.subTree } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.67: } -//│ ║ ^^^ -//│ ╙── Note: use flag `:ex` to see internal error info. -//│ map: ('value -> (Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two['A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'value0) & 'a -> (Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two['A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'b & 'A) & 'c -> (Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two['A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'd & 'A) & 'e -> (Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two['A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'f & 'A) & 'g -> (Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two['A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'h & 'A)) -> 'i -> (Leaf[((nothing, (nothing, nothing,) | 'd,) | 'b, ((nothing, nothing,) | 'h, nothing,) | 'f,) | 'value0] | 'j) -//│ where -//│ 'j :> Node['A] with { -//│ subTree: Leaf[((nothing, (nothing, nothing,) | 'd,) | 'b, ((nothing, nothing,) | 'h, nothing,) | 'f,) | 'value0] | 'j -//│ } -//│ 'i <: Leaf[?] & { -//│ value: ((anything, (anything, anything,) & 'c,) & 'a, ((anything, anything,) & 'g, anything,) & 'e,) & 'value -//│ } | (Node[?] with {subTree: 'i}) -//│ 'A :> ((nothing, nothing,) | 'h, (nothing, nothing,) | 'd,) -//│ <: Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two[Two['A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] & 'A] -//│ = [Function: map] +// * On some systems, the default -Xss4M is not enough for this case +// :e // * Needs precise-rec-typing (see below) +// rec def map f tree = case tree of { +// | Leaf -> Leaf { value = f tree.value } +// | Node -> Node { subTree = map (mapTwo f) tree.subTree } +// } :e // occurs-check :precise-rec-typing @@ -255,7 +90,7 @@ rec def map f tree = case tree of { //│ where //│ 'a <: 'b -> 'c & 'd -> 'e) -> 'subTree -> (PerfectTree[Two['A]] & 'subTree0) //│ 'a <: 'value -> 'value0) -//│ = [Function: map1] +//│ = [Function: map] :e map succ n4 @@ -269,8 +104,8 @@ map succ n4 //│ 'a <: 'value -> 'value0) //│ ╙── //│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required -//│ ║ l.261: map succ n4 -//│ ║ ^^^^^^^^^^^ +//│ ║ l.96: map succ n4 +//│ ║ ^^^^^^^^^^^ //│ ╙── Note: use flag `:ex` to see internal error info. //│ res: error //│ = Node1 { subTree: Node1 { subTree: Leaf { value: [Array] } } }