diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 82156fb6b0..59c82b4983 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -73,6 +73,7 @@ jobs: - name: Check parser error messages exhaustiveness run: | npm run compiler parser:check-errors + npm run compiler graindoc-parser:check-errors # Formatting lint last because building is more important - name: Run formatting lint diff --git a/compiler/esy.json b/compiler/esy.json index b6983c1d30..5307e00283 100644 --- a/compiler/esy.json +++ b/compiler/esy.json @@ -38,7 +38,7 @@ "@opam/dune-configurator": ">= 3.6.1 < 4.0.0", "@opam/fp": "0.0.1", "@opam/fs": "0.0.2", - "@opam/menhir": "20211125", + "@opam/menhir": "20220210", "@opam/ocamlgraph": ">= 2.0.0 < 3.0.0", "@opam/ppx_deriving": ">= 5.2.1 < 6.0.0", "@opam/ppx_deriving_cmdliner": ">= 0.6.1", diff --git a/compiler/esy.lock/index.json b/compiler/esy.lock/index.json index d4a1ec149b..1bfe393942 100644 --- a/compiler/esy.lock/index.json +++ b/compiler/esy.lock/index.json @@ -1,5 +1,5 @@ { - "checksum": "c0fd160e669e4135a3c194cb5123a95e", + "checksum": "c922120cb5fa1586903a0da6b7150e13", "root": "@grain/compiler@link-dev:./esy.json", "node": { "yarn-pkg-config@github:esy-ocaml/yarn-pkg-config#db3a0b63883606dd57c54a7158d560d6cba8cd79@d41d8cd9": { @@ -220,7 +220,7 @@ "overrides": [], "dependencies": [ "ocaml@github:phated/ocaml:package.json#a25997805f1ce225f23c0321e827c0d503896017@d41d8cd9", - "@opam/topkg@opam:1.0.6@da3f4ab1", + "@opam/topkg@opam:1.0.7@7ee47d76", "@opam/ocamlfind@opam:1.9.5@c23112ba", "@opam/ocamlbuild@opam:0.14.2@c6163b28", "@opam/cmdliner@opam:1.1.1@03763729", @@ -250,7 +250,7 @@ "dependencies": [ "ocaml@github:phated/ocaml:package.json#a25997805f1ce225f23c0321e827c0d503896017@d41d8cd9", "@opam/uutf@opam:1.0.3@47c95a18", "@opam/uucp@opam:15.0.0@55460339", - "@opam/topkg@opam:1.0.6@da3f4ab1", + "@opam/topkg@opam:1.0.7@7ee47d76", "@opam/ocamlfind@opam:1.9.5@c23112ba", "@opam/ocamlbuild@opam:0.14.2@c6163b28", "@opam/cmdliner@opam:1.1.1@03763729", @@ -280,7 +280,7 @@ "overrides": [], "dependencies": [ "ocaml@github:phated/ocaml:package.json#a25997805f1ce225f23c0321e827c0d503896017@d41d8cd9", - "@opam/uutf@opam:1.0.3@47c95a18", "@opam/topkg@opam:1.0.6@da3f4ab1", + "@opam/uutf@opam:1.0.3@47c95a18", "@opam/topkg@opam:1.0.7@7ee47d76", "@opam/ocamlfind@opam:1.9.5@c23112ba", "@opam/ocamlbuild@opam:0.14.2@c6163b28", "@opam/cmdliner@opam:1.1.1@03763729", @@ -290,20 +290,20 @@ "ocaml@github:phated/ocaml:package.json#a25997805f1ce225f23c0321e827c0d503896017@d41d8cd9" ] }, - "@opam/utop@opam:2.10.0@9af1bb18": { - "id": "@opam/utop@opam:2.10.0@9af1bb18", + "@opam/utop@opam:2.11.0@bd245e47": { + "id": "@opam/utop@opam:2.11.0@bd245e47", "name": "@opam/utop", - "version": "opam:2.10.0", + "version": "opam:2.11.0", "source": { "type": "install", "source": [ - "archive:https://opam.ocaml.org/cache/sha256/47/475d16a2f9ea61c602ac32673ee210c76cc768f7214987d70c069532c2782d00#sha256:475d16a2f9ea61c602ac32673ee210c76cc768f7214987d70c069532c2782d00", - "archive:https://github.com/ocaml-community/utop/releases/download/2.10.0/utop-2.10.0.tbz#sha256:475d16a2f9ea61c602ac32673ee210c76cc768f7214987d70c069532c2782d00" + "archive:https://opam.ocaml.org/cache/sha256/69/6937c6c672913ac3b875341ac4a205c7561d01cd8ac8f47cfb35d3bc0e762170#sha256:6937c6c672913ac3b875341ac4a205c7561d01cd8ac8f47cfb35d3bc0e762170", + "archive:https://github.com/ocaml-community/utop/releases/download/2.11.0/utop-2.11.0.tbz#sha256:6937c6c672913ac3b875341ac4a205c7561d01cd8ac8f47cfb35d3bc0e762170" ], "opam": { "name": "utop", - "version": "2.10.0", - "path": "esy.lock/opam/utop.2.10.0" + "version": "2.11.0", + "path": "esy.lock/opam/utop.2.11.0" } }, "overrides": [], @@ -442,20 +442,20 @@ "@opam/dune@opam:3.6.1@662f326b" ] }, - "@opam/topkg@opam:1.0.6@da3f4ab1": { - "id": "@opam/topkg@opam:1.0.6@da3f4ab1", + "@opam/topkg@opam:1.0.7@7ee47d76": { + "id": "@opam/topkg@opam:1.0.7@7ee47d76", "name": "@opam/topkg", - "version": "opam:1.0.6", + "version": "opam:1.0.7", "source": { "type": "install", "source": [ - "archive:https://opam.ocaml.org/cache/sha512/8e/8e34391e2f499cec332b79454a4edb36a35db6fe22437f017fd5c80ae065160dc967ac02d894a94d08d62dd476521e63733f4cadc3b9b6b314b6aa5b2b4ede78#sha512:8e34391e2f499cec332b79454a4edb36a35db6fe22437f017fd5c80ae065160dc967ac02d894a94d08d62dd476521e63733f4cadc3b9b6b314b6aa5b2b4ede78", - "archive:https://erratique.ch/software/topkg/releases/topkg-1.0.6.tbz#sha512:8e34391e2f499cec332b79454a4edb36a35db6fe22437f017fd5c80ae065160dc967ac02d894a94d08d62dd476521e63733f4cadc3b9b6b314b6aa5b2b4ede78" + "archive:https://opam.ocaml.org/cache/sha512/09/09e59f1759bf4db8471f02d0aefd8db602b44932a291c05c312b1423796e7a15d1598d3c62a0cec7f083eff8e410fac09363533dc4bd2120914bb9664efea535#sha512:09e59f1759bf4db8471f02d0aefd8db602b44932a291c05c312b1423796e7a15d1598d3c62a0cec7f083eff8e410fac09363533dc4bd2120914bb9664efea535", + "archive:https://erratique.ch/software/topkg/releases/topkg-1.0.7.tbz#sha512:09e59f1759bf4db8471f02d0aefd8db602b44932a291c05c312b1423796e7a15d1598d3c62a0cec7f083eff8e410fac09363533dc4bd2120914bb9664efea535" ], "opam": { "name": "topkg", - "version": "1.0.6", - "path": "esy.lock/opam/topkg.1.0.6" + "version": "1.0.7", + "path": "esy.lock/opam/topkg.1.0.7" } }, "overrides": [], @@ -627,13 +627,13 @@ "dependencies": [ "ocaml@github:phated/ocaml:package.json#a25997805f1ce225f23c0321e827c0d503896017@d41d8cd9", "@opam/sexplib0@opam:v0.15.1@51111c0c", - "@opam/parsexp@opam:v0.15.0@742345c3", "@opam/num@opam:1.4@54b259a0", + "@opam/parsexp@opam:v0.15.0@742345c3", "@opam/num@opam:1.4@16d26a67", "@opam/dune@opam:3.6.1@662f326b", "@esy-ocaml/substs@0.0.1@d41d8cd9" ], "devDependencies": [ "ocaml@github:phated/ocaml:package.json#a25997805f1ce225f23c0321e827c0d503896017@d41d8cd9", "@opam/sexplib0@opam:v0.15.1@51111c0c", - "@opam/parsexp@opam:v0.15.0@742345c3", "@opam/num@opam:1.4@54b259a0", + "@opam/parsexp@opam:v0.15.0@742345c3", "@opam/num@opam:1.4@16d26a67", "@opam/dune@opam:3.6.1@662f326b" ] }, @@ -738,7 +738,7 @@ "@opam/ppx_derivers@opam:1.2.1@e2cbad12", "@opam/ocamlfind@opam:1.9.5@c23112ba", "@opam/merlin-extend@opam:0.6.1@7d979feb", - "@opam/menhir@opam:20211125@5ae9a0c2", + "@opam/menhir@opam:20220210@ff5ea9a7", "@opam/fix@opam:20220121@17b9a1a4", "@opam/dune@opam:3.6.1@662f326b", "@esy-ocaml/substs@0.0.1@d41d8cd9" ], @@ -747,7 +747,7 @@ "@opam/result@opam:1.5@1c6a6533", "@opam/ppx_derivers@opam:1.2.1@e2cbad12", "@opam/merlin-extend@opam:0.6.1@7d979feb", - "@opam/menhir@opam:20211125@5ae9a0c2", + "@opam/menhir@opam:20220210@ff5ea9a7", "@opam/fix@opam:20220121@17b9a1a4", "@opam/dune@opam:3.6.1@662f326b" ] }, @@ -770,7 +770,7 @@ "overrides": [], "dependencies": [ "ocaml@github:phated/ocaml:package.json#a25997805f1ce225f23c0321e827c0d503896017@d41d8cd9", - "@opam/topkg@opam:1.0.6@da3f4ab1", + "@opam/topkg@opam:1.0.7@7ee47d76", "@opam/ocamlfind@opam:1.9.5@c23112ba", "@opam/ocamlbuild@opam:0.14.2@c6163b28", "@esy-ocaml/substs@0.0.1@d41d8cd9" @@ -919,14 +919,14 @@ "ocaml@github:phated/ocaml:package.json#a25997805f1ce225f23c0321e827c0d503896017@d41d8cd9", "@opam/yojson@opam:2.0.2@eb65f292", "@opam/result@opam:1.5@1c6a6533", "@opam/ppxlib@opam:0.28.0@8c51d241", - "@opam/ppx_deriving@opam:5.2.1@089e5dd3", + "@opam/ppx_deriving@opam:5.2.1@2315fdd0", "@opam/dune@opam:3.6.1@662f326b", "@esy-ocaml/substs@0.0.1@d41d8cd9" ], "devDependencies": [ "ocaml@github:phated/ocaml:package.json#a25997805f1ce225f23c0321e827c0d503896017@d41d8cd9", "@opam/yojson@opam:2.0.2@eb65f292", "@opam/result@opam:1.5@1c6a6533", "@opam/ppxlib@opam:0.28.0@8c51d241", - "@opam/ppx_deriving@opam:5.2.1@089e5dd3", + "@opam/ppx_deriving@opam:5.2.1@2315fdd0", "@opam/dune@opam:3.6.1@662f326b" ] }, @@ -947,7 +947,7 @@ "ocaml@github:phated/ocaml:package.json#a25997805f1ce225f23c0321e827c0d503896017@d41d8cd9", "@opam/result@opam:1.5@1c6a6533", "@opam/ppxlib@opam:0.28.0@8c51d241", - "@opam/ppx_deriving@opam:5.2.1@089e5dd3", + "@opam/ppx_deriving@opam:5.2.1@2315fdd0", "@opam/dune@opam:3.6.1@662f326b", "@opam/cmdliner@opam:1.1.1@03763729", "@esy-ocaml/substs@0.0.1@d41d8cd9" @@ -956,13 +956,13 @@ "ocaml@github:phated/ocaml:package.json#a25997805f1ce225f23c0321e827c0d503896017@d41d8cd9", "@opam/result@opam:1.5@1c6a6533", "@opam/ppxlib@opam:0.28.0@8c51d241", - "@opam/ppx_deriving@opam:5.2.1@089e5dd3", + "@opam/ppx_deriving@opam:5.2.1@2315fdd0", "@opam/dune@opam:3.6.1@662f326b", "@opam/cmdliner@opam:1.1.1@03763729" ] }, - "@opam/ppx_deriving@opam:5.2.1@089e5dd3": { - "id": "@opam/ppx_deriving@opam:5.2.1@089e5dd3", + "@opam/ppx_deriving@opam:5.2.1@2315fdd0": { + "id": "@opam/ppx_deriving@opam:5.2.1@2315fdd0", "name": "@opam/ppx_deriving", "version": "opam:5.2.1", "source": { @@ -1407,8 +1407,8 @@ "@opam/dune@opam:3.6.1@662f326b" ] }, - "@opam/num@opam:1.4@54b259a0": { - "id": "@opam/num@opam:1.4@54b259a0", + "@opam/num@opam:1.4@16d26a67": { + "id": "@opam/num@opam:1.4@16d26a67", "name": "@opam/num", "version": "opam:1.4", "source": { @@ -1521,20 +1521,20 @@ "@opam/dune@opam:3.6.1@662f326b" ] }, - "@opam/menhirSdk@opam:20211125@60ac0b7e": { - "id": "@opam/menhirSdk@opam:20211125@60ac0b7e", + "@opam/menhirSdk@opam:20220210@fe146ed3": { + "id": "@opam/menhirSdk@opam:20220210@fe146ed3", "name": "@opam/menhirSdk", - "version": "opam:20211125", + "version": "opam:20220210", "source": { "type": "install", "source": [ - "archive:https://opam.ocaml.org/cache/md5/27/27ddfc9be183d6ae8f5440d807c68e38#md5:27ddfc9be183d6ae8f5440d807c68e38", - "archive:https://gitlab.inria.fr/fpottier/menhir/-/archive/20211125/archive.tar.gz#md5:27ddfc9be183d6ae8f5440d807c68e38" + "archive:https://opam.ocaml.org/cache/md5/e3/e3cef220f676c4b1c16cbccb174cefe3#md5:e3cef220f676c4b1c16cbccb174cefe3", + "archive:https://gitlab.inria.fr/fpottier/menhir/-/archive/20220210/archive.tar.gz#md5:e3cef220f676c4b1c16cbccb174cefe3" ], "opam": { "name": "menhirSdk", - "version": "20211125", - "path": "esy.lock/opam/menhirSdk.20211125" + "version": "20220210", + "path": "esy.lock/opam/menhirSdk.20220210" } }, "overrides": [], @@ -1547,20 +1547,20 @@ "@opam/dune@opam:3.6.1@662f326b" ] }, - "@opam/menhirLib@opam:20211125@cd0b955b": { - "id": "@opam/menhirLib@opam:20211125@cd0b955b", + "@opam/menhirLib@opam:20220210@9afeb270": { + "id": "@opam/menhirLib@opam:20220210@9afeb270", "name": "@opam/menhirLib", - "version": "opam:20211125", + "version": "opam:20220210", "source": { "type": "install", "source": [ - "archive:https://opam.ocaml.org/cache/md5/27/27ddfc9be183d6ae8f5440d807c68e38#md5:27ddfc9be183d6ae8f5440d807c68e38", - "archive:https://gitlab.inria.fr/fpottier/menhir/-/archive/20211125/archive.tar.gz#md5:27ddfc9be183d6ae8f5440d807c68e38" + "archive:https://opam.ocaml.org/cache/md5/e3/e3cef220f676c4b1c16cbccb174cefe3#md5:e3cef220f676c4b1c16cbccb174cefe3", + "archive:https://gitlab.inria.fr/fpottier/menhir/-/archive/20220210/archive.tar.gz#md5:e3cef220f676c4b1c16cbccb174cefe3" ], "opam": { "name": "menhirLib", - "version": "20211125", - "path": "esy.lock/opam/menhirLib.20211125" + "version": "20220210", + "path": "esy.lock/opam/menhirLib.20220210" } }, "overrides": [], @@ -1573,33 +1573,33 @@ "@opam/dune@opam:3.6.1@662f326b" ] }, - "@opam/menhir@opam:20211125@5ae9a0c2": { - "id": "@opam/menhir@opam:20211125@5ae9a0c2", + "@opam/menhir@opam:20220210@ff5ea9a7": { + "id": "@opam/menhir@opam:20220210@ff5ea9a7", "name": "@opam/menhir", - "version": "opam:20211125", + "version": "opam:20220210", "source": { "type": "install", "source": [ - "archive:https://opam.ocaml.org/cache/md5/27/27ddfc9be183d6ae8f5440d807c68e38#md5:27ddfc9be183d6ae8f5440d807c68e38", - "archive:https://gitlab.inria.fr/fpottier/menhir/-/archive/20211125/archive.tar.gz#md5:27ddfc9be183d6ae8f5440d807c68e38" + "archive:https://opam.ocaml.org/cache/md5/e3/e3cef220f676c4b1c16cbccb174cefe3#md5:e3cef220f676c4b1c16cbccb174cefe3", + "archive:https://gitlab.inria.fr/fpottier/menhir/-/archive/20220210/archive.tar.gz#md5:e3cef220f676c4b1c16cbccb174cefe3" ], "opam": { "name": "menhir", - "version": "20211125", - "path": "esy.lock/opam/menhir.20211125" + "version": "20220210", + "path": "esy.lock/opam/menhir.20220210" } }, "overrides": [], "dependencies": [ "ocaml@github:phated/ocaml:package.json#a25997805f1ce225f23c0321e827c0d503896017@d41d8cd9", - "@opam/menhirSdk@opam:20211125@60ac0b7e", - "@opam/menhirLib@opam:20211125@cd0b955b", + "@opam/menhirSdk@opam:20220210@fe146ed3", + "@opam/menhirLib@opam:20220210@9afeb270", "@opam/dune@opam:3.6.1@662f326b", "@esy-ocaml/substs@0.0.1@d41d8cd9" ], "devDependencies": [ "ocaml@github:phated/ocaml:package.json#a25997805f1ce225f23c0321e827c0d503896017@d41d8cd9", - "@opam/menhirSdk@opam:20211125@60ac0b7e", - "@opam/menhirLib@opam:20211125@cd0b955b", + "@opam/menhirSdk@opam:20220210@fe146ed3", + "@opam/menhirLib@opam:20220210@9afeb270", "@opam/dune@opam:3.6.1@662f326b" ] }, @@ -1684,7 +1684,7 @@ "overrides": [], "dependencies": [ "ocaml@github:phated/ocaml:package.json#a25997805f1ce225f23c0321e827c0d503896017@d41d8cd9", - "@opam/topkg@opam:1.0.6@da3f4ab1", + "@opam/topkg@opam:1.0.7@7ee47d76", "@opam/ocamlfind@opam:1.9.5@c23112ba", "@opam/ocamlbuild@opam:0.14.2@c6163b28", "@opam/lwt@opam:5.6.1@2a9902ab", @@ -1730,8 +1730,8 @@ "@opam/dune@opam:3.6.1@662f326b" ] }, - "@opam/js_of_ocaml-compiler@opam:4.0.0@e10fcdb0": { - "id": "@opam/js_of_ocaml-compiler@opam:4.0.0@e10fcdb0", + "@opam/js_of_ocaml-compiler@opam:4.0.0@5d988f22": { + "id": "@opam/js_of_ocaml-compiler@opam:4.0.0@5d988f22", "name": "@opam/js_of_ocaml-compiler", "version": "opam:4.0.0", "source": { @@ -1757,9 +1757,9 @@ "@opam/yojson@opam:2.0.2@eb65f292", "@opam/ppxlib@opam:0.28.0@8c51d241", "@opam/ocamlfind@opam:1.9.5@c23112ba", - "@opam/menhirSdk@opam:20211125@60ac0b7e", - "@opam/menhirLib@opam:20211125@cd0b955b", - "@opam/menhir@opam:20211125@5ae9a0c2", + "@opam/menhirSdk@opam:20220210@fe146ed3", + "@opam/menhirLib@opam:20220210@9afeb270", + "@opam/menhir@opam:20220210@ff5ea9a7", "@opam/dune@opam:3.6.1@662f326b", "@opam/cmdliner@opam:1.1.1@03763729", "@esy-ocaml/substs@0.0.1@d41d8cd9" @@ -1768,9 +1768,9 @@ "ocaml@github:phated/ocaml:package.json#a25997805f1ce225f23c0321e827c0d503896017@d41d8cd9", "@opam/yojson@opam:2.0.2@eb65f292", "@opam/ppxlib@opam:0.28.0@8c51d241", - "@opam/menhirSdk@opam:20211125@60ac0b7e", - "@opam/menhirLib@opam:20211125@cd0b955b", - "@opam/menhir@opam:20211125@5ae9a0c2", + "@opam/menhirSdk@opam:20220210@fe146ed3", + "@opam/menhirLib@opam:20220210@9afeb270", + "@opam/menhir@opam:20220210@ff5ea9a7", "@opam/dune@opam:3.6.1@662f326b", "@opam/cmdliner@opam:1.1.1@03763729" ] @@ -2400,9 +2400,9 @@ "@opam/ppx_sexp_conv@opam:v0.15.1@0f138aac", "@opam/ppx_deriving_yojson@opam:3.7.0@167442d6", "@opam/ppx_deriving_cmdliner@github:hammerlab/ppx_deriving_cmdliner:ppx_deriving_cmdliner.opam#1f086651fe7f8dd98e371b09c6fcc4dbc6db1c7c@d41d8cd9", - "@opam/ppx_deriving@opam:5.2.1@089e5dd3", + "@opam/ppx_deriving@opam:5.2.1@2315fdd0", "@opam/ocamlgraph@opam:2.0.0@929b9eba", - "@opam/menhir@opam:20211125@5ae9a0c2", + "@opam/menhir@opam:20220210@ff5ea9a7", "@opam/fs@github:reasonml/reason-native:fs.opam#0ed854f986256e52e59aeecfa90e9af60f105b15@d41d8cd9", "@opam/fp@github:reasonml/reason-native:fp.opam#0ed854f986256e52e59aeecfa90e9af60f105b15@d41d8cd9", "@opam/dune-configurator@opam:3.6.1@966be260", @@ -2414,7 +2414,7 @@ "devDependencies": [ "@reason-native/rely@github:reasonml/reason-native:rely.json#0ed854f986256e52e59aeecfa90e9af60f105b15@d41d8cd9", "@opam/ocaml-lsp-server@opam:1.14.1@ac41cc96", - "@opam/js_of_ocaml-compiler@opam:4.0.0@e10fcdb0" + "@opam/js_of_ocaml-compiler@opam:4.0.0@5d988f22" ], "installConfig": { "pnp": false } }, @@ -2467,11 +2467,11 @@ "overrides": [], "dependencies": [ "ocaml@github:phated/ocaml:package.json#a25997805f1ce225f23c0321e827c0d503896017@d41d8cd9", - "@opam/utop@opam:2.10.0@9af1bb18", "@opam/result@opam:1.5@1c6a6533", + "@opam/utop@opam:2.11.0@bd245e47", "@opam/result@opam:1.5@1c6a6533", "@opam/ppx_derivers@opam:1.2.1@e2cbad12", "@opam/ocamlfind@opam:1.9.5@c23112ba", "@opam/merlin-extend@opam:0.6.1@7d979feb", - "@opam/menhir@opam:20211125@5ae9a0c2", + "@opam/menhir@opam:20220210@ff5ea9a7", "@opam/fix@opam:20220121@17b9a1a4", "@opam/dune@opam:3.6.1@662f326b" ], "devDependencies": [ diff --git a/compiler/esy.lock/opam/js_of_ocaml-compiler.4.0.0/opam b/compiler/esy.lock/opam/js_of_ocaml-compiler.4.0.0/opam index 47bdee230b..e880218768 100644 --- a/compiler/esy.lock/opam/js_of_ocaml-compiler.4.0.0/opam +++ b/compiler/esy.lock/opam/js_of_ocaml-compiler.4.0.0/opam @@ -28,6 +28,7 @@ conflicts: [ "ocamlfind" {< "1.5.1"} "js_of_ocaml" {< "3.0"} "base-domains" + "ocaml-option-bytecode-only" ] dev-repo: "git+https://github.com/ocsigen/js_of_ocaml.git" build: [ diff --git a/compiler/esy.lock/opam/menhir.20211125/opam b/compiler/esy.lock/opam/menhir.20220210/opam similarity index 69% rename from compiler/esy.lock/opam/menhir.20211125/opam rename to compiler/esy.lock/opam/menhir.20220210/opam index fb1eeb040f..498658b42c 100644 --- a/compiler/esy.lock/opam/menhir.20211125/opam +++ b/compiler/esy.lock/opam/menhir.20220210/opam @@ -1,3 +1,4 @@ + opam-version: "2.0" maintainer: "francois.pottier@inria.fr" authors: [ @@ -12,7 +13,7 @@ build: [ ["dune" "build" "-p" name "-j" jobs] ] depends: [ - "ocaml" {>= "4.11.0" & < "5.0"} + "ocaml" {>= "4.03.0"} "dune" {>= "2.8.0"} "menhirLib" {= version} "menhirSdk" {= version} @@ -20,9 +21,9 @@ depends: [ synopsis: "An LR(1) parser generator" url { src: - "https://gitlab.inria.fr/fpottier/menhir/-/archive/20211125/archive.tar.gz" + "https://gitlab.inria.fr/fpottier/menhir/-/archive/20220210/archive.tar.gz" checksum: [ - "md5=27ddfc9be183d6ae8f5440d807c68e38" - "sha512=6f09d3008414b652aeee1387c712420635debb1e32539b17a7865805a7d4cf6c8d7dab8d5c6d4c583145f3f2fab07524ae64a832683ad64e832b80557d7526f9" + "md5=e3cef220f676c4b1c16cbccb174cefe3" + "sha512=3063fec1d8b9fe092c8461b0689d426c7fe381a2bf3fd258dc42ceecca1719d32efbb8a18d94ada5555c38175ea352da3adbb239fdbcbcf52c3a5c85a4d9586f" ] } diff --git a/compiler/esy.lock/opam/menhirLib.20211125/opam b/compiler/esy.lock/opam/menhirLib.20220210/opam similarity index 73% rename from compiler/esy.lock/opam/menhirLib.20211125/opam rename to compiler/esy.lock/opam/menhirLib.20220210/opam index 1029e852ff..d2097ae4f3 100644 --- a/compiler/esy.lock/opam/menhirLib.20211125/opam +++ b/compiler/esy.lock/opam/menhirLib.20220210/opam @@ -1,3 +1,4 @@ + opam-version: "2.0" maintainer: "francois.pottier@inria.fr" authors: [ @@ -21,9 +22,9 @@ conflicts: [ synopsis: "Runtime support library for parsers generated by Menhir" url { src: - "https://gitlab.inria.fr/fpottier/menhir/-/archive/20211125/archive.tar.gz" + "https://gitlab.inria.fr/fpottier/menhir/-/archive/20220210/archive.tar.gz" checksum: [ - "md5=27ddfc9be183d6ae8f5440d807c68e38" - "sha512=6f09d3008414b652aeee1387c712420635debb1e32539b17a7865805a7d4cf6c8d7dab8d5c6d4c583145f3f2fab07524ae64a832683ad64e832b80557d7526f9" + "md5=e3cef220f676c4b1c16cbccb174cefe3" + "sha512=3063fec1d8b9fe092c8461b0689d426c7fe381a2bf3fd258dc42ceecca1719d32efbb8a18d94ada5555c38175ea352da3adbb239fdbcbcf52c3a5c85a4d9586f" ] } diff --git a/compiler/esy.lock/opam/menhirSdk.20211125/opam b/compiler/esy.lock/opam/menhirSdk.20220210/opam similarity index 73% rename from compiler/esy.lock/opam/menhirSdk.20211125/opam rename to compiler/esy.lock/opam/menhirSdk.20220210/opam index 8feb958d86..585d2ca330 100644 --- a/compiler/esy.lock/opam/menhirSdk.20211125/opam +++ b/compiler/esy.lock/opam/menhirSdk.20220210/opam @@ -1,3 +1,4 @@ + opam-version: "2.0" maintainer: "francois.pottier@inria.fr" authors: [ @@ -21,9 +22,9 @@ conflicts: [ synopsis: "Compile-time library for auxiliary tools related to Menhir" url { src: - "https://gitlab.inria.fr/fpottier/menhir/-/archive/20211125/archive.tar.gz" + "https://gitlab.inria.fr/fpottier/menhir/-/archive/20220210/archive.tar.gz" checksum: [ - "md5=27ddfc9be183d6ae8f5440d807c68e38" - "sha512=6f09d3008414b652aeee1387c712420635debb1e32539b17a7865805a7d4cf6c8d7dab8d5c6d4c583145f3f2fab07524ae64a832683ad64e832b80557d7526f9" + "md5=e3cef220f676c4b1c16cbccb174cefe3" + "sha512=3063fec1d8b9fe092c8461b0689d426c7fe381a2bf3fd258dc42ceecca1719d32efbb8a18d94ada5555c38175ea352da3adbb239fdbcbcf52c3a5c85a4d9586f" ] } diff --git a/compiler/esy.lock/opam/num.1.4/opam b/compiler/esy.lock/opam/num.1.4/opam index 253f84e024..0cea40c1e0 100644 --- a/compiler/esy.lock/opam/num.1.4/opam +++ b/compiler/esy.lock/opam/num.1.4/opam @@ -10,7 +10,10 @@ depends: [ "ocaml" {>= "4.06.0"} "ocamlfind" {build & >= "1.7.3"} ] -conflicts: ["base-num"] +conflicts: [ + "base-num" + "ocaml-option-bytecode-only" +] build: make install: [ ["ocamlfind" "remove" "num"] diff --git a/compiler/esy.lock/opam/ppx_deriving.5.2.1/opam b/compiler/esy.lock/opam/ppx_deriving.5.2.1/opam index ea9c3c61f4..f6197c6ffa 100644 --- a/compiler/esy.lock/opam/ppx_deriving.5.2.1/opam +++ b/compiler/esy.lock/opam/ppx_deriving.5.2.1/opam @@ -10,7 +10,7 @@ tags: [ "syntax" ] build: [ ["dune" "subst"] {dev} ["dune" "build" "-p" name "-j" jobs] - ["dune" "runtest" "-p" name "-j" jobs] {with-test} + ["dune" "runtest" "-p" name "-j" jobs] {with-test & ocaml:version < "5.0.0"} ["dune" "build" "@doc" "-p" name "-j" jobs] {with-doc} ] depends: [ diff --git a/compiler/esy.lock/opam/topkg.1.0.6/opam b/compiler/esy.lock/opam/topkg.1.0.7/opam similarity index 89% rename from compiler/esy.lock/opam/topkg.1.0.6/opam rename to compiler/esy.lock/opam/topkg.1.0.7/opam index d8c8d66195..83fc06f492 100644 --- a/compiler/esy.lock/opam/topkg.1.0.6/opam +++ b/compiler/esy.lock/opam/topkg.1.0.7/opam @@ -41,7 +41,7 @@ depends: [ build: ["ocaml" "pkg/pkg.ml" "build" "--pkg-name" name "--dev-pkg" "%{dev}%"] dev-repo: "git+https://erratique.ch/repos/topkg.git" url { - src: "https://erratique.ch/software/topkg/releases/topkg-1.0.6.tbz" + src: "https://erratique.ch/software/topkg/releases/topkg-1.0.7.tbz" checksum: - "sha512=8e34391e2f499cec332b79454a4edb36a35db6fe22437f017fd5c80ae065160dc967ac02d894a94d08d62dd476521e63733f4cadc3b9b6b314b6aa5b2b4ede78" + "sha512=09e59f1759bf4db8471f02d0aefd8db602b44932a291c05c312b1423796e7a15d1598d3c62a0cec7f083eff8e410fac09363533dc4bd2120914bb9664efea535" } \ No newline at end of file diff --git a/compiler/esy.lock/opam/utop.2.10.0/opam b/compiler/esy.lock/opam/utop.2.11.0/opam similarity index 77% rename from compiler/esy.lock/opam/utop.2.10.0/opam rename to compiler/esy.lock/opam/utop.2.11.0/opam index dbd68fd498..d9f71c3cdb 100644 --- a/compiler/esy.lock/opam/utop.2.10.0/opam +++ b/compiler/esy.lock/opam/utop.2.11.0/opam @@ -6,7 +6,7 @@ homepage: "https://github.com/ocaml-community/utop" bug-reports: "https://github.com/ocaml-community/utop/issues" doc: "https://ocaml-community.github.io/utop/" depends: [ - "ocaml" {>= "4.03.0"} + "ocaml" {>= "4.08.0"} "base-unix" "base-threads" "ocamlfind" {>= "1.7.2"} @@ -34,10 +34,10 @@ and more. It integrates with the Tuareg mode in Emacs. """ url { src: - "https://github.com/ocaml-community/utop/releases/download/2.10.0/utop-2.10.0.tbz" + "https://github.com/ocaml-community/utop/releases/download/2.11.0/utop-2.11.0.tbz" checksum: [ - "sha256=475d16a2f9ea61c602ac32673ee210c76cc768f7214987d70c069532c2782d00" - "sha512=becbbc3b6651978bc6729631ec8a17a4e93e21d85b00af499f10caa9553166378190e6f1b2495ce4b8c2b5952f315ca88923a761067de47b614ed16d0f0d77c4" + "sha256=6937c6c672913ac3b875341ac4a205c7561d01cd8ac8f47cfb35d3bc0e762170" + "sha512=ab8b96eaa7f24654a371245f14819b74de0907ed8f3b2bbd9196808dc10e536458cf95418eeacf6dfc4b7f64a8dd088ee31e2eaae3d9ebc7de7cebcada52fb84" ] } -x-commit-hash: "e56a75d2826fbe0ba3bc27a6d19fe08e02c3216d" +x-commit-hash: "595002e6f07e6a3c6abc6e94a1b2448006115f1b" diff --git a/compiler/graindoc/docblock.re b/compiler/graindoc/docblock.re index 7b44f13504..576061296e 100644 --- a/compiler/graindoc/docblock.re +++ b/compiler/graindoc/docblock.re @@ -8,7 +8,7 @@ type t = { name: string, type_sig: string, description: option(string), - attributes: list(Comments.Attribute.t), + attributes: Comments.Attribute.attributes, }; exception @@ -163,7 +163,7 @@ let for_value_description = let (args, returns) = types_for_function(~ident, vd); // This replaces the default `None` for `attr_type` on `Param` and `Returns` attributes - let apply_types: (int, Comments.Attribute.t) => Comments.Attribute.t = + let apply_types: (int, Comment_attributes.t) => Comment_attributes.t = (idx, attr) => { switch (attr) { | Param(attr) => @@ -252,7 +252,7 @@ let to_markdown = (~current_version, docblock) => { let deprecations = docblock.attributes |> List.filter(Comments.Attribute.is_deprecated) - |> List.map((attr: Comments.Attribute.t) => { + |> List.map((attr: Comment_attributes.t) => { switch (attr) { | Deprecated({attr_desc}) => attr_desc | _ => @@ -275,7 +275,7 @@ let to_markdown = (~current_version, docblock) => { let since_attr = docblock.attributes |> List.find_opt(Comments.Attribute.is_since) - |> Option.map((attr: Comments.Attribute.t) => { + |> Option.map((attr: Comment_attributes.t) => { switch (attr) { | Since({attr_version}) => output_for_since(~current_version, attr_version) @@ -286,7 +286,7 @@ let to_markdown = (~current_version, docblock) => { let history_attrs = docblock.attributes |> List.filter(Comments.Attribute.is_history) - |> List.map((attr: Comments.Attribute.t) => { + |> List.map((attr: Comment_attributes.t) => { switch (attr) { | History({attr_version, attr_desc}) => output_for_history(~current_version, attr_version, attr_desc) @@ -315,7 +315,7 @@ let to_markdown = (~current_version, docblock) => { let params = docblock.attributes |> List.filter(Comments.Attribute.is_param) - |> List.map((attr: Comments.Attribute.t) => { + |> List.map((attr: Comment_attributes.t) => { switch (attr) { | Param({attr_name, attr_type, attr_desc}) => [ Markdown.code(attr_name), @@ -336,7 +336,7 @@ let to_markdown = (~current_version, docblock) => { let returns = docblock.attributes |> List.filter(Comments.Attribute.is_returns) - |> List.map((attr: Comments.Attribute.t) => { + |> List.map((attr: Comment_attributes.t) => { switch (attr) { | Returns({attr_type, attr_desc}) => [ Option.fold(~none="", ~some=Markdown.code, attr_type), @@ -357,7 +357,7 @@ let to_markdown = (~current_version, docblock) => { docblock.attributes |> List.filter(Comments.Attribute.is_throws) |> List.fold_left( - (map, attr: Comments.Attribute.t) => { + (map, attr: Comment_attributes.t) => { switch (attr) { | Throws({attr_type: Some(attr_type), attr_desc}) => StringMap.update( @@ -400,7 +400,7 @@ let to_markdown = (~current_version, docblock) => { let examples = docblock.attributes |> List.filter(Comments.Attribute.is_example) - |> List.map((attr: Comments.Attribute.t) => { + |> List.map((attr: Comment_attributes.t) => { switch (attr) { | Example({attr_desc}) => attr_desc | _ => diff --git a/compiler/graindoc/graindoc.re b/compiler/graindoc/graindoc.re index f89478927f..1e2d88467d 100644 --- a/compiler/graindoc/graindoc.re +++ b/compiler/graindoc/graindoc.re @@ -100,7 +100,7 @@ let generate_docs = let deprecations = attrs |> List.filter(Comments.Attribute.is_deprecated) - |> List.map((attr: Comments.Attribute.t) => { + |> List.map((attr: Comment_attributes.t) => { switch (attr) { | Deprecated({attr_desc}) => attr_desc | _ => @@ -130,7 +130,7 @@ let generate_docs = let since_attr = attrs |> List.find_opt(Comments.Attribute.is_since) - |> Option.map((attr: Comments.Attribute.t) => { + |> Option.map((attr: Comment_attributes.t) => { switch (attr) { | Since({attr_version}) => Docblock.output_for_since(~current_version, attr_version) @@ -141,7 +141,7 @@ let generate_docs = let history_attrs = attrs |> List.filter(Comments.Attribute.is_history) - |> List.map((attr: Comments.Attribute.t) => { + |> List.map((attr: Comment_attributes.t) => { switch (attr) { | History({attr_version, attr_desc}) => Docblock.output_for_history( @@ -168,7 +168,7 @@ let generate_docs = let example_attrs = attrs |> List.filter(Comments.Attribute.is_example); if (List.length(example_attrs) > 0) { List.iter( - (attr: Comments.Attribute.t) => { + (attr: Comment_attributes.t) => { switch (attr) { | Example({attr_desc}) => Buffer.add_string(buf, Markdown.code_block(attr_desc)) @@ -218,7 +218,7 @@ let generate_docs = next_section_start_line, ); List.iter( - (attr: Comments.Attribute.t) => { + (attr: Comment_attributes.t) => { switch (attr) { | Section({attr_name, attr_desc}) => Buffer.add_string(buf, Markdown.heading(~level=2, attr_name)); diff --git a/compiler/package.json b/compiler/package.json index 2c900bfa20..5a84c2673c 100644 --- a/compiler/package.json +++ b/compiler/package.json @@ -31,6 +31,11 @@ "parser:list-errors": "esy b menhir src/parsing/parser.mly --unused-tokens --list-errors > src/parsing/parser.messages.generated", "parser:update-errors": "esy b menhir src/parsing/parser.mly --unused-tokens --update-errors src/parsing/parser.messages > src/parsing/parser.messages.generated && cp src/parsing/parser.messages.generated src/parsing/parser.messages", "parser:check-errors": "npm run parser:list-errors && esy b menhir src/parsing/parser.mly --unused-tokens --compare-errors src/parsing/parser.messages.generated --compare-errors src/parsing/parser.messages", + "graindoc-parser:interpret": "esy b menhir src/diagnostics/graindoc_parser.mly --unused-tokens --interpret", + "graindoc-parser:interpret-error": "esy b menhir src/diagnostics/graindoc_parser.mly --unused-tokens --interpret-error", + "graindoc-parser:list-errors": "esy b menhir src/diagnostics/graindoc_parser.mly --unused-tokens --list-errors > src/diagnostics/graindoc_parser.messages.generated", + "graindoc-parser:update-errors": "esy b menhir src/diagnostics/graindoc_parser.mly --unused-tokens --update-errors src/diagnostics/graindoc_parser.messages > src/diagnostics/graindoc_parser.messages.generated && cp src/diagnostics/graindoc_parser.messages.generated src/diagnostics/graindoc_parser.messages", + "graindoc-parser:check-errors": "npm run graindoc-parser:list-errors && esy b menhir src/diagnostics/graindoc_parser.mly --unused-tokens --compare-errors src/diagnostics/graindoc_parser.messages.generated --compare-errors src/diagnostics/graindoc_parser.messages", "import-dependencies": "esy import-dependencies _export", "export-dependencies": "esy export-dependencies", "build-dependencies": "esy build-dependencies" diff --git a/compiler/src/diagnostics/comment_attributes.re b/compiler/src/diagnostics/comment_attributes.re new file mode 100644 index 0000000000..b56ae56307 --- /dev/null +++ b/compiler/src/diagnostics/comment_attributes.re @@ -0,0 +1,37 @@ +exception InvalidAttribute(string); +exception MalformedAttribute(string, string); + +type attr_name = string; +type attr_desc = string; +// The `attr_type` always starts as `None` and is applied later by something like Graindoc +type attr_type = option(string); +type attr_version = string; + +type t = + | Param({ + attr_name, + attr_type, + attr_desc, + }) + | Returns({ + attr_desc, + attr_type, + }) + // Currently only accepts single-line examples + | Example({attr_desc}) + | Section({ + attr_name, + attr_desc, + }) + | Deprecated({attr_desc}) + | Since({attr_version}) + | History({ + attr_version, + attr_desc, + }) + | Throws({ + attr_type, + attr_desc, + }); + +type parsed_graindoc = (option(string), list(t)); diff --git a/compiler/src/diagnostics/comments.re b/compiler/src/diagnostics/comments.re index e5be786d5e..c28153e825 100644 --- a/compiler/src/diagnostics/comments.re +++ b/compiler/src/diagnostics/comments.re @@ -4,253 +4,121 @@ open Grain_utils; // Attributes in a comment are prefixed with `@` symbol, such as `@param` module Attribute = { - exception InvalidAttribute(string); - exception MalformedAttribute(string, string); - - type attr_name = string; - type attr_desc = string; - // The `attr_type` always starts as `None` and is applied later by something like Graindoc - type attr_type = option(string); - type attr_version = string; - - type t = - | Param({ - attr_name, - attr_type, - attr_desc, - }) - | Returns({ - attr_desc, - attr_type, - }) - // Currently only accepts single-line examples - | Example({attr_desc}) - | Section({ - attr_name, - attr_desc, - }) - | Deprecated({attr_desc}) - | Since({attr_version}) - | History({ - attr_version, - attr_desc, - }) - | Throws({ - attr_type, - attr_desc, - }); - - let parse_param = (~attr, content) => { - let re = Str.regexp({|^\([^:]+\):[ ]+\(.+\)$|}); - if (Str.string_match(re, content, 0)) { - let attr_name = Str.matched_group(1, content); - let attr_desc = Str.matched_group(2, content); - Param({attr_name, attr_desc, attr_type: None}); - } else { - raise( - MalformedAttribute( - attr, - "@param ParamName: Description of param value", - ), - ); - }; - }; + open Comment_attributes; - let parse_returns = (~attr, content) => { - let re = Str.regexp({|^\(.+\)$|}); - if (Str.string_match(re, content, 0)) { - let attr_desc = Str.matched_group(1, content); - Returns({attr_desc, attr_type: None}); - } else { - raise( - MalformedAttribute(attr, "@returns Description of return value"), - ); - }; - }; + type attributes = list(t); - let parse_example = (~attr, content) => { - let re = Str.regexp({|^\(.+\)$|}); - if (Str.string_match(re, content, 0)) { - let attr_desc = Str.matched_group(1, content); - Example({attr_desc: attr_desc}); - } else { - raise(MalformedAttribute(attr, "@example single-line code example")); - }; - }; + type error = + | GraindocSyntaxError(string, string); - let parse_section = (~attr, content) => { - let re = Str.regexp({|^\([^:]+\):[ ]+\(.+\)$|}); - if (Str.string_match(re, content, 0)) { - let attr_name = Str.matched_group(1, content); - let attr_desc = Str.matched_group(2, content); - Section({attr_name, attr_desc}); - } else { - raise( - MalformedAttribute( - attr, - "@section SectionName: Description of section", - ), - ); + exception Error(Location.t, error); + + let report_error = (ppf, err) => + switch (err) { + | GraindocSyntaxError(msg, where) => + Format.fprintf(ppf, "Graindoc syntax error %s: %s", where, msg) }; - }; - let parse_deprecated = (~attr, content) => { - let re = Str.regexp({|^\(.+\)$|}); - if (Str.string_match(re, content, 0)) { - let attr_desc = Str.matched_group(1, content); - Deprecated({attr_desc: attr_desc}); - } else { - raise( - MalformedAttribute(attr, "@deprecated Description of deprecation"), + let () = + Location.register_error_of_exn( + fun + | Error(loc, err) => + Some(Location.error_of_printer(loc, report_error, err)) + | _ => None, + ); + + let extract = (comment_source, comment_content, comment_loc) => { + // strip trailing */ to allow block comments in examples + let modified_source = + String.trim( + Grain_utils.String_utils.slice(~first=0, ~last=-2, comment_source), ); - }; - }; + let lexbuf = Sedlexing.Utf8.from_string(modified_source); - let parse_since = (~attr, content) => { - let re = Str.regexp({|^v?\([0-9]+\.[0-9]+\.[0-9]+\)$|}); - if (Str.string_match(re, content, 0)) { - let attr_version = Str.matched_group(1, content); - Since({attr_version: attr_version}); - } else { - raise(MalformedAttribute(attr, "@since vX.Y.Z")); - }; - }; + Sedlexing.set_position(lexbuf, comment_loc.Location.loc_start); + Sedlexing.set_filename(lexbuf, comment_loc.Location.loc_start.pos_fname); - let parse_history = (~attr, content) => { - let re = Str.regexp({|^v?\([0-9]+\.[0-9]+\.[0-9]+\):[ ]+\(.+\)$|}); - if (Str.string_match(re, content, 0)) { - let attr_version = Str.matched_group(1, content); - let attr_desc = Str.matched_group(2, content); - History({attr_version, attr_desc}); - } else { - raise( - MalformedAttribute(attr, "@history vX.Y.Z: Description of history"), + let parse_graindoc = + MenhirLib.Convert.Simplified.traditional2revised( + Graindoc_parser.graindoc, + ); + let (buffer, graindoc_lexer) = + MenhirLib.ErrorReports.wrap_supplier( + Sedlexing.with_tokenizer(Graindoc_lexer.make_lexer(), lexbuf), ); - }; - }; - let parse_throws = (~attr, content) => { - let re = Str.regexp({|^\([^:]+\):[ ]+\(.+\)$|}); - if (Str.string_match(re, content, 0)) { - let attr_type = Str.matched_group(1, content); - let attr_desc = Str.matched_group(2, content); - Throws({attr_type: Some(attr_type), attr_desc}); - } else { + try(parse_graindoc(graindoc_lexer)) { + | Graindoc_parser.Error(state) => + open Lexing; + let chunk = ((start_p, end_p)) => + String_utils.Utf8.sub( + comment_source, + start_p.pos_cnum - comment_loc.loc_start.pos_cnum, + end_p.pos_cnum - start_p.pos_cnum, + ); + let where = MenhirLib.ErrorReports.show(chunk, buffer); raise( - MalformedAttribute( - attr, - "@throws ExceptionType: Explanation of exceptional case", + Error( + Location.curr(lexbuf), + GraindocSyntaxError( + Graindoc_parser_messages.message(state), + where, + ), ), ); }; }; - let extract = comment => { - let attrs = ref([]); - let attr_line_re = Str.regexp({|^@\([a-zA-Z_]+\)\b\(.*\)$|}); - - // TODO: We should probably transition to a lexer, instead of 2-passes of RegExp - let out = - Str.global_substitute( - attr_line_re, - _ => { - let attr = Str.matched_group(1, comment); - // Trim this since we only match word boundaries now - let content = String.trim(Str.matched_group(2, comment)); - switch (attr) { - | "param" => - let param_attr = parse_param(~attr, content); - attrs := [param_attr, ...attrs^]; - | "returns" => - let returns_attr = parse_returns(~attr, content); - attrs := [returns_attr, ...attrs^]; - | "example" => - let example_attr = parse_example(~attr, content); - attrs := [example_attr, ...attrs^]; - | "section" => - let section_attr = parse_section(~attr, content); - attrs := [section_attr, ...attrs^]; - | "deprecated" => - let deprecated_attr = parse_deprecated(~attr, content); - attrs := [deprecated_attr, ...attrs^]; - | "since" => - let since_attr = parse_since(~attr, content); - attrs := [since_attr, ...attrs^]; - | "history" => - let history_attr = parse_history(~attr, content); - attrs := [history_attr, ...attrs^]; - | "throws" => - let throws_attr = parse_throws(~attr, content); - attrs := [throws_attr, ...attrs^]; - | _ => raise(InvalidAttribute(attr)) - }; - - // Replace it with nothing - ""; - }, - comment, - ); - - let desc = String.trim(out); - let desc_opt = - if (desc != "") { - Some(desc); - } else { - None; - }; - (desc_opt, List.rev(attrs^)); - }; - - let is_param = (attr: t) => { + let is_param = attr => { switch (attr) { | Param(_) => true | _ => false }; }; - let is_returns = (attr: t) => { + let is_returns = attr => { switch (attr) { | Returns(_) => true | _ => false }; }; - let is_example = (attr: t) => { + let is_example = attr => { switch (attr) { | Example(_) => true | _ => false }; }; - let is_section = (attr: t) => { + let is_section = attr => { switch (attr) { | Section(_) => true | _ => false }; }; - let is_deprecated = (attr: t) => { + let is_deprecated = attr => { switch (attr) { | Deprecated(_) => true | _ => false }; }; - let is_since = (attr: t) => { + let is_since = attr => { switch (attr) { | Since(_) => true | _ => false }; }; - let is_history = (attr: t) => { + let is_history = attr => { switch (attr) { | History(_) => true | _ => false }; }; - let is_throws = (attr: t) => { + let is_throws = attr => { switch (attr) { | Throws(_) => true | _ => false @@ -281,7 +149,7 @@ module Attribute = { }; type description = option(string); -type attributes = list(Attribute.t); +type attributes = Attribute.attributes; module type OrderedComments = { type comment = (Typedtree.comment, description, attributes); @@ -321,8 +189,9 @@ module MakeOrderedComments = | Block({cmt_loc, _}) => let data = (comment, None, []); (cmt_loc.loc_start.pos_lnum, cmt_loc.loc_end.pos_lnum, data); - | Doc({cmt_loc, cmt_content}) => - let (description, attributes) = Attribute.extract(cmt_content); + | Doc({cmt_source, cmt_content, cmt_loc}) => + let (description, attributes) = + Attribute.extract(cmt_source, cmt_content, cmt_loc); let data = (comment, description, attributes); (cmt_loc.loc_start.pos_lnum, cmt_loc.loc_end.pos_lnum, data); }; diff --git a/compiler/src/diagnostics/dune b/compiler/src/diagnostics/dune index d8c8eda563..8c9fe95dbc 100644 --- a/compiler/src/diagnostics/dune +++ b/compiler/src/diagnostics/dune @@ -1,8 +1,19 @@ +(menhir + (modules graindoc_parser) + (flags --explain --unused-tokens --exn-carries-state --strict)) + +(rule + (action + (with-stdout-to + graindoc_parser_messages.ml + (run menhir %{dep:graindoc_parser.mly} --compile-errors + %{dep:graindoc_parser.messages} --unused-tokens)))) + (library (name grain_diagnostics) (public_name grain_diagnostics) (synopsis "Diagnostic modules for Grain compiler") (libraries compiler-libs.common grain_utils grain_typed str - ppx_deriving_yojson.runtime yojson) + ppx_deriving_yojson.runtime yojson menhirLib sexplib) (preprocess - (pps ppx_deriving_yojson))) + (pps ppx_deriving_yojson sedlex.ppx))) diff --git a/compiler/src/diagnostics/graindoc_lexer.re b/compiler/src/diagnostics/graindoc_lexer.re new file mode 100644 index 0000000000..0429fdc4ff --- /dev/null +++ b/compiler/src/diagnostics/graindoc_lexer.re @@ -0,0 +1,213 @@ +open Grain_parsing; +open Graindoc_parser; + +let lexbuf_loc = lexbuf => { + let (loc_start, loc_end) = Sedlexing.lexing_positions(lexbuf); + Location.{loc_start, loc_end, loc_ghost: false}; +}; + +let ident = [%sedlex.regexp? (xid_start | '_', Star(xid_continue))]; +let semver = [%sedlex.regexp? + ( + Opt('v'), + Plus('0' .. '9'), + '.', + Plus('0' .. '9'), + '.', + Plus('0' .. '9'), + Opt(( + '-', + Star('0' .. '9' | 'A' .. 'z' | '-' | '.'), + Opt(('+', Star('0' .. '9' | 'A' .. 'z' | '-'))), + )), + ) +]; + +let normalize_semver = semver => + if (semver.[0] == 'v') { + Grain_utils.String_utils.slice( + ~first=1, + ~last=String.length(semver), + semver, + ); + } else { + semver; + }; + +// HORIZONTAL TABULATION +// VERTICAL TABULATION +// SPACE +// LEFT-TO-RIGHT MARK +// RIGHT-TO-LEFT MARK +let blank = [%sedlex.regexp? 0x09 | 0x0B | 0x20 | 0x200E | 0x200F]; + +// LINE FEED +// FORM FEED +// CARRIAGE RETURN +// NEXT LINE +// LINE SEPARATOR +// PARAGRAPH SEPARATOR +let newline = [%sedlex.regexp? 0x0A | 0x0C | 0x0D | 0x85 | 0x2028 | 0x2029]; + +// A colon eats whitespace after it +let colon = [%sedlex.regexp? (':', Star(blank))]; + +// A asterisk eats whitespace before it and up to 1 after it +let asterisk = [%sedlex.regexp? (Star(blank), '*', Opt(blank))]; + +type lexer_state = {mutable lexer_mode} +and lexer_mode = + | Start + | Default + | Param + | Section + | Since + | History + | Throws + | FreeTextAttribute; + +let rec token = (state, lexbuf) => { + switch (state.lexer_mode) { + | Start => start(state, lexbuf) + | Default => default(state, lexbuf) + | Param => param(state, lexbuf) + | Section => section(state, lexbuf) + | Since => since(state, lexbuf) + | History => history(state, lexbuf) + | Throws => throws(state, lexbuf) + | FreeTextAttribute => free_text_attribute(state, lexbuf) + }; +} + +and start = (state, lexbuf) => { + switch%sedlex (lexbuf) { + | ("/**", Star(blank)) => + state.lexer_mode = Default; + default(state, lexbuf); + | _ => + state.lexer_mode = Default; + default(state, lexbuf); + }; +} + +and default = (state, lexbuf) => { + switch%sedlex (lexbuf) { + | asterisk => default(state, lexbuf) + | "@param" => + state.lexer_mode = Param; + PARAM; + | "@returns" => + state.lexer_mode = FreeTextAttribute; + RETURNS; + | "@example" => + state.lexer_mode = FreeTextAttribute; + EXAMPLE; + | "@section" => + state.lexer_mode = Section; + SECTION; + | "@deprecated" => + state.lexer_mode = FreeTextAttribute; + DEPRECATED; + | "@since" => + state.lexer_mode = Since; + SINCE; + | "@history" => + state.lexer_mode = History; + HISTORY; + | "@throws" => + state.lexer_mode = Throws; + THROWS; + | newline => EOL + | eof => EOF + | _ => text(state, lexbuf) + }; +} + +and free_text_attribute = (state, lexbuf) => { + switch%sedlex (lexbuf) { + | blank => free_text_attribute(state, lexbuf) + | _ => + state.lexer_mode = Default; + default(state, lexbuf); + }; +} + +and param = (state, lexbuf) => { + switch%sedlex (lexbuf) { + | blank => param(state, lexbuf) + | ident => IDENT(Sedlexing.Utf8.lexeme(lexbuf)) + | colon => + state.lexer_mode = Default; + COLON; + | _ => + state.lexer_mode = Default; + default(state, lexbuf); + }; +} + +and section = (state, lexbuf) => { + switch%sedlex (lexbuf) { + | blank => section(state, lexbuf) + | (Compl(blank | newline | ':' | eof), Star(Compl(newline | ':' | eof))) => + TEXT(Sedlexing.Utf8.lexeme(lexbuf)) + | colon => + state.lexer_mode = Default; + COLON; + | _ => + state.lexer_mode = Default; + default(state, lexbuf); + }; +} + +and since = (state, lexbuf) => { + switch%sedlex (lexbuf) { + | blank => since(state, lexbuf) + | semver => + state.lexer_mode = Default; + SEMVER(normalize_semver(Sedlexing.Utf8.lexeme(lexbuf))); + | _ => + state.lexer_mode = Default; + default(state, lexbuf); + }; +} + +and history = (state, lexbuf) => { + switch%sedlex (lexbuf) { + | blank => history(state, lexbuf) + | semver => SEMVER(normalize_semver(Sedlexing.Utf8.lexeme(lexbuf))) + | colon => + state.lexer_mode = Default; + COLON; + | _ => + state.lexer_mode = Default; + default(state, lexbuf); + }; +} + +and throws = (state, lexbuf) => { + switch%sedlex (lexbuf) { + | blank => throws(state, lexbuf) + | (Compl(blank | newline | ':' | eof), Star(Compl(newline | ':' | eof))) => + CONSTRUCTOR(Sedlexing.Utf8.lexeme(lexbuf)) + | colon => + state.lexer_mode = Default; + COLON; + | _ => + state.lexer_mode = Default; + default(state, lexbuf); + }; +} + +and text = (state, lexbuf) => { + switch%sedlex (lexbuf) { + | Plus(Compl(newline | eof)) => TEXT(Sedlexing.Utf8.lexeme(lexbuf)) + | _ => + state.lexer_mode = Default; + default(state, lexbuf); + }; +}; + +let make_lexer = () => { + let state = {lexer_mode: Start}; + lexbuf => token(state, lexbuf); +}; diff --git a/compiler/src/diagnostics/graindoc_parser.messages b/compiler/src/diagnostics/graindoc_parser.messages new file mode 100644 index 0000000000..3dea2af3ed --- /dev/null +++ b/compiler/src/diagnostics/graindoc_parser.messages @@ -0,0 +1,278 @@ +graindoc: SEMVER +## +## Ends in an error in state: 0. +## +## graindoc' -> . graindoc [ # ] +## +## The known suffix of the stack is as follows: +## +## + +Expected a description or Graindoc attribute. + +graindoc: TEXT TEXT +## +## Ends in an error in state: 4. +## +## description -> multiline_text_help . [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOF DEPRECATED ] +## description -> multiline_text_help . eols [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOF DEPRECATED ] +## multiline_text_help -> multiline_text_help . EOL TEXT [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## multiline_text_help -> multiline_text_help . eols EOL TEXT [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## +## The known suffix of the stack is as follows: +## multiline_text_help +## +graindoc: SINCE SEMVER TEXT +## +## Ends in an error in state: 42. +## +## attributes_help -> attributes_help . option(eols) attribute [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## graindoc -> option(eols) description attributes_help . EOF [ # ] +## graindoc -> option(eols) description attributes_help . eols EOF [ # ] +## +## The known suffix of the stack is as follows: +## option(eols) description attributes_help +## + +Expected a newline character. + +graindoc: TEXT EOL SEMVER +## +## Ends in an error in state: 5. +## +## eols -> EOL . [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## multiline_text_help -> multiline_text_help EOL . TEXT [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## +## The known suffix of the stack is as follows: +## multiline_text_help EOL +## +graindoc: TEXT EOL EOL SEMVER +## +## Ends in an error in state: 8. +## +## eols -> eols EOL . [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## multiline_text_help -> multiline_text_help eols EOL . TEXT [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## +## The known suffix of the stack is as follows: +## multiline_text_help eols EOL +## +graindoc: DEPRECATED TEXT TEXT +## +## Ends in an error in state: 14. +## +## attribute_text -> multiline_text_help . [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## attribute_text -> multiline_text_help . eols [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## multiline_text_help -> multiline_text_help . EOL TEXT [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## multiline_text_help -> multiline_text_help . eols EOL TEXT [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## +## The known suffix of the stack is as follows: +## multiline_text_help +## +graindoc: DEPRECATED EOL TEXT TEXT +## +## Ends in an error in state: 18. +## +## attribute_text -> eols multiline_text_help . [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## attribute_text -> eols multiline_text_help . eols [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## multiline_text_help -> multiline_text_help . EOL TEXT [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## multiline_text_help -> multiline_text_help . eols EOL TEXT [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## +## The known suffix of the stack is as follows: +## eols multiline_text_help +## +graindoc: SINCE SEMVER EOL TEXT +## +## Ends in an error in state: 46. +## +## eols -> eols . EOL [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## graindoc -> option(eols) description attributes_help eols . EOF [ # ] +## option(eols) -> eols . [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE DEPRECATED ] +## +## The known suffix of the stack is as follows: +## option(eols) description attributes_help eols +## +graindoc: EOL SEMVER +## +## Ends in an error in state: 50. +## +## eols -> eols . EOL [ THROWS TEXT SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## option(eols) -> eols . [ THROWS TEXT SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOF DEPRECATED ] +## +## The known suffix of the stack is as follows: +## eols +## + +Expected a Graindoc attribute, such as `@param`, `@returns`, or `@example`. + +graindoc: THROWS THROWS +## +## Ends in an error in state: 11. +## +## attribute -> THROWS . CONSTRUCTOR COLON attribute_text [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## +## The known suffix of the stack is as follows: +## THROWS +## + +Expected an exception constructor. + +graindoc: THROWS CONSTRUCTOR THROWS +## +## Ends in an error in state: 12. +## +## attribute -> THROWS CONSTRUCTOR . COLON attribute_text [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## +## The known suffix of the stack is as follows: +## THROWS CONSTRUCTOR +## +graindoc: SECTION TEXT THROWS +## +## Ends in an error in state: 24. +## +## attribute -> SECTION TEXT . COLON attribute_text [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## +## The known suffix of the stack is as follows: +## SECTION TEXT +## +graindoc: PARAM IDENT THROWS +## +## Ends in an error in state: 30. +## +## attribute -> PARAM IDENT . COLON attribute_text [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## +## The known suffix of the stack is as follows: +## PARAM IDENT +## +graindoc: HISTORY SEMVER THROWS +## +## Ends in an error in state: 34. +## +## attribute -> HISTORY SEMVER . COLON attribute_text [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## +## The known suffix of the stack is as follows: +## HISTORY SEMVER +## + +Expected a colon. + +graindoc: THROWS CONSTRUCTOR COLON THROWS +## +## Ends in an error in state: 13. +## +## attribute -> THROWS CONSTRUCTOR COLON . attribute_text [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## +## The known suffix of the stack is as follows: +## THROWS CONSTRUCTOR COLON +## +graindoc: DEPRECATED EOL THROWS +## +## Ends in an error in state: 16. +## +## attribute_text -> eols . multiline_text_help [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## attribute_text -> eols . multiline_text_help eols [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## eols -> eols . EOL [ TEXT EOL ] +## +## The known suffix of the stack is as follows: +## eols +## +graindoc: SECTION TEXT COLON THROWS +## +## Ends in an error in state: 25. +## +## attribute -> SECTION TEXT COLON . attribute_text [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## +## The known suffix of the stack is as follows: +## SECTION TEXT COLON +## +graindoc: RETURNS THROWS +## +## Ends in an error in state: 27. +## +## attribute -> RETURNS . attribute_text [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## +## The known suffix of the stack is as follows: +## RETURNS +## +graindoc: PARAM IDENT COLON THROWS +## +## Ends in an error in state: 31. +## +## attribute -> PARAM IDENT COLON . attribute_text [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## +## The known suffix of the stack is as follows: +## PARAM IDENT COLON +## +graindoc: HISTORY SEMVER COLON THROWS +## +## Ends in an error in state: 35. +## +## attribute -> HISTORY SEMVER COLON . attribute_text [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## +## The known suffix of the stack is as follows: +## HISTORY SEMVER COLON +## +graindoc: EXAMPLE THROWS +## +## Ends in an error in state: 37. +## +## attribute -> EXAMPLE . attribute_text [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## +## The known suffix of the stack is as follows: +## EXAMPLE +## +graindoc: DEPRECATED THROWS +## +## Ends in an error in state: 40. +## +## attribute -> DEPRECATED . attribute_text [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## +## The known suffix of the stack is as follows: +## DEPRECATED +## + +Expected a description. + +graindoc: SINCE THROWS +## +## Ends in an error in state: 21. +## +## attribute -> SINCE . SEMVER [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## +## The known suffix of the stack is as follows: +## SINCE +## +graindoc: HISTORY THROWS +## +## Ends in an error in state: 33. +## +## attribute -> HISTORY . SEMVER COLON attribute_text [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## +## The known suffix of the stack is as follows: +## HISTORY +## + +Expected a version number in Semantic Versioning format, e.g. `v1.2.3`. + +graindoc: SECTION THROWS +## +## Ends in an error in state: 23. +## +## attribute -> SECTION . TEXT COLON attribute_text [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## +## The known suffix of the stack is as follows: +## SECTION +## + +Expected a section title. + +graindoc: PARAM THROWS +## +## Ends in an error in state: 29. +## +## attribute -> PARAM . IDENT COLON attribute_text [ THROWS SINCE SECTION RETURNS PARAM HISTORY EXAMPLE EOL EOF DEPRECATED ] +## +## The known suffix of the stack is as follows: +## PARAM +## + +Expected a parameter name. diff --git a/compiler/src/diagnostics/graindoc_parser.mly b/compiler/src/diagnostics/graindoc_parser.mly new file mode 100644 index 0000000000..a80cc1c1a1 --- /dev/null +++ b/compiler/src/diagnostics/graindoc_parser.mly @@ -0,0 +1,48 @@ +%token PARAM SECTION SINCE HISTORY THROWS RETURNS EXAMPLE DEPRECATED COLON EOL EOF +%token TEXT IDENT SEMVER CONSTRUCTOR + +%right EOL + +%start graindoc + +%% + +eols: + | EOL + | eols EOL {} + +multiline_text_help: + | TEXT { [$1] } + | multiline_text_help EOL TEXT { $3 :: "\n" :: $1 } + | multiline_text_help eols EOL TEXT { $4 :: "\n\n" :: $1 } + +%inline multiline_text: + | rev(multiline_text_help) { String.concat "" $1 } + +description: + | { None } + | multiline_text ioption(eols) { Some($1) } + +attribute_text: + | ioption(eols) multiline_text ioption(eols) %prec EOL { $2 } + +attribute: + | PARAM IDENT COLON attribute_text { Param({ attr_name=$2; attr_type=None; attr_desc=$4 }) } + | RETURNS attribute_text { Returns({ attr_desc=$2; attr_type=None }) } + | EXAMPLE attribute_text { Example({attr_desc=$2}) } + | SECTION TEXT COLON attribute_text { Section({ attr_name=$2; attr_desc=$4; }) } + | DEPRECATED attribute_text { Deprecated({attr_desc=$2}) } + | SINCE SEMVER { Since({attr_version=$2}) } + | HISTORY SEMVER COLON attribute_text { History({ attr_version=$2; attr_desc=$4; }) } + | THROWS CONSTRUCTOR COLON attribute_text { Throws({ attr_type=Some $2; attr_desc=$4; }); } + +attributes_help: + | attribute { [$1] } + | attributes_help option(eols) attribute { $3 :: $1 } + +%inline attributes: + | { [] } + | rev(attributes_help) ioption(eols) { $1 } + +graindoc: + | option(eols) description attributes EOF { ($2, $3) }